/*
 * Copyright (C) 2005, 2007, 2015 Apple Inc. All rights reserved.
 * Copyright (C) 2005 Ben La Monica <ben.lamonica@gmail.com>.  All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions
 * are met:
 * 1. Redistributions of source code must retain the above copyright
 *    notice, this list of conditions and the following disclaimer.
 * 2. 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.
 *
 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``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 AUTHOR 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.
 */

#include "PlatformImage.h"

#include <CoreGraphics/CGBitmapContext.h>
#include <CoreGraphics/CGImage.h>
#include <ImageIO/ImageIO.h>
#include <algorithm>
#include <stdio.h>

#ifdef _WIN32
#include <winsock2.h>
#include <windows.h>
#include <fcntl.h>
#include <io.h>
#endif

#if __APPLE__
#include <TargetConditionals.h>

#if TARGET_OS_IPHONE
#include <MobileCoreServices/UTCoreTypes.h>
#else
#include <CoreServices/CoreServices.h>
#endif

#endif

#ifndef CGFLOAT_DEFINED
#ifdef __LP64__
typedef double CGFloat;
#else
typedef float CGFloat;
#endif
#define CGFLOAT_DEFINED 1
#endif

#ifdef _WIN32
#define FORMAT_SIZE_T "Iu"
#else
#define FORMAT_SIZE_T "zu"
#endif

#ifdef _WIN32
static const CFStringRef kUTTypePNG = CFSTR("public.png");
#endif

namespace ImageDiff {

static std::unique_ptr<PlatformImage> createImageFromDataProvider(CGDataProviderRef dataProvider)
{
    double scaleFactor = 1;

    auto imageSource = CGImageSourceCreateWithDataProvider(dataProvider, 0);
    if (auto properties = CGImageSourceCopyPropertiesAtIndex(imageSource, 0, nullptr)) {
        auto resolutionXProperty = (CFNumberRef)CFDictionaryGetValue(properties, kCGImagePropertyDPIWidth);
        auto resolutionYProperty = (CFNumberRef)CFDictionaryGetValue(properties, kCGImagePropertyDPIHeight);
        if (resolutionXProperty && resolutionYProperty) {
            double resolutionX, resolutionY;
            if (CFNumberGetValue(resolutionXProperty, kCFNumberDoubleType, &resolutionX) && CFNumberGetValue(resolutionYProperty, kCFNumberDoubleType, &resolutionY)) {
                if (resolutionX != resolutionY)
                    fprintf(stderr, "Image has different horizontal and vertical resolutions, which is not supported");

                scaleFactor = resolutionX / 72.0;
            }
        }
        CFRelease(properties);
    }

    auto image = CGImageSourceCreateImageAtIndex(imageSource, 0, nullptr);
    CFRelease(imageSource);
    if (!image)
        return nullptr;

    return std::make_unique<PlatformImage>(image, scaleFactor);
}

std::unique_ptr<PlatformImage> PlatformImage::createFromFile(const char* filePath)
{
    auto dataProvider = CGDataProviderCreateWithFilename(filePath);
    if (!dataProvider)
        return nullptr;

    auto result = createImageFromDataProvider(dataProvider);
    CGDataProviderRelease(dataProvider);
    return result;
}

std::unique_ptr<PlatformImage> PlatformImage::createFromStdin(size_t imageSize)
{
    unsigned char buffer[2048];
    CFMutableDataRef data = CFDataCreateMutable(0, imageSize);

    size_t bytesRemaining = imageSize;
    while (bytesRemaining > 0) {
        size_t bytesToRead = std::min<size_t>(bytesRemaining, 2048);
        size_t bytesRead = fread(buffer, 1, bytesToRead, stdin);
        CFDataAppendBytes(data, buffer, static_cast<CFIndex>(bytesRead));
        bytesRemaining -= static_cast<int>(bytesRead);
    }
    CGDataProviderRef dataProvider = CGDataProviderCreateWithCFData(data);
    CFRelease(data);

    auto result = createImageFromDataProvider(dataProvider);
    CGDataProviderRelease(dataProvider);
    return result;
}

std::unique_ptr<PlatformImage> PlatformImage::createFromDiffData(void* data, size_t width, size_t height)
{
    static CGColorSpaceRef diffColorspace = CGColorSpaceCreateDeviceGray();
    CGDataProviderRef provider = CGDataProviderCreateWithData(0, data, width * height, [](void*, const void* data, size_t) {
        free(const_cast<void*>(data));
    });
    CGImageRef image = CGImageCreate(width, height, 8, 8, width, diffColorspace, 0, provider, 0, false, kCGRenderingIntentDefault);
    CFRelease(provider);

    return std::make_unique<PlatformImage>(image);
}

PlatformImage::PlatformImage(CGImageRef image, double scaleFactor)
    : m_image(image)
    , m_scaleFactor(scaleFactor)
{
}

PlatformImage::~PlatformImage()
{
    CFRelease(m_image);
    free(m_buffer);
}

size_t PlatformImage::width() const
{
    return CGImageGetWidth(m_image);
}

size_t PlatformImage::height() const
{
    return CGImageGetHeight(m_image);
}

size_t PlatformImage::rowBytes() const
{
    return width() * 4;
}

bool PlatformImage::hasAlpha() const
{
    CGImageAlphaInfo info = CGImageGetAlphaInfo(m_image);
    return (info >= kCGImageAlphaPremultipliedLast) && (info <= kCGImageAlphaFirst);
}

unsigned char* PlatformImage::pixels() const
{
    size_t width = this->width();
    size_t height = this->height();
    size_t rowBytes = width * 4;

    m_buffer = calloc(height, rowBytes);
    CGContextRef context = CGBitmapContextCreate(m_buffer, width, height, 8, rowBytes, CGImageGetColorSpace(m_image), kCGImageAlphaPremultipliedFirst | kCGBitmapByteOrder32Host);
    CGContextDrawImage(context, CGRectMake(0, 0, width, height), m_image);
    CFRelease(context);
    return reinterpret_cast<unsigned char*>(m_buffer);
}

void PlatformImage::writeAsPNGToStdout()
{
    CFMutableDataRef imageData = CFDataCreateMutable(0, 0);
    CGImageDestinationRef imageDest = CGImageDestinationCreateWithData(imageData, kUTTypePNG, 1, 0);
    CGImageDestinationAddImage(imageDest, m_image, 0);
    CGImageDestinationFinalize(imageDest);
    printf("Content-Length: %" FORMAT_SIZE_T "\n", static_cast<size_t>(CFDataGetLength(imageData)));
    fwrite(CFDataGetBytePtr(imageData), 1, CFDataGetLength(imageData), stdout);
    CFRelease(imageData);
    CFRelease(imageDest);
}

} // namespace ImageDiff
