/*
 * Copyright (c) 2011, 2016, Oracle and/or its affiliates. All rights reserved.
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
 *
 * This code is free software; you can redistribute it and/or modify it
 * under the terms of the GNU General Public License version 2 only, as
 * published by the Free Software Foundation.  Oracle designates this
 * particular file as subject to the "Classpath" exception as provided
 * by Oracle in the LICENSE file that accompanied this code.
 *
 * This code is distributed in the hope that it will be useful, but WITHOUT
 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
 * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
 * version 2 for more details (a copy is included in the LICENSE file that
 * accompanied this code).
 *
 * You should have received a copy of the GNU General Public License version
 * 2 along with this work; if not, write to the Free Software Foundation,
 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
 *
 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
 * or visit www.oracle.com if you need additional information or have any
 * questions.
 */
#import "jni_util.h"

#import <Cocoa/Cocoa.h>
#import <JavaNativeFoundation/JavaNativeFoundation.h>

#import "GeomUtilities.h"
#import "ThreadUtilities.h"

#import "sun_lwawt_macosx_CImage.h"


static void CImage_CopyArrayIntoNSImageRep
(jint *srcPixels, jint *dstPixels, int width, int height)
{
    int x, y;
    // TODO: test this on big endian systems (not sure if its correct)...
    for (y = 0; y < height; y++) {
        for (x = 0; x < width; x++) {
            jint pix = srcPixels[x];
            jint a = (pix >> 24) & 0xff;
            jint r = (pix >> 16) & 0xff;
            jint g = (pix >>  8) & 0xff;
            jint b = (pix      ) & 0xff;
            dstPixels[x] = (b << 24) | (g << 16) | (r << 8) | a;
        }
        srcPixels += width; // TODO: use explicit scanStride
        dstPixels += width;
    }
}

static void CImage_CopyNSImageIntoArray
(NSImage *srcImage, jint *dstPixels, NSRect fromRect, NSRect toRect)
{
    int width = toRect.size.width;
    int height = toRect.size.height;
    CGColorSpaceRef colorspace = CGColorSpaceCreateDeviceRGB();
    CGContextRef cgRef = CGBitmapContextCreate(dstPixels, width, height,
                                8, width * 4, colorspace,
                                kCGImageAlphaPremultipliedFirst | kCGBitmapByteOrder32Host);
    CGColorSpaceRelease(colorspace);
    NSGraphicsContext *context = [NSGraphicsContext graphicsContextWithGraphicsPort:cgRef flipped:NO];
    CGContextRelease(cgRef);
    NSGraphicsContext *oldContext = [[NSGraphicsContext currentContext] retain];
    [NSGraphicsContext setCurrentContext:context];
    [srcImage drawInRect:toRect
                fromRect:fromRect
               operation:NSCompositeSourceOver
                fraction:1.0];
    [NSGraphicsContext setCurrentContext:oldContext];
    [oldContext release];
}

static NSBitmapImageRep* CImage_CreateImageRep(JNIEnv *env, jintArray buffer, jint width, jint height)
{
    NSBitmapImageRep* imageRep = [[NSBitmapImageRep alloc] initWithBitmapDataPlanes:NULL
                                                                         pixelsWide:width
                                                                         pixelsHigh:height
                                                                      bitsPerSample:8
                                                                    samplesPerPixel:4
                                                                           hasAlpha:YES
                                                                           isPlanar:NO
                                                                     colorSpaceName:NSDeviceRGBColorSpace
                                                                       bitmapFormat:NSAlphaFirstBitmapFormat
                                                                        bytesPerRow:width*4 // TODO: use explicit scanStride
                                                                       bitsPerPixel:32];

    jint *imgData = (jint *)[imageRep bitmapData];
    if (imgData == NULL) return 0L;

    jint *src = (*env)->GetPrimitiveArrayCritical(env, buffer, NULL);
    if (src == NULL) return 0L;

    CImage_CopyArrayIntoNSImageRep(src, imgData, width, height);

    (*env)->ReleasePrimitiveArrayCritical(env, buffer, src, JNI_ABORT);

    return imageRep;
}

/*
 * Class:     sun_lwawt_macosx_CImage
 * Method:    nativeCreateNSImageFromArray
 * Signature: ([III)J
 */
JNIEXPORT jlong JNICALL Java_sun_lwawt_macosx_CImage_nativeCreateNSImageFromArray
(JNIEnv *env, jclass klass, jintArray buffer, jint width, jint height)
{
    jlong result = 0L;

JNF_COCOA_ENTER(env);
    
    NSBitmapImageRep* imageRep = CImage_CreateImageRep(env, buffer, width, height);
    if (imageRep) {
        NSImage *nsImage = [[[NSImage alloc] initWithSize:NSMakeSize(width, height)] retain];
        [nsImage addRepresentation:imageRep];
        [imageRep release];
        result = ptr_to_jlong(nsImage);
    }

JNF_COCOA_EXIT(env);

    return result;
}

/*
 * Class:     sun_lwawt_macosx_CImage
 * Method:    nativeCreateNSImageFromArrays
 * Signature: ([[I[I[I)J
 */
JNIEXPORT jlong JNICALL Java_sun_lwawt_macosx_CImage_nativeCreateNSImageFromArrays
(JNIEnv *env, jclass klass, jobjectArray buffers, jintArray widths, jintArray heights)
{
    jlong result = 0L;

JNF_COCOA_ENTER(env);

    jsize num = (*env)->GetArrayLength(env, buffers);
    NSMutableArray * reps = [NSMutableArray arrayWithCapacity: num];

    jint * ws = (*env)->GetIntArrayElements(env, widths, NULL);
    if (ws != NULL) {
        jint * hs = (*env)->GetIntArrayElements(env, heights, NULL);
        if (hs != NULL) {
            jsize i;
            for (i = 0; i < num; i++) {
                jintArray buffer = (*env)->GetObjectArrayElement(env, buffers, i);

                NSBitmapImageRep* imageRep = CImage_CreateImageRep(env, buffer, ws[i], hs[i]);
                if (imageRep) {
                    [reps addObject: imageRep];
                }
            }

            (*env)->ReleaseIntArrayElements(env, heights, hs, JNI_ABORT);
        }
        (*env)->ReleaseIntArrayElements(env, widths, ws, JNI_ABORT);
    }
    if ([reps count]) {
        NSImage *nsImage = [[[NSImage alloc] initWithSize:NSMakeSize(0, 0)] retain];
        [nsImage addRepresentations: reps];
        result = ptr_to_jlong(nsImage);
    }

JNF_COCOA_EXIT(env);

    return result;
}

/*
 * Class:     sun_lwawt_macosx_CImage
 * Method:    nativeCreateNSImageFromIconSelector
 * Signature: (I)J
 */
JNIEXPORT jlong JNICALL Java_sun_lwawt_macosx_CImage_nativeCreateNSImageFromIconSelector
(JNIEnv *env, jclass klass, jint selector)
{
    NSImage *image = nil;

JNF_COCOA_ENTER(env);

    IconRef iconRef;
    if (noErr == GetIconRef(kOnSystemDisk, kSystemIconsCreator, selector, &iconRef)) {
        image = [[[NSImage alloc] initWithIconRef:iconRef] retain];
        ReleaseIconRef(iconRef);
    }

JNF_COCOA_EXIT(env);

    return ptr_to_jlong(image);
}

/*
 * Class:     sun_lwawt_macosx_CImage
 * Method:    nativeCreateNSImageFromFileContents
 * Signature: (Ljava/lang/String;)J
 */
JNIEXPORT jlong JNICALL Java_sun_lwawt_macosx_CImage_nativeCreateNSImageFromFileContents
(JNIEnv *env, jclass klass, jstring file)
{
    NSImage *image = nil;

JNF_COCOA_ENTER(env);

    NSString *path = JNFNormalizedNSStringForPath(env, file);
    image = [[[NSImage alloc] initByReferencingFile:path] retain];

JNF_COCOA_EXIT(env);

    return ptr_to_jlong(image);
}

/*
 * Class:     sun_lwawt_macosx_CImage
 * Method:    nativeCreateNSImageOfFileFromLaunchServices
 * Signature: (Ljava/lang/String;)J
 */
JNIEXPORT jlong JNICALL Java_sun_lwawt_macosx_CImage_nativeCreateNSImageOfFileFromLaunchServices
(JNIEnv *env, jclass klass, jstring file)
{
    __block NSImage *image = nil;

JNF_COCOA_ENTER(env);

    NSString *path = JNFNormalizedNSStringForPath(env, file);
    [ThreadUtilities performOnMainThreadWaiting:YES block:^(){
        image = [[[NSWorkspace sharedWorkspace] iconForFile:path] retain];
        [image setScalesWhenResized:TRUE];
    }];

JNF_COCOA_EXIT(env);

    return ptr_to_jlong(image);
}

/*
 * Class:     sun_lwawt_macosx_CImage
 * Method:    nativeCreateNSImageFromImageName
 * Signature: (Ljava/lang/String;)J
 */
JNIEXPORT jlong JNICALL Java_sun_lwawt_macosx_CImage_nativeCreateNSImageFromImageName
(JNIEnv *env, jclass klass, jstring name)
{
    NSImage *image = nil;

JNF_COCOA_ENTER(env);

    image = [[NSImage imageNamed:JNFJavaToNSString(env, name)] retain];

JNF_COCOA_EXIT(env);

    return ptr_to_jlong(image);
}

/*
 * Class:     sun_lwawt_macosx_CImage
 * Method:    nativeCopyNSImageIntoArray
 * Signature: (J[III)V
 */
JNIEXPORT void JNICALL Java_sun_lwawt_macosx_CImage_nativeCopyNSImageIntoArray
        (JNIEnv *env, jclass klass, jlong nsImgPtr, jintArray buffer, jint dw, jint dh)
{
    JNF_COCOA_ENTER(env);

    NSImage *img = (NSImage *)jlong_to_ptr(nsImgPtr);
    jint *dst = (*env)->GetPrimitiveArrayCritical(env, buffer, NULL);
    if (dst) {
        NSSize size = [(NSImage *)jlong_to_ptr(nsImgPtr) size];
        NSRect fromRect = NSMakeRect(0, 0, size.width, size.height);
        NSRect toRect = NSMakeRect(0, 0, dw, dh);
        CImage_CopyNSImageIntoArray(img, dst, fromRect, toRect);
        (*env)->ReleasePrimitiveArrayCritical(env, buffer, dst, JNI_ABORT);
    }

    JNF_COCOA_EXIT(env);
}

/*
 * Class:     sun_lwawt_macosx_CImage
 * Method:    nativeGetNSImageSize
 * Signature: (J)Ljava/awt/geom/Dimension2D;
 */
JNIEXPORT jobject JNICALL Java_sun_lwawt_macosx_CImage_nativeGetNSImageSize
(JNIEnv *env, jclass klass, jlong nsImgPtr)
{
    jobject size = NULL;

JNF_COCOA_ENTER(env);

    size = NSToJavaSize(env, [(NSImage *)jlong_to_ptr(nsImgPtr) size]);

JNF_COCOA_EXIT(env);

    return size;
}

/*
 * Class:     sun_lwawt_macosx_CImage
 * Method:    nativeSetNSImageSize
 * Signature: (JDD)V
 */
JNIEXPORT void JNICALL Java_sun_lwawt_macosx_CImage_nativeSetNSImageSize
(JNIEnv *env, jclass clazz, jlong image, jdouble w, jdouble h)
{
    if (!image) return;
    NSImage *i = (NSImage *)jlong_to_ptr(image);

JNF_COCOA_ENTER(env);

    [i setScalesWhenResized:TRUE];
    [i setSize:NSMakeSize(w, h)];

JNF_COCOA_EXIT(env);
}

/*
 * Class:     sun_lwawt_macosx_CImage
 * Method:    nativeResizeNSImageRepresentations
 * Signature: (JDD)V
 */
JNIEXPORT void JNICALL Java_sun_lwawt_macosx_CImage_nativeResizeNSImageRepresentations
(JNIEnv *env, jclass clazz, jlong image, jdouble w, jdouble h)
{
    if (!image) return;
    NSImage *i = (NSImage *)jlong_to_ptr(image);
    
JNF_COCOA_ENTER(env);
    
    NSImageRep *imageRep = nil;
    NSArray *imageRepresentations = [i representations];
    NSEnumerator *imageEnumerator = [imageRepresentations objectEnumerator];
    while ((imageRep = [imageEnumerator nextObject]) != nil) {
        [imageRep setSize:NSMakeSize(w, h)];
    }
    
JNF_COCOA_EXIT(env);
}

NSComparisonResult getOrder(BOOL order){
    return (NSComparisonResult) (order ? NSOrderedAscending : NSOrderedDescending);
}

/*
 * Class:     sun_lwawt_macosx_CImage
 * Method:    nativeGetNSImageRepresentationsCount
 * Signature: (JDD)[Ljava/awt/geom/Dimension2D;
 */
JNIEXPORT jobjectArray JNICALL
                  Java_sun_lwawt_macosx_CImage_nativeGetNSImageRepresentationSizes
(JNIEnv *env, jclass clazz, jlong image, jdouble w, jdouble h)
{
    if (!image) return NULL;
    jobjectArray jreturnArray = NULL;
    NSImage *img = (NSImage *)jlong_to_ptr(image);

JNF_COCOA_ENTER(env);
        
    NSArray *imageRepresentations = [img representations];
    if([imageRepresentations count] == 0){
        return NULL;
    }
    
    NSArray *sortedImageRepresentations = [imageRepresentations
                    sortedArrayUsingComparator: ^(id obj1, id obj2) {
        
        NSImageRep *imageRep1 = (NSImageRep *) obj1;
        NSImageRep *imageRep2 = (NSImageRep *) obj2;
        NSSize size1 = [imageRep1 size];
        NSSize size2 = [imageRep2 size];
        
        if (NSEqualSizes(size1, size2)) {
            return getOrder([imageRep1 pixelsWide] <= [imageRep2 pixelsWide] &&
                            [imageRep1 pixelsHigh] <= [imageRep2 pixelsHigh]);
        }

        return getOrder(size1.width <= size2.width && size1.height <= size2.height);
    }];

    NSMutableArray *sortedPixelSizes = [[[NSMutableArray alloc] init] autorelease];
    NSSize lastSize = [[sortedImageRepresentations lastObject] size];
    
    NSUInteger i = [sortedImageRepresentations indexOfObjectPassingTest:
               ^BOOL(id obj, NSUInteger idx, BOOL *stop) {
        NSSize imageRepSize = [obj size];
        return (w <= imageRepSize.width && h <= imageRepSize.height)
                   || NSEqualSizes(imageRepSize, lastSize);
    }];

    NSUInteger count = [sortedImageRepresentations count];
    i = (i == NSNotFound) ? count - 1 : i;
    NSSize bestFitSize = [[sortedImageRepresentations objectAtIndex: i] size];

    for(; i < count; i++){
        NSImageRep *imageRep = [sortedImageRepresentations objectAtIndex: i];

        if (!NSEqualSizes([imageRep size], bestFitSize)) {
            break;
        }

        NSSize pixelSize = NSMakeSize(
                                [imageRep pixelsWide], [imageRep pixelsHigh]);
        [sortedPixelSizes addObject: [NSValue valueWithSize: pixelSize]];
    }

    count = [sortedPixelSizes count];
    static JNF_CLASS_CACHE(jc_Dimension, "java/awt/Dimension");
    jreturnArray = JNFNewObjectArray(env, &jc_Dimension, count);
    CHECK_NULL_RETURN(jreturnArray, NULL);

    for(i = 0; i < count; i++){
        NSSize pixelSize = [[sortedPixelSizes objectAtIndex: i] sizeValue];

        (*env)->SetObjectArrayElement(env, jreturnArray, i,
                                      NSToJavaSize(env, pixelSize));
        JNU_CHECK_EXCEPTION_RETURN(env, NULL);
    }

JNF_COCOA_EXIT(env);

    return jreturnArray;
}

/*
 * Class:     sun_lwawt_macosx_CImage
 * Method:    nativeGetPlatformImageBytes
 * Signature: ([III)[B
 */
JNIEXPORT jbyteArray JNICALL Java_sun_lwawt_macosx_CImage_nativeGetPlatformImageBytes
(JNIEnv *env, jclass klass, jintArray buffer, jint width, jint height)
{
    jbyteArray result = 0L;
    
    JNF_COCOA_ENTER(env);
    
    NSBitmapImageRep* imageRep = [CImage_CreateImageRep(env, buffer, width, height) autorelease];
    if (imageRep) {
        NSData *tiffImage = [imageRep TIFFRepresentation];
        jsize tiffSize = (jsize)[tiffImage length];
        result = (*env)->NewByteArray(env, tiffSize);
        CHECK_NULL_RETURN(result, nil);
        jbyte *tiffData = (jbyte *)(*env)->GetPrimitiveArrayCritical(env, result, 0);
        CHECK_NULL_RETURN(tiffData, nil);
        [tiffImage getBytes:tiffData];
        (*env)->ReleasePrimitiveArrayCritical(env, result, tiffData, 0);
    }
    
    JNF_COCOA_EXIT(env);
    
    return result;
}

/*
 * Class:     sun_lwawt_macosx_CImage
 * Method:    nativeCreateNSImageFromBytes
 * Signature: ([B)J
 */
JNIEXPORT jlong JNICALL Java_sun_lwawt_macosx_CImage_nativeCreateNSImageFromBytes
(JNIEnv *env, jclass klass, jbyteArray sourceData)
{
    jlong result = 0L;
    CHECK_NULL_RETURN(sourceData, 0L);
    
    JNF_COCOA_ENTER(env);
    
    jsize sourceSize = (*env)->GetArrayLength(env, sourceData);
    if (sourceSize == 0) return 0L;
    
    jbyte *sourceBytes = (*env)->GetPrimitiveArrayCritical(env, sourceData, NULL);
    CHECK_NULL_RETURN(sourceBytes, 0L);
    NSData *rawData = [NSData dataWithBytes:sourceBytes length:sourceSize];    
    NSImage *newImage = [[NSImage alloc] initWithData:rawData];
    
    (*env)->ReleasePrimitiveArrayCritical(env, sourceData, sourceBytes, JNI_ABORT);
    CHECK_NULL_RETURN(newImage, 0L);
    
    result = ptr_to_jlong(newImage);
    JNF_COCOA_EXIT(env);
    
    return result;
}

