/*
 * Copyright (c) 1996, 2008, 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.
 */

#include "awt_Object.h"
#include "ObjectList.h"

#ifdef DEBUG
static BOOL reportEvents = FALSE;
#endif


/************************************************************************
 * AwtObject fields
 */

jfieldID AwtObject::pDataID;
jfieldID AwtObject::destroyedID;
jfieldID AwtObject::targetID;
jclass AwtObject::wObjectPeerClass;
jmethodID AwtObject::getPeerForTargetMID;
jfieldID AwtObject::createErrorID;


/************************************************************************
 * AwtObject methods
 */

AwtObject::AwtObject()
{
    theAwtObjectList.Add(this);
    m_peerObject = NULL;
    m_callbacksEnabled = TRUE;
}

AwtObject::~AwtObject()
{
}

void AwtObject::Dispose()
{
    theAwtObjectList.Remove(this);

    // value 0 of lParam means that we should not attempt to enter the
    // SyncCall critical section, as it was entered someshere earlier
    AwtToolkit::GetInstance().PostMessage(WM_AWT_DELETEOBJECT, (WPARAM)this, (LPARAM)0);
}

void AwtObject::_Dispose(PDATA pData)
{
    TRY_NO_VERIFY;

    CriticalSection::Lock l(AwtToolkit::GetInstance().GetSyncCS());

    if (pData != NULL) {
        AwtObject *o = (AwtObject *)pData;
        AwtToolkit::GetInstance().SendMessage(WM_AWT_DISPOSE, (WPARAM)o, (LPARAM)0);
    }

    CATCH_BAD_ALLOC;
}

/*
 * Return the peer associated with some target.  This information is
 * maintained in a hashtable at the java level.
 */
jobject AwtObject::GetPeerForTarget(JNIEnv *env, jobject target)
{
    jobject result =
        env->CallStaticObjectMethod(AwtObject::wObjectPeerClass,
                                    AwtObject::getPeerForTargetMID,
                                    target);

    DASSERT(!safe_ExceptionOccurred(env));
    return result;
}

/* Execute a callback to the associated Java peer. */
void
AwtObject::DoCallback(const char* methodName, const char* methodSig, ...)
{
    JNIEnv *env = (JNIEnv *)JNU_GetEnv(jvm, JNI_VERSION_1_2);

    /* don't callback during the create & initialization process */
    if (m_peerObject != NULL && m_callbacksEnabled) {
        va_list args;
        va_start(args, methodSig);
#ifdef DEBUG
        if (reportEvents) {
            jstring targetStr =
                (jstring)JNU_CallMethodByName(env, NULL, GetTarget(env),
                                              "getName",
                                              "()Ljava/lang/String;").l;
            DASSERT(!safe_ExceptionOccurred(env));
            LPCWSTR targetStrW = JNU_GetStringPlatformChars(env, targetStr, NULL);
            printf("Posting %s%s method to %S\n", methodName, methodSig, targetStrW);
            JNU_ReleaseStringPlatformChars(env, targetStr, targetStrW);
        }
#endif
        /* caching would do much good here */
        JNU_CallMethodByNameV(env, NULL, GetPeer(env),
                              methodName, methodSig, args);
        {
            jthrowable exc = safe_ExceptionOccurred(env);
            if (exc) {
                env->DeleteLocalRef(exc);
                env->ExceptionDescribe();
                env->ExceptionClear();
            }
        }
        DASSERT(!safe_ExceptionOccurred(env));
        va_end(args);
    }
}

void AwtObject::SendEvent(jobject event)
{
    JNIEnv *env = (JNIEnv *)JNU_GetEnv(jvm, JNI_VERSION_1_2);

#ifdef DEBUG
    if (reportEvents) {
        jstring eventStr = JNU_ToString(env, event);
        DASSERT(!safe_ExceptionOccurred(env));
        jstring targetStr =
            (jstring)JNU_CallMethodByName(env, NULL, GetTarget(env),"getName",
                                          "()Ljava/lang/String;").l;
        DASSERT(!safe_ExceptionOccurred(env));
        LPCWSTR eventStrW = JNU_GetStringPlatformChars(env, eventStr, NULL);
        LPCWSTR targetStrW = JNU_GetStringPlatformChars(env, targetStr, NULL);
        printf("Posting %S to %S\n", eventStrW, targetStrW);
        JNU_ReleaseStringPlatformChars(env, eventStr, eventStrW);
        JNU_ReleaseStringPlatformChars(env, targetStr, targetStrW);
    }
#endif
    /* Post event to the system EventQueue. */
    JNU_CallMethodByName(env, NULL, GetPeer(env), "postEvent",
                         "(Ljava/awt/AWTEvent;)V", event);
    {
        jthrowable exc = safe_ExceptionOccurred(env);
        if (exc) {
            env->DeleteLocalRef(exc);
            env->ExceptionDescribe();
        }
    }
    DASSERT(!safe_ExceptionOccurred(env));
}

//
// (static)
// Switches to Windows thread via SendMessage and synchronously
// calls AwtObject::WinThreadExecProc with the given command id
// and parameters.
//
// Useful for writing code that needs to be synchronized with
// what's happening on the Windows thread.
//
LRESULT AwtObject::WinThreadExec(
    jobject                             peerObject,
    UINT                                cmdId,
    LPARAM                              param1,
    LPARAM                              param2,
    LPARAM                              param3,
    LPARAM                              param4 )
{
    DASSERT( peerObject != NULL);

    JNIEnv *env = (JNIEnv *)JNU_GetEnv(jvm, JNI_VERSION_1_2);
    // since we pass peerObject to another thread we must
    //   make a global ref
    jobject peerObjectGlobalRef = env->NewGlobalRef(peerObject);

    ExecuteArgs         args;
    LRESULT         retVal;

    // setup arguments
    args.cmdId = cmdId;
    args.param1 = param1;
    args.param2 = param2;
    args.param3 = param3;
    args.param4 = param4;

    // call WinThreadExecProc on the toolkit thread
    retVal = AwtToolkit::GetInstance().SendMessage(WM_AWT_EXECUTE_SYNC,
                                                   (WPARAM)peerObjectGlobalRef,
                                                   (LPARAM)&args);
    return retVal;
}

LRESULT AwtObject::WinThreadExecProc(ExecuteArgs * args)
{
    DASSERT(FALSE); // no default handler
    return 0L;
}

/************************************************************************
 * WObjectPeer native methods
 */

extern "C" {

JNIEXPORT void JNICALL
Java_sun_awt_windows_WObjectPeer_initIDs(JNIEnv *env, jclass cls) {
    TRY;

    AwtObject::wObjectPeerClass = (jclass)env->NewGlobalRef(cls);
    AwtObject::pDataID = env->GetFieldID(cls, "pData", "J");
    AwtObject::destroyedID = env->GetFieldID(cls, "destroyed", "Z");
    AwtObject::targetID = env->GetFieldID(cls, "target",
                                              "Ljava/lang/Object;");

    AwtObject::getPeerForTargetMID =
        env->GetStaticMethodID(cls, "getPeerForTarget",
                         "(Ljava/lang/Object;)Lsun/awt/windows/WObjectPeer;");

    AwtObject::createErrorID = env->GetFieldID(cls, "createError", "Ljava/lang/Error;");

    DASSERT(AwtObject::pDataID != NULL);
    DASSERT(AwtObject::destroyedID != NULL);
    DASSERT(AwtObject::targetID != NULL);
    DASSERT(AwtObject::getPeerForTargetMID != NULL);
    DASSERT(AwtObject::createErrorID != NULL);

    CATCH_BAD_ALLOC;
}

} /* extern "C" */
