#include <CoreFoundation/CoreFoundation.h>
#include <CoreServices/CoreServices.h>
#include <QuickLook/QuickLook.h>

OSStatus GenerateThumbnailForURL(void *thisInterface, QLThumbnailRequestRef thumbnail, CFURLRef url, CFStringRef contentTypeUTI, CFDictionaryRef options, CGSize maxSize);
void CancelThumbnailGeneration(void *thisInterface, QLThumbnailRequestRef thumbnail);

/* -----------------------------------------------------------------------------
    Generate a thumbnail for file

   This function's job is to create thumbnail for designated file as fast as possible
   ----------------------------------------------------------------------------- */

struct PPIThumb
{
    int width;
    int height;
    int comp;
    /*
    bool valid()
    {
        return (width == 128 && height == 128 && comp == 4);
    }
    */
};

struct PPIDocVersion
{
    int major;
    int minor;
};

struct PPISoftVersion
{
    int major;
    int minor;
    int fix;
    int build;
};

struct PPIHeader
{
    char magic[4];
    struct PPIDocVersion doc_version;
    struct PPISoftVersion soft_version;
    struct PPIThumb thumb_header;
    /*
    bool valid()
    {
        if (strcmp(magic, "PPI") != 0)
            return false;
        if (doc_version.major != 0 || doc_version.minor != 1)
            return false;
        if (!thumb_header.valid())
            return false;
        return true;
    }
    */
};

OSStatus GenerateThumbnailForURL(void *thisInterface, QLThumbnailRequestRef thumbnail, CFURLRef url, CFStringRef contentTypeUTI, CFDictionaryRef options, CGSize maxSize)
{
    // To complete your generator please implement the function GenerateThumbnailForURL in GenerateThumbnailForURL.c
    //maxSize = CGSizeMake(128, 128);
    CGContextRef context = QLThumbnailRequestCreateContext(thumbnail, maxSize, true, NULL);
    CGRect renderRect = CGRectMake(0., 0., maxSize.width, maxSize.height);
    
    CFStringRef path = CFURLCopyFileSystemPath(url, kCFURLPOSIXPathStyle);
    const char* path_string = CFStringGetCStringPtr(path, kCFStringEncodingUTF8);
    
    FILE* fp = fopen(path_string, "rb");
    if (fp)
    {
        struct PPIHeader header;
        fread(&header, sizeof(struct PPIHeader), 1, fp);
        int w = header.thumb_header.width;
        int h = header.thumb_header.height;
        int c = header.thumb_header.comp;

        CGColorSpaceRef colorSpace = CGColorSpaceCreateDeviceRGB();
        CGContextRef bmp = CGBitmapContextCreate(NULL, w, h, 8, w * c, colorSpace, kCGImageAlphaPremultipliedLast);
        uint8_t* data = CGBitmapContextGetData(bmp);
        fread(data, w * h * c, 1, fp);
        fclose(fp);
        
        CGImageRef img = CGBitmapContextCreateImage(bmp);
        CGContextDrawImage(context, renderRect, img);
    }
    else
    {
        CGContextSetRGBFillColor(context, 1, 0, 0, 1);
        CGContextFillRect(context, CGRectMake(0, 0, maxSize.width, maxSize.height));
    }
    QLThumbnailRequestFlushContext(thumbnail, context);
    CFRelease(context);
    return noErr;
}

void CancelThumbnailGeneration(void *thisInterface, QLThumbnailRequestRef thumbnail)
{
    // Implement only if supported
}
