/*
 * Copyright (c) 2011, Oracle and/or its affiliates. All rights reserved.
 */

#import "com_sun_glass_ui_Pixels.h"
#import "com_sun_glass_ui_Pixels_Format.h"
#import "com_sun_glass_ui_mac_MacPixels.h"
#import "common.h"

#import "GlassMacros.h"

//#define VERBOSE
#ifndef VERBOSE
    #define LOG(MSG, ...)
#else
    #define LOG(MSG, ...) GLASS_LOG(MSG, ## __VA_ARGS__);
#endif

/*
 * Class:     com_sun_glass_ui_mac_MacPixels
 * Method:    _initIDs
 * Signature: ()I
 */
JNIEXPORT jint JNICALL Java_com_sun_glass_ui_mac_MacPixels__1initIDs
(JNIEnv *env, jclass jClass)
{
    LOG("Java_com_sun_glass_ui_mac_MacPixels__1initIDs");
    
    if (jPixelsAttachData == NULL)
    {
        jPixelsAttachData =  (*env)->GetMethodID(env, jClass, "attachData", "(J)V");
    }
    
    // http://developer.apple.com/library/mac/#documentation/GraphicsImaging/Conceptual/OpenGL-MacProgGuide/opengl_designstrategies/opengl_designstrategies.html%23//apple_ref/doc/uid/TP40001987-CH2-SW17
    // GL_BGRA + GL_UNSIGNED_INT_8_8_8_8_REV == ARGB (big) == BGRA (little)
    return com_sun_glass_ui_Pixels_Format_BYTE_BGRA_PRE;
}

/*
 * Class:     com_sun_glass_ui_mac_MacPixels
 * Method:    _copyPixels
 * Signature: (Ljava/nio/Buffer;Ljava/nio/Buffer;I)V
 */
JNIEXPORT void JNICALL Java_com_sun_glass_ui_mac_MacPixels__1copyPixels
(JNIEnv *env, jobject jPixels, jobject jSrc, jobject jDst, jint jSize)
{
    LOG("Java_com_sun_glass_ui_mac_MacPixels__1copyPixels");
    
    GLASS_ASSERT_MAIN_JAVA_THREAD(env);
    
    void *src = (*env)->GetDirectBufferAddress(env, jSrc);
    void *dst = (*env)->GetDirectBufferAddress(env, jDst);
    if ((src != NULL) && (src != NULL) && (jSize > 0))
    {
        memcpy(src, dst, jSize);
    }
    GLASS_CHECK_EXCEPTION(env);
}

/*
 * Class:     com_sun_glass_ui_mac_MacPixels
 * Method:    _attachInt
 * Signature: (JIILjava/nio/IntBuffer;[II)V
 */
JNIEXPORT void JNICALL Java_com_sun_glass_ui_mac_MacPixels__1attachInt
(JNIEnv *env, jobject jPixels, jlong jPtr, jint jWidth, jint jHeight, jobject jBuffer, jintArray jArray, jint jOffset)
{
    LOG("Java_com_sun_glass_ui_mac_MacPixels__1attachInt");
    
    Java_com_sun_glass_ui_mac_MacPixels__1attachByte(env, jPixels, jPtr, jWidth, jHeight, jBuffer, jArray, 4*jOffset);
}

/*
 * Class:     com_sun_glass_ui_mac_MacPixels
 * Method:    _attachByte
 * Signature: (JIILjava/nio/ByteBuffer;[BI)V
 */
JNIEXPORT void JNICALL Java_com_sun_glass_ui_mac_MacPixels__1attachByte
(JNIEnv *env, jobject jPixels, jlong jPtr, jint jWidth, jint jHeight, jobject jBuffer, jbyteArray jArray, jint jOffset)
{
    LOG("Java_com_sun_glass_ui_mac_MacPixels__1attachByte");
    
    GLASS_ASSERT_MAIN_JAVA_THREAD(env);
    {
        u_int8_t *data = NULL;
        if (jArray != NULL)
        {
            jboolean isCopy = JNI_FALSE;
            data = (*env)->GetPrimitiveArrayCritical(env, jArray, &isCopy);
        }
        else
        {
            data = (*env)->GetDirectBufferAddress(env, jBuffer);
        }
        
        CGImageRef cgImage = NULL;
        if (data != NULL)
        {
            CGColorSpaceRef colorSpace = CGColorSpaceCreateDeviceRGB();
            {
                CGDataProviderRef provider = CGDataProviderCreateWithData(NULL, data+jOffset, jWidth*jHeight*4, NULL);
                if (provider != NULL)
                {
                    cgImage = CGImageCreate(jWidth, jHeight, 8, 32, 4*jWidth, colorSpace, kCGImageAlphaPremultipliedFirst|kCGBitmapByteOrder32Little, provider, NULL, 1, kCGRenderingIntentDefault);
                    CGDataProviderRelease(provider);
                }
            }
            CGColorSpaceRelease(colorSpace);
        }
        
        if (jArray != NULL)
        {
            (*env)->ReleasePrimitiveArrayCritical(env, jArray, data, JNI_ABORT);
        }
        
        NSImage **nsImage = (NSImage**)jlong_to_ptr(jPtr);
        if (cgImage != NULL)
        {
            *nsImage = [[NSImage alloc] initWithCGImage:cgImage size:NSMakeSize(jWidth, jHeight)];
            
            CGImageRelease(cgImage);
        }
        else
        {
            *nsImage = nil;
        }
    }
    GLASS_CHECK_EXCEPTION(env);
}
