/*
 * 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/CGImageDestination.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 {

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

    auto image = CGImageCreateWithPNGDataProvider(dataProvider, 0, false, kCGRenderingIntentDefault);
    CGDataProviderRelease(dataProvider);
    if (!image)
        return nullptr;

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

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);
    CGImageRef image = CGImageCreateWithPNGDataProvider(dataProvider, 0, false, kCGRenderingIntentDefault);
    CFRelease(dataProvider);

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

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)
    : m_image(image)
{
}

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
