/*
 * Copyright (c) 2010, Oracle and/or its affiliates. All rights reserved.
 */
package com.sun.glass.ui.win;

import com.sun.glass.ui.Application;
import com.sun.glass.ui.CommonDialogs.ExtensionFilter;
import com.sun.glass.ui.Cursor;
import com.sun.glass.ui.Launchable;
import com.sun.glass.ui.Menu;
import com.sun.glass.ui.MenuBar;
import com.sun.glass.ui.MenuItem;
import com.sun.glass.ui.Pixels;
import com.sun.glass.ui.Pen;
import com.sun.glass.ui.Robot;
import com.sun.glass.ui.Screen;
import com.sun.glass.ui.Size;
import com.sun.glass.ui.Timer;
import com.sun.glass.ui.View;
import com.sun.glass.ui.Window;

import java.nio.ByteBuffer;
import java.nio.IntBuffer;
import java.security.AccessController;
import java.security.PrivilegedAction;
import java.util.List;


public class WinApplication extends Application {

    private static native void initIDs();
    static {
        Application.loadNativeLibrary();
        initIDs();
    }

    // returng toolkit window HWND
    private native long _init();
    private native void _runLoop(String args[], Launchable launchable);
    private native void _terminateLoop();

    @Override protected void runLoop(final String args[], final Launchable launchable) {
        boolean isEventThread = AccessController
            .doPrivileged(new PrivilegedAction<Boolean>() {
                public Boolean run() {
                    Boolean result = Boolean.getBoolean("javafx.embed.isEventThread");
                    return result == null ? false : result.booleanValue();
                    }
                });
        if (isEventThread) {
            _init();
            setEventThread(Thread.currentThread());
            launchable.finishLaunching(args);
            return;
        }
    	final Thread toolkitThread =
            AccessController.doPrivileged(new PrivilegedAction<Thread>() {
                public Thread run() {
                    Thread th = new Thread(new Runnable() {
                        public void run() {
                            _init();
                            _runLoop(args, launchable);
                        }
                    }, "WindowsNativeRunloopThread");
                    return th;
                }
            });   
        setEventThread(toolkitThread);
        toolkitThread.start();
    }

    @Override protected void finishTerminating() {
        final Thread toolkitThread = getEventThread();
        if (toolkitThread != null) {
            _terminateLoop();
            setEventThread(null);
        }
        super.finishTerminating();
    }

    @Override public boolean shouldUpdateWindow() {
        return true;
    }

    @Override native protected Object _enterNestedEventLoop();
    @Override native protected void _leaveNestedEventLoop(Object retValue);


    // FACTORY METHODS

    @Override public Window createWindow(Window owner, Screen screen, int styleMask) {
        return new WinWindow(owner, screen, styleMask);
    }

    @Override public Window createWindow(long parent) {
        return new WinChildWindow(parent);
    }

    @Override public View createView(Pen pen) {
        return new WinView(pen);
    }

    @Override public Cursor createCursor(int type) {
        return new WinCursor(type);
    }

    @Override public Cursor createCursor(int x, int y, Pixels pixels) {
        return new WinCursor(x, y, pixels);
    }

    @Override protected void staticCursor_setVisible(boolean visible) {
        WinCursor.setVisible_impl(visible);
    }

    @Override protected Size staticCursor_getBestSize(int width, int height) {
        return WinCursor.getBestSize_impl(width, height);
    }

    @Override public Pixels createPixels(int width, int height, ByteBuffer data) {
        return new WinPixels(width, height, data);
    }

    @Override public Pixels createPixels(int width, int height, IntBuffer data) {
        return new WinPixels(width, height, data);
    }

    @Override protected int staticPixels_getNativeFormat() {
        return WinPixels.getNativeFormat_impl();
    }

    @Override public Robot createRobot() {
        return new WinRobot();
    }

    @Override protected Screen staticScreen_getDeepestScreen() {
        return WinScreen.getDeepestScreen_impl();
    }

    @Override protected Screen staticScreen_getMainScreen() {
        return WinScreen.getMainScreen_impl();
    }
    @Override protected Screen staticScreen_getScreenForLocation(int x, int y) {
        return WinScreen.getScreenForLocation_impl(x, y);
    }

    @Override protected Screen staticScreen_getScreenForPtr(long screenPtr) {
        return WinScreen.getScreenForPtr_impl(screenPtr);
    }

    @Override protected List<Screen> staticScreen_getScreens() {
        return WinScreen.getScreens_impl();
    }

    @Override public Timer createTimer(Runnable runnable) {
        return new WinTimer(runnable);
    }

    @Override protected int staticTimer_getMinPeriod() {
        return WinTimer.getMinPeriod_impl();
    }

    @Override protected int staticTimer_getMaxPeriod() {
        return WinTimer.getMaxPeriod_impl();
    }

    @Override protected String[] staticCommonDialogs_showFileChooser(Window owner, String folder, String title, int type,
                                             boolean multipleMode, ExtensionFilter[] extensionFilters) {
        return WinCommonDialogs.showFileChooser_impl(owner, folder, title, type, multipleMode, extensionFilters);
    }

    @Override protected String staticCommonDialogs_showFolderChooser(Window owner, String folder, String title) {
        return WinCommonDialogs.showFolderChooser_impl(owner, folder, title);
    }

    @Override protected long staticView_getMultiClickTime() {
        return WinView.getMultiClickTime_impl();
    }

    @Override protected int staticView_getMultiClickMaxX() {
        return WinView.getMultiClickMaxX_impl();
    }

    @Override protected int staticView_getMultiClickMaxY() {
        return WinView.getMultiClickMaxY_impl();
    }
    
    @Override native protected void _invokeAndWait(Runnable runnable);

    @Override native protected void _invokeLater(Runnable runnable);

    @Override native protected void _postOnEventQueue(Runnable runnable);

    @Override
    public boolean supportsTransparentWindows() {
        return true;
    }
}
