/*
 * Copyright (c) 2011, Oracle and/or its affiliates. All rights reserved.
 */
#include "common.h"
#include "Utils.h"
#include "Timer.h"
#include "com_sun_glass_ui_win_WinTimer.h"

UINT Timer::timersCount = 0;
UINT Timer::wTimerRes = 0;
TIMECAPS Timer::tc = {0, 0};

class RunnableTimer : public Timer {
    public:
        static jlong Start(jobject r, jint period)
        {
            try {
                return ptr_to_jlong(new RunnableTimer(r, period));
            } catch (...) {
                return 0;
            }
        }

        static void Stop(jlong timer)
        {
            delete (RunnableTimer*)jlong_to_ptr(timer);
        }

        RunnableTimer(jobject r, jint period) : env(NULL), runnable(r)
        {
            if (!start((UINT)period)) {
                throw Exception();
            }
        }

        virtual void TimerCallback()
        {
            GetEnv()->CallVoidMethod(runnable, javaIDs.Runnable.run);
            CheckAndClearException(GetEnv());
        }
    private:
        JNIEnv * env;
        JGlobalRef<jobject> runnable;

        JNIEnv * GetEnv()
        {
            if (!env) {
                // We never DetachCurrentThread() but that's OK. Even if a
                // thread is re-used, the Attach*() simply fills in the env.
                GetJVM()->AttachCurrentThreadAsDaemon((void**)&env, NULL);
            }
            return env;
        }
};

extern "C" {

/*
 * Class:     com_sun_glass_ui_win_WinTimer
 * Method:    _start
 * Signature: (I)J
 */
JNIEXPORT jlong JNICALL Java_com_sun_glass_ui_win_WinTimer__1start
  (JNIEnv * env, jobject jThis, jobject runnable, jint period)
{
    return RunnableTimer::Start(runnable, period);
}

/*
 * Class:     com_sun_glass_ui_win_WinTimer
 * Method:    _stop
 * Signature: (J)V
 */
JNIEXPORT void JNICALL Java_com_sun_glass_ui_win_WinTimer__1stop
  (JNIEnv * env, jobject jThis, jlong timer)
{
    RunnableTimer::Stop(timer);
}

/*
 * Class:     com_sun_glass_ui_win_WinTimer
 * Method:    _getMinPeriod
 * Signature: ()I
 */
JNIEXPORT jint JNICALL Java_com_sun_glass_ui_win_WinTimer__1getMinPeriod
  (JNIEnv * env, jclass cls)
{
    return Timer::GetMinPeriod();
}

/*
 * Class:     com_sun_glass_ui_win_WinTimer
 * Method:    _getMaxPeriod
 * Signature: ()I
 */
JNIEXPORT jint JNICALL Java_com_sun_glass_ui_win_WinTimer__1getMaxPeriod
  (JNIEnv * env, jclass cls)
{
    return Timer::GetMaxPeriod();
}

} //extern "C"

