/*
 * Copyright (C) 2010 Google Inc. All rights reserved.
 * Copyright (C) 2012 Apple Inc.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions are
 * met:
 *
 *     * Redistributions of source code must retain the above copyright
 * notice, this list of conditions and the following disclaimer.
 *     * Redistributions in binary form must reproduce the above
 * copyright notice, this list of conditions and the following disclaimer
 * in the documentation and/or other materials provided with the
 * distribution.
 *     * Neither the name of Google Inc. nor the names of its
 * contributors may be used to endorse or promote products derived from
 * this software without specific prior written permission.
 *
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
 * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 */

#import "config.h"

#if !PLATFORM(IOS_FAMILY)

#import <AppKit/AppKit.h>
#import <ApplicationServices/ApplicationServices.h>
#import <IOKit/pwr_mgt/IOPMLib.h>
#import <getopt.h>
#import <signal.h>
#import <stdio.h>
#import <stdlib.h>

#if USE(APPLE_INTERNAL_SDK)

#import <ColorSync/ColorSyncPriv.h>

#else

CFUUIDRef CGDisplayCreateUUIDFromDisplayID(uint32_t displayID);

#endif

// This is a simple helper app that changes the color profile of the main display
// to GenericRGB and back when done. This program is managed by the layout
// test script, so it can do the job for multiple DumpRenderTree while they are
// running layout tests.

static int installColorProfile = false;
static int preferIntegratedGPU = false;
static uint32_t assertionIDForDisplaySleep = 0;
static uint32_t assertionIDForSystemSleep = 0;

static NSMutableDictionary *originalColorProfileURLs(void)
{
    static NSMutableDictionary *sharedInstance;
    if (!sharedInstance)
        sharedInstance = [[NSMutableDictionary alloc] init];
    return sharedInstance;
}

static NSURL *colorProfileURLForDisplay(NSString *displayUUIDString)
{
    CFUUIDRef uuid = CFUUIDCreateFromString(kCFAllocatorDefault, (CFStringRef)displayUUIDString);
    CFDictionaryRef deviceInfo = ColorSyncDeviceCopyDeviceInfo(kColorSyncDisplayDeviceClass, uuid);
    CFRelease(uuid);
    if (!deviceInfo) {
        NSLog(@"Could not retrieve device info from ColorSync; not setting main display's color profile.");
        return nil;
    }

    CFStringRef profileID = CFSTR("1");
    CFURLRef profileURL = nil;

    CFDictionaryRef factoryProfiles = (CFDictionaryRef)CFDictionaryGetValue(deviceInfo, kColorSyncFactoryProfiles);
    if (factoryProfiles)
        profileID = (CFStringRef)CFDictionaryGetValue(factoryProfiles, kColorSyncDeviceDefaultProfileID);

    CFDictionaryRef customProfiles = (CFDictionaryRef)CFDictionaryGetValue(deviceInfo, kColorSyncCustomProfiles);
    if (customProfiles)
        profileURL = (CFURLRef)CFDictionaryGetValue(customProfiles, profileID);
    if (!profileURL && factoryProfiles) {
        CFDictionaryRef profile = (CFDictionaryRef)CFDictionaryGetValue(factoryProfiles, profileID);
        if (profile)
            profileURL = (CFURLRef)CFDictionaryGetValue(profile, kColorSyncDeviceProfileURL);
    }
    
    if (!profileURL) {
        NSLog(@"Could not determine current color profile, so it will not be reset after running the tests.");
        CFRelease(deviceInfo);
        return nil;
    }

    NSURL *url = CFBridgingRelease(CFRetain(profileURL));
    CFRelease(deviceInfo);
    return url;
}

static NSArray *displayUUIDStrings(void)
{
    NSMutableArray *result = [NSMutableArray array];

    enum { maxDisplayCount = 10 };
    CGDirectDisplayID displayIDs[maxDisplayCount] = { 0 };
    uint32_t displayCount = 0;
    
    CGError err = CGGetOnlineDisplayList(maxDisplayCount, displayIDs, &displayCount);
    if (err != kCGErrorSuccess) {
        NSLog(@"Error %d getting online display list; not setting display color profile.", err);
        return nil;
    }

    if (!displayCount) {
        NSLog(@"No display attached to system; not setting display color profile.");
        return nil;
    }

    for (uint32_t i = 0; i < displayCount; ++i) {
        CFUUIDRef displayUUIDRef = CGDisplayCreateUUIDFromDisplayID(displayIDs[i]);
        [result addObject:(NSString *)CFBridgingRelease(CFUUIDCreateString(kCFAllocatorDefault, displayUUIDRef))];
        CFRelease(displayUUIDRef);
    }
    
    return result;
}

static void saveDisplayColorProfiles(NSArray *displayUUIDStrings)
{
    NSMutableDictionary *userColorProfiles = originalColorProfileURLs();

    for (NSString *UUIDString in displayUUIDStrings) {
        if ([userColorProfiles objectForKey:UUIDString])
            continue;
        
        NSURL *colorProfileURL = colorProfileURLForDisplay(UUIDString);
        if (!colorProfileURL)
            continue;

        [userColorProfiles setObject:colorProfileURL forKey:UUIDString];
    }
}

static void setDisplayColorProfile(NSString *displayUUIDString, NSURL *colorProfileURL)
{
    NSDictionary *profileInfo = @{
        (__bridge NSString *)kColorSyncDeviceDefaultProfileID : colorProfileURL
    };

    CFUUIDRef uuid = CFUUIDCreateFromString(kCFAllocatorDefault, (CFStringRef)displayUUIDString);
    BOOL success = ColorSyncDeviceSetCustomProfiles(kColorSyncDisplayDeviceClass, uuid, (CFDictionaryRef)profileInfo);
    if (!success)
        NSLog(@"Failed to set color profile for display %@! Many pixel tests may fail as a result.", displayUUIDString);
    CFRelease(uuid);
}

static void restoreDisplayColorProfiles(NSArray *displayUUIDStrings)
{
    NSMutableDictionary* userColorProfiles = originalColorProfileURLs();

    for (NSString *UUIDString in displayUUIDStrings) {
        NSURL *profileURL = [userColorProfiles objectForKey:UUIDString];
        if (!profileURL)
            continue;
        
        setDisplayColorProfile(UUIDString, profileURL);
    }
}

static void installLayoutTestColorProfile(void)
{
    if (!installColorProfile)
        return;

    // To make sure we get consistent colors (not dependent on the chosen color
    // space of the display), we force the generic sRGB color profile on all displays.
    // This causes a change the user can see.

    NSArray *displays = displayUUIDStrings();
    saveDisplayColorProfiles(displays);

    // Profile path needs to be hardcoded because of <rdar://problem/28392768>.
    NSURL *sRGBProfileURL = [NSURL fileURLWithPath:@"/System/Library/ColorSync/Profiles/sRGB Profile.icc"];
    
    for (NSString *displayUUIDString in displays)
        setDisplayColorProfile(displayUUIDString, sRGBProfileURL);
}

static void restoreUserColorProfile(void)
{
    if (!installColorProfile)
        return;

    // This is used as a signal handler, and thus the calls into ColorSync are unsafe.
    // But we might as well try to restore the user's color profile, we're going down anyway...
    
    NSArray *displays = displayUUIDStrings();
    restoreDisplayColorProfiles(displays);
}

static void releaseSleepAssertions(void)
{
    IOPMAssertionRelease(assertionIDForDisplaySleep);
    IOPMAssertionRelease(assertionIDForSystemSleep);
}

static void simpleSignalHandler(int sig)
{
    // Try to restore the color profile and try to go down cleanly
    restoreUserColorProfile();
    releaseSleepAssertions();
    exit(128 + sig);
}

static void lockDownDiscreteGraphics(void)
{
    mach_port_t mainPort;

    if (IOMainPort(bootstrap_port, &mainPort) != KERN_SUCCESS)
        return;

    CFDictionaryRef classToMatch = IOServiceMatching("AppleGraphicsControl");
    if (!classToMatch)
        return;

    io_service_t serviceObject = IOServiceGetMatchingService(mainPort, classToMatch);
    if (!serviceObject) {
        // The machine does not allow control over the choice of graphics device.
        return;
    }

    // We're intentionally leaking this io_connect in order for the process to stay locked to discrete graphics
    // for the lifetime of the service connection.
    static io_connect_t permanentLockDownService = 0;

    // This call stalls until the graphics device lock is granted.
    kern_return_t kernResult = IOServiceOpen(serviceObject, mach_task_self(), 1, &permanentLockDownService);
    if (kernResult != KERN_SUCCESS) {
        NSLog(@"IOServiceOpen() failed in %s with kernResult = %d", __FUNCTION__, kernResult);
        return;
    }

    kernResult = IOObjectRelease(serviceObject);
    if (kernResult != KERN_SUCCESS)
        NSLog(@"IOObjectRelease() failed in %s with kernResult = %d", __FUNCTION__, kernResult);
}

static void addSleepAssertions(void)
{
    CFStringRef assertionName = CFSTR("WebKit LayoutTestHelper");
    CFStringRef assertionDetails = CFSTR("WebKit layout-test helper tool is preventing sleep.");
    IOPMAssertionCreateWithDescription(kIOPMAssertionTypePreventUserIdleDisplaySleep,
        assertionName, assertionDetails, assertionDetails, NULL, 0, NULL, &assertionIDForDisplaySleep);
    IOPMAssertionCreateWithDescription(kIOPMAssertionTypePreventUserIdleSystemSleep,
        assertionName, assertionDetails, assertionDetails, NULL, 0, NULL, &assertionIDForSystemSleep);
}

int main(int argc, char* argv[])
{
    struct option options[] = {
        { "install-color-profile", no_argument, &installColorProfile, true },
        { "prefer-integrated-gpu", no_argument, &preferIntegratedGPU, true },
    };

    int option;
    while ((option = getopt_long(argc, (char* const*)argv, "", options, NULL)) != -1) {
        switch (option) {
        case '?':   // unknown or ambiguous option
        case ':':   // missing argument
            exit(1);
            break;
        }
    }

    // Hooks the ways we might get told to clean up...
    signal(SIGINT, simpleSignalHandler);
    signal(SIGHUP, simpleSignalHandler);
    signal(SIGTERM, simpleSignalHandler);

    addSleepAssertions();
    if (!preferIntegratedGPU)
        lockDownDiscreteGraphics();

    // Save off the current profile, and then install the layout test profile.
    installLayoutTestColorProfile();

    // Let the script know we're ready
    printf("ready\n");
    fflush(stdout);

    // Wait for any key (or signal)
    getchar();

    // Restore the profile
    restoreUserColorProfile();
    releaseSleepAssertions();

    return 0;
}

#endif // !PLATFORM(IOS_FAMILY)

#if PLATFORM(IOS_FAMILY)
int main(int argc, char* argv[])
{
    return 0;
}
#endif
