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

package com.sun.glass.tests;

import static org.junit.Assert.*;
import org.junit.Test;
import org.junit.Before;
import org.junit.After;
import org.junit.BeforeClass;
import org.junit.AfterClass;

import com.sun.glass.ui.*;
import com.sun.glass.events.*;
import java.util.Map;
import java.util.List;

public class GrabFocus
{
    private static final int WINDOW_X = 101;
    private static final int WINDOW_Y = 102;
    private static final int WINDOW_W = 512;
    private static final int WINDOW_H = 256;

    private static final int WINDOW_CENTER_X = WINDOW_X + WINDOW_W / 2;
    private static final int WINDOW_CENTER_Y = WINDOW_Y + WINDOW_H / 2;

    private static final int WINDOW_CAPTION_X = WINDOW_X + WINDOW_W / 2;
    private static final int WINDOW_CAPTION_Y = WINDOW_Y + 7;
    //NOTE: the +7 above is an empiric value. Better to use View.getY()/2,
    //      but we need no view in this test.

    private static volatile Window mainWindow;
    private static volatile Robot robot;

    private static volatile boolean focusUngrabReceived = false;
    private static volatile boolean grabFocusSucceeded = false;

    @BeforeClass
    static public void prepare()
    {
        try
        {
            Application app = Application.GetApplication();
            Screen screen = Screen.getMainScreen();
            
            int windowMask = Window.TITLED|Window.CLOSABLE|Window.MINIMIZABLE;
            mainWindow = app.createWindow(screen, windowMask);
            mainWindow.setEventHandler(new Window.EventHandler() {
                @Override public void handleWindowEvent(Window window, long time, int type) {
                    if (type == WindowEvent.FOCUS_UNGRAB) {
                        focusUngrabReceived = true;
                    }
                }
            });
            mainWindow.setPosition(WINDOW_X, WINDOW_Y);
            mainWindow.setSize(WINDOW_W, WINDOW_H);
            mainWindow.setTitle(app.getName());
            mainWindow.setVisible(true);

            mainWindow.toFront();
            mainWindow.requestFocus();
            
            robot = app.createRobot();

            Thread.sleep(1000); // let things settle down
        }
        catch (Throwable t)
        {
            t.printStackTrace();
            System.exit(0);
        }
    }
    
    @AfterClass
    static public void finish()
    {
        mainWindow.close();
    }
            
    private static volatile RuntimeException throwable;
    private static void exec(final Runnable runnable) {
        throwable = null;

        Application.GetApplication().invokeAndWait(new Runnable() {
            @Override public void run() {
                try {
                    runnable.run();
                } catch (RuntimeException t) {
                    throwable = t;
                }
            }
        });

        if (throwable != null) {
            throw throwable;
        }
    }

    private static void mouseClick(int x, int y) {
        robot.mouseMove(x, y);
        robot.mousePress(1);
        robot.mouseRelease(1);

        try { Thread.sleep(500); } catch (InterruptedException e) {}
    }

    @Test public void checkProgramaticalUngrab() {
        exec(new Runnable() {
            @Override public void run() {
                grabFocusSucceeded = mainWindow.grabFocus();
            }
        });
        if (!grabFocusSucceeded) {
            return;
        }
        assertFalse(focusUngrabReceived);
        exec(new Runnable() {
            @Override public void run() {
                mainWindow.ungrabFocus();
            }
        });
        assertTrue(focusUngrabReceived);

        focusUngrabReceived = false;
    }

    @Test public void checkCaptionClickUngrab() {
        exec(new Runnable() {
            @Override public void run() {
                grabFocusSucceeded = mainWindow.grabFocus();
            }
        });
        if (!grabFocusSucceeded) {
            return;
        }
        assertFalse(focusUngrabReceived);

        mouseClick(WINDOW_CAPTION_X, WINDOW_CAPTION_Y);

        assertTrue(focusUngrabReceived);

        focusUngrabReceived = false;
    } 

    @Test public void checkCenterClickNoUngrab() {
        exec(new Runnable() {
            @Override public void run() {
                grabFocusSucceeded = mainWindow.grabFocus();
            }
        });
        if (!grabFocusSucceeded) {
            return;
        }
        assertFalse(focusUngrabReceived);

        mouseClick(WINDOW_CENTER_X, WINDOW_CENTER_Y);

        assertFalse(focusUngrabReceived);

        exec(new Runnable() {
            @Override public void run() {
                mainWindow.ungrabFocus();
            }
        });
        focusUngrabReceived = false;
    }
}
