/*
 * 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()
{
    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()
{
    NSMutableArray *result = [NSMutableArray array];

    static const uint32_t 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()
{
    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()
{
    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()
{
    mach_port_t masterPort;
    kern_return_t kernResult = IOMasterPort(bootstrap_port, &masterPort);
    if (kernResult != KERN_SUCCESS)
        return;
    CFDictionaryRef classToMatch = IOServiceMatching("AppleGraphicsControl");
    if (!classToMatch)
        return;

    io_service_t serviceObject = IOServiceGetMatchingService(masterPort, 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.
    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()
{
    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
