/*
 * Copyright (c) 2011, 2014, 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 <JavaNativeFoundation/JavaNativeFoundation.h>

#import "jni_util.h"
#import "ThreadUtilities.h"
#import "LWCToolkit.h"
#import "AWT_debug.h"


/*
 * Class:     sun_awt_CGraphicsEnvironment
 * Method:    initCocoa
 * Signature: ()V
 */
JNIEXPORT void JNICALL
Java_sun_awt_CGraphicsEnvironment_initCocoa
(JNIEnv *env, jclass self)
{
JNF_COCOA_ENTER(env);

    // Inform Cocoa that we're multi-threaded.
    // Creating a short-lived NSThread is the recommended way of doing so.
    [NSThread detachNewThreadSelector:@selector(self) toTarget:[NSObject class] withObject:nil];

JNF_COCOA_EXIT(env);
}

#define MAX_DISPLAYS 64

/*
 * Class:     sun_awt_CGraphicsEnvironment
 * Method:    getDisplayIDs
 * Signature: ()[I
 */
JNIEXPORT jintArray JNICALL
Java_sun_awt_CGraphicsEnvironment_getDisplayIDs
(JNIEnv *env, jclass class)
{
    jintArray ret = NULL;

JNF_COCOA_ENTER(env);

    /* Get the count */
    CGDisplayCount displayCount;
    if (CGGetOnlineDisplayList(MAX_DISPLAYS, NULL, &displayCount) != kCGErrorSuccess) {
        [JNFException raise:env
                         as:kInternalError
                     reason:"CGGetOnlineDisplayList() failed to get display count"];
        return NULL;
    }

    /* Allocate an array and get the size list of display Ids */
    CGDirectDisplayID displays[MAX_DISPLAYS];
    if (CGGetOnlineDisplayList(displayCount, displays, &displayCount) != kCGErrorSuccess) {
        [JNFException raise:env
                         as:kInternalError
                     reason:"CGGetOnlineDisplayList() failed to get display list"];
        return NULL;
    }

    CGDisplayCount i;
    CGDisplayCount displayActiveCount = 0; //Active and sleeping.
    for (i = 0; i < displayCount; ++i) {
        if (CGDisplayMirrorsDisplay(displays[i]) == kCGNullDirectDisplay) {
            ++displayActiveCount;
        } else {
            displays[i] = kCGNullDirectDisplay;
        }
    }

    /* Allocate a java array for display identifiers */
    ret = JNFNewIntArray(env, displayActiveCount);

    /* Initialize and return the backing int array */
    assert(sizeof(jint) >= sizeof(CGDirectDisplayID));
    jint *elems = (*env)->GetIntArrayElements(env, ret, 0);
    CHECK_NULL_RETURN(elems, NULL);

    /* Filter out the mirrored displays */
    for (i = 0; i < displayCount; ++i) {
        if (displays[i] != kCGNullDirectDisplay) {
            elems[--displayActiveCount] = displays[i];
        }
    }

    (*env)->ReleaseIntArrayElements(env, ret, elems, 0);

JNF_COCOA_EXIT(env);

    return ret;
}

/*
 * Class:     sun_awt_CGraphicsEnvironment
 * Method:    getMainDisplayID
 * Signature: ()I
 */
JNIEXPORT jint JNICALL
Java_sun_awt_CGraphicsEnvironment_getMainDisplayID
(JNIEnv *env, jclass class)
{
    return CGMainDisplayID();
}

/*
 * Post the display reconfiguration event.
 */
static void displaycb_handle
(CGDirectDisplayID display, CGDisplayChangeSummaryFlags flags, void *userInfo)
{
    if (flags == kCGDisplayBeginConfigurationFlag) return;

    [ThreadUtilities performOnMainThreadWaiting:NO block:^() {

        JNFPerformEnvBlock(JNFThreadDetachImmediately, ^(JNIEnv *env) {
            JNFWeakJObjectWrapper *wrapper = (JNFWeakJObjectWrapper *)userInfo;

            jobject graphicsEnv = [wrapper jObjectWithEnv:env];
            if (graphicsEnv == NULL) return; // ref already GC'd
            static JNF_CLASS_CACHE(jc_CGraphicsEnvironment, "sun/awt/CGraphicsEnvironment");
            static JNF_MEMBER_CACHE(jm_displayReconfiguration,
                    jc_CGraphicsEnvironment, "_displayReconfiguration","(IZ)V");
            JNFCallVoidMethod(env, graphicsEnv, jm_displayReconfiguration,
                    (jint) display, (jboolean) flags & kCGDisplayRemoveFlag);
        });
    }];
}

/*
 * Class:     sun_awt_CGraphicsEnvironment
 * Method:    registerDisplayReconfiguration
 * Signature: ()J
 */
JNIEXPORT jlong JNICALL
Java_sun_awt_CGraphicsEnvironment_registerDisplayReconfiguration
(JNIEnv *env, jobject this)
{
    jlong ret = 0L;

JNF_COCOA_ENTER(env);

    JNFWeakJObjectWrapper *wrapper = [JNFWeakJObjectWrapper wrapperWithJObject:this withEnv:env];
    CFRetain(wrapper); // pin from ObjC-GC

    /* Register the callback */
    if (CGDisplayRegisterReconfigurationCallback(&displaycb_handle, wrapper) != kCGErrorSuccess) {
        [JNFException raise:env
                         as:kInternalError
                     reason:"CGDisplayRegisterReconfigurationCallback() failed"];
        return 0L;
    }

    ret = ptr_to_jlong(wrapper);

JNF_COCOA_EXIT(env);

    return ret;
}

/*
 * Class:     sun_awt_CGraphicsEnvironment
 * Method:    deregisterDisplayReconfiguration
 * Signature: (J)V
 */
JNIEXPORT void JNICALL
Java_sun_awt_CGraphicsEnvironment_deregisterDisplayReconfiguration
(JNIEnv *env, jobject this, jlong p)
{
JNF_COCOA_ENTER(env);

    JNFWeakJObjectWrapper *wrapper = (JNFWeakJObjectWrapper *)jlong_to_ptr(p);
    if (!wrapper) return;

    /* Remove the registration */
    if (CGDisplayRemoveReconfigurationCallback(&displaycb_handle, wrapper) != kCGErrorSuccess) {
        [JNFException raise:env
                         as:kInternalError
                     reason:"CGDisplayRemoveReconfigurationCallback() failed, leaking the callback context!"];
        return;
    }

    [wrapper setJObject:NULL withEnv:env]; // more efficiant to pre-clear

    CFRelease(wrapper);

JNF_COCOA_EXIT(env);
}
