/*******************************************************************************
 * Copyright (c) 2000, 2016 IBM Corporation and others.
 * All rights reserved. This program and the accompanying materials
 * are made available under the terms of the Eclipse Public License v1.0
 * which accompanies this distribution, and is available at
 * http://www.eclipse.org/legal/epl-v10.html
 *
 * Contributors:
 *     IBM Corporation - initial API and implementation
 *******************************************************************************/
package org.eclipse.swt.tests.junit;

import java.util.HashMap;

import org.eclipse.swt.SWT;
import org.eclipse.swt.graphics.Point;
import org.eclipse.swt.widgets.Display;
import org.eclipse.swt.widgets.Event;


public class ConsistencyUtility {

    static HashMap<String, String[]> eventOrdering = new HashMap<>();
    static HashMap<String, Integer> eventTypes = new HashMap<>();
    static {

        eventOrdering.put("DoubleClick", 			new String[] {"MouseDown", "Selection:", "MouseUp", "MouseDown", "MouseDoubleClick", "DefaultSelection", "MouseUp"});
        eventOrdering.put("DragDetect", 			new String[] {"MouseDown", "DragDetect", "MouseUp"});
        eventOrdering.put("EnterSelection", 		new String[] {"Traverse:Return", "KeyDown", "DefaultSelection", "KeyUp"});
        eventOrdering.put("KeySelection", 			new String[] {"Traverse:Arrow Next", "KeyDown", "Selection:", "KeyUp"});
        eventOrdering.put("MenuDetect", 			new String[] {"MouseDown", "MenuDetect", "MouseUp"});

        eventOrdering.put("ButtonMouseSelection", 	new String[] {"MouseDown", "MouseUp", "Selection:"});
        eventOrdering.put("ComboMouseSelection",	new String[] {"MouseDown", "MouseUp", "Verify", "Modify", "Selection:"});
        eventOrdering.put("CComboMouseSelection",	new String[] {"Modify", "Selection:"});
        eventOrdering.put("ExpandBarMouseSelection",new String[] {"MouseDown", "MouseUp", "Selection:"});
        eventOrdering.put("ListMouseSelection", 	new String[] {"MouseDown", "MouseUp", "Selection:"});
        eventOrdering.put("SashMouseSelection", 	new String[] {"Selection:Drag", "MouseDown", "Selection:", "MouseUp"});
        eventOrdering.put("TabFolderMouseSelection",new String[] {"MouseDown", "Selection:", "MouseUp" });
        eventOrdering.put("TableMouseSelection",	new String[] {"MouseDown", "Selection:", "MouseUp" });
        eventOrdering.put("ToolBarMouseSelection", 	new String[] {"MouseDown", "MouseUp", "Selection:"});
        eventOrdering.put("TreeMouseSelection",		new String[] {"MouseDown", "Selection:", "MouseUp" });
        eventOrdering.put("TableTreeMouseSelection",new String[] {"MouseDown", "Selection:", "MouseUp" });
        eventOrdering.put("CTabFolderMouseSelection",new String[] {"Selection:", "MouseDown", "MouseUp" });

        eventOrdering.put("ListDoubleClick", 		new String[] {"MouseDown", "MouseUp", "Selection:", "MouseDown", "MouseDoubleClick", "DefaultSelection", "MouseUp"});
        eventOrdering.put("ButtonEnterSelection", 	new String[] {"Traverse:Return", "KeyDown", "KeyUp"});
        eventOrdering.put("ExpandBarEnterSelection",new String[] {"Traverse:Return", "Selection:", "KeyDown", "KeyUp"});
        eventOrdering.put("CComboEnterSelection", 	new String[] {"Traverse:Return", "DefaultSelection", "KeyDown", "KeyUp"});
        eventOrdering.put("ToolBarEnterSelection", 	new String[] {"Traverse:Return", "Selection:", "KeyDown", "KeyUp"});
        eventOrdering.put("TreeDragDetect", 		new String[] {"MouseDown", "Selection:", "DragDetect", "MouseUp"});
        eventOrdering.put("TableTreeDragDetect", 	new String[] {"MouseDown", "Selection:", "DragDetect", "MouseUp"});
        eventOrdering.put("TableMenuDetect", 		new String[] {"MenuDetect", "MouseDown", "Selection:", "MouseUp"});
        eventOrdering.put("TableTreeMenuDetect",	new String[] {"MenuDetect", "MouseDown", "Selection:", "MouseUp"});

        eventOrdering.put("ButtonSpaceSelection", 	new String[] {"Traverse:Mnemonic", "KeyDown", "KeyUp", "Selection:"});
        eventOrdering.put("ExpandBarSpaceSelection",new String[] {"MouseDown", "MouseUp", "Selection:", "Traverse:Mnemonic", "KeyDown", "KeyUp"});
        eventOrdering.put("ListSpaceSelection", 	new String[] {"Selection:", "KeyDown", "KeyUp"});
        eventOrdering.put("ToolBarSpaceSelection", 	new String[] {"MouseDown", "MouseUp", "Selection:", "Traverse:Mnemonic", "KeyDown", "KeyUp"});
        eventOrdering.put("TreeSpaceSelection", 	new String[] {"Selection:", "KeyDown", "KeyUp"});
        eventOrdering.put("TableTreeSpaceSelection",new String[] {"KeyDown", "KeyUp"});

        eventOrdering.put("ComboKeySelection", 		new String[] {"KeyDown", "Verify", "Modify", "Selection:", "KeyUp"});
        eventOrdering.put("CComboKeySelection", 	new String[] {"Traverse:Arrow Next", "Modify", "Selection:", "KeyDown", "KeyUp"});
        eventOrdering.put("CTabFolderKeySelection",	new String[] {"Traverse:Arrow Next", "Selection:", "KeyDown", "KeyUp"});
        eventOrdering.put("SliderKeySelection",		new String[] {"Traverse:Arrow Next", "KeyDown", "Selection:Arrow Down", "KeyUp" });

        eventOrdering.put("SliderArrowSelection",	new String[] {"MouseDown", "Selection:Arrow Down", "MouseUp" });

        eventOrdering.put("CoolBarChevronDragDetect",new String[] {"MouseDown", "DragDetect"});
        eventOrdering.put("CoolBarChevronMenuDetect",new String[] {"MouseDown", "Selection:Arrow"});
        eventOrdering.put("CoolBarChevronMouseSelection",new String[] {"MouseDown", "Selection:Arrow", });

        eventOrdering.put("ScaleTroughSelection",	new String[] {"Selection:", "MouseDown", "MouseUp" });
        eventOrdering.put("SliderTroughSelection",	new String[] {"MouseDown", "Selection:Page Down", "MouseUp" });
        eventOrdering.put("ScaleThumbSelection",	new String[] {"Selection:", "MouseDown", "MouseUp" });
        eventOrdering.put("SliderThumbSelection",	new String[] {"MouseDown", "Selection:Drag", "MouseUp" });

        eventOrdering.put("ShellClose",				new String[] {"Close", "Dispose"});
        eventOrdering.put("ShellDispose",			new String[] {"Dispose"});
        eventOrdering.put("ShellIconify",			new String[] {"FocusOut", "Iconify", "Deactivate", "Deiconify", "Activate", "FocusIn", "Activate"});
        eventOrdering.put("ShellOpen",				new String[] {"Activate", "FocusIn", "Show"});

        eventOrdering.put("TabFolderPgdwnSelection",new String[] {"KeyDown", "Traverse:Page Next", "Selection:", "KeyUp", "KeyUp"});
        eventOrdering.put("TabFolderPgupSelection", new String[] {"KeyDown", "Traverse:Page Previous", "Selection:", "KeyUp", "KeyUp"});
        eventOrdering.put("CTabFolderPgdwnSelection",new String[] {"KeyDown", "Selection:", "Traverse:None", "KeyUp", "KeyUp"});
        eventOrdering.put("CTabFolderPgupSelection",new String[] {"KeyDown", "Selection:", "Traverse:None", "KeyUp", "KeyUp"});

        eventOrdering.put("StyledTextModify",		new String[] {"Verify", "Modify", "KeyDown", "KeyUp"});
        eventOrdering.put("TextModify",				new String[] {"KeyDown", "Verify", "Modify", "KeyUp"});

        eventOrdering.put("TreeKeyExpand", 			new String[] {"Traverse:Arrow Next", "KeyDown", "Expand", "KeyUp"});
        eventOrdering.put("TreeMouseExpand", 		new String[] {"Expand", "MouseDown", "MouseUp"});
        eventOrdering.put("TableTreeKeyExpand", 	new String[] {"Traverse:Arrow Next", "Expand", "KeyDown", "KeyUp"});
        eventOrdering.put("TableTreeMouseExpand", 	new String[] {"Expand", "MouseDown", "Selection:", "MouseUp"});

        eventOrdering.put("TableTreeTable", 		new String[] {"MouseDown", "MouseUp", "MouseDoubleClick", "KeyDown", "KeyUp", "MenuDetect", "DragDetect", "Traverse"});

        eventTypes.put("None", Integer.valueOf(SWT.None));
        eventTypes.put("KeyDown", Integer.valueOf(SWT.KeyDown));
        eventTypes.put("KeyUp", Integer.valueOf(SWT.KeyUp));
        eventTypes.put("MouseDown", Integer.valueOf(SWT.MouseDown));
        eventTypes.put("MouseUp", Integer.valueOf(SWT.MouseUp));
        eventTypes.put("MouseMove", Integer.valueOf(SWT.MouseMove));
        eventTypes.put("MouseEnter", Integer.valueOf(SWT.MouseEnter));
        eventTypes.put("MouseExit", Integer.valueOf(SWT.MouseExit));
        eventTypes.put("MouseDoubleClick", Integer.valueOf(SWT.MouseDoubleClick));
        eventTypes.put("Paint", Integer.valueOf(SWT.Paint));
        eventTypes.put("Move", Integer.valueOf(SWT.Move));
        eventTypes.put("Resize", Integer.valueOf(SWT.Resize));
        eventTypes.put("Dispose", Integer.valueOf(SWT.Dispose));
        eventTypes.put("Selection", Integer.valueOf(SWT.Selection));
        eventTypes.put("DefaultSelection", Integer.valueOf(SWT.DefaultSelection));
        eventTypes.put("FocusIn", Integer.valueOf(SWT.FocusIn));
        eventTypes.put("FocusOut", Integer.valueOf(SWT.FocusOut));
        eventTypes.put("Expand", Integer.valueOf(SWT.Expand));
        eventTypes.put("Collapse", Integer.valueOf(SWT.Collapse));
        eventTypes.put("Iconify", Integer.valueOf(SWT.Iconify));
        eventTypes.put("Deiconify", Integer.valueOf(SWT.Deiconify));
        eventTypes.put("Close", Integer.valueOf(SWT.Close));
        eventTypes.put("Show", Integer.valueOf(SWT.Show));
        eventTypes.put("Hide", Integer.valueOf(SWT.Hide));
        eventTypes.put("Modify", Integer.valueOf(SWT.Modify));
        eventTypes.put("Verify", Integer.valueOf(SWT.Verify));
        eventTypes.put("Activate", Integer.valueOf(SWT.Activate));
        eventTypes.put("Deactivate", Integer.valueOf(SWT.Deactivate));
        eventTypes.put("Help", Integer.valueOf(SWT.Help));
        eventTypes.put("DragDetect", Integer.valueOf(SWT.DragDetect));
        eventTypes.put("Arm", Integer.valueOf(SWT.Arm));
        eventTypes.put("Traverse", Integer.valueOf(SWT.Traverse));
        eventTypes.put("MouseHover", Integer.valueOf(SWT.MouseHover));
        eventTypes.put("HardKeyDown", Integer.valueOf(SWT.HardKeyDown));
        eventTypes.put("HardKeyUp", Integer.valueOf(SWT.HardKeyUp));
        eventTypes.put("MenuDetect", Integer.valueOf(SWT.MenuDetect));
        eventTypes.put("SetData", Integer.valueOf(SWT.SetData));
    }

    static String[] eventNames = {
		"None", 			"KeyDown", 		"KeyUp", 			"MouseDown",
		"MouseUp",			"MouseMove",	"MouseEnter",		"MouseExit",
		"MouseDoubleClick",	"Paint",		"Move",				"Resize",
		"Dispose",			"Selection",	"DefaultSelection",	"FocusIn",
		"FocusOut",			"Expand",		"Collapse",			"Iconify",
		"Deiconify",		"Close",		"Show",				"Hide",
		"Modify",			"Verify",		"Activate",			"Deactivate",
		"Help",				"DragDetect",	"Arm",				"Traverse",
		"MouseHover",		"HardKeyDown",	"HardKeyUp",		"MenuDetect",
		"SetData"};

    static int[] convertEventNames(String[] origNames) {
        String[] names = new String[origNames.length];
        System.arraycopy(origNames, 0, names, 0, origNames.length);
        names = removeDuplicates(names);
        int[] types = new int[names.length];
        for(int i=0; i<names.length; i++) {
            types[i] = eventTypes.get(names[i]).intValue();
        }
        return types;
    }

    private static String[] removeDuplicates(String[] names) {
        int dups=0;
        for(int i=0; i<names.length; i++) {
            int index = names[i].indexOf(':');
            if(index != -1)
                names[i] = names[i].substring(0, index);
            for(int j=0; j<i; j++) {
                if(names[i].equals(names[j])) {
                    for(int k=i+1; k<names.length; k++) {
                        names[k-1] = names[k];
                    }
                    names[names.length-1] = "duplicate"+ dups;
                    dups++;
                }
            }
        }
        String[] temp = new String[names.length-dups];
        System.arraycopy(names, 0, temp, 0, names.length-dups);
        return temp;
    }

    public static String[] selectionTypes = {
        "Drag", 		"Home",  			"End", 				"Arrow Down",
        "Arrow Up", 	"Page Down", 		"Page Up", 			"Check",
        "Arrow",
    };

    public static int[] [] selectionConversion = {
        {SWT.DRAG, 0},
        {SWT.HOME, 1},
        {SWT.END, 2},
        {SWT.ARROW_DOWN, 3},
        {SWT.ARROW_UP, 4},
        {SWT.PAGE_DOWN, 5},
        {SWT.PAGE_UP, 6},
        {SWT.CHECK, 7},
        {SWT.ARROW, 8},
    };

    static String getSelectionType(int type) {
        for(int i=0; i<selectionConversion.length;i++) {
            if(type == selectionConversion[i][0])
                return selectionTypes[selectionConversion[i][1]];
        }
        return "";
    }

    static String[] traversalTypes = {
    	    "None", 		"Escape", 			"Return", 			"Tab Previous",
    	    "Tab Next", 	"Arrow Previous",	"Arrow Next", 		"Mnemonic",
    	    "Page Previous", "Page Next"};

    static String getTraversalType(int type) {
        int pow = 0;
        if(type != 0)
            pow =(int)(Math.log(type)/Math.log(2));
        return traversalTypes[pow];
    }

    static final int NONE = 0;
    static final int SHELL_ICONIFY = 1;
    static final int KEY_PRESS = 10;
    static final int DOUBLE_KEY_PRESS = 20;
    static final int MOUSE_CLICK = 30;
    static final int MOUSE_DOUBLECLICK = 40;
    static final int MOUSE_DRAG = 50;
    static final int SELECTION = 60;

    static final int ESCAPE_MENU = 1;


    //posts a click at display mapped x and y with button button
    static boolean postClick(Display display, int x, int y, int button) {
        Event event = new Event();
        event.type = SWT.MouseMove;
        event.x = x;
        event.y = y;
        if(!display.post(event))  {
            System.out.println("MouseMove not posted");
            return false;
        }

        event = new Event();
        event.type = SWT.MouseDown;
        event.button = button;
        if(!display.post(event)) {
            System.out.println("MouseDown not posted");
            return false;
        }
        event = new Event();
        event.type = SWT.MouseUp;
        event.button = button;
        if(!display.post(event)) {
            System.out.println("MouseUp not posted");
            //TODO: potentially dangerous to have a mousedown and no mouseup
            //force the issue?
            return false;
        }
//	  	try {
//	        Thread.sleep(1600);
//	    } catch(InterruptedException ie) {}
        return true;
    }

    static boolean postClick(Display display, Point pt, int button) {
        return postClick(display, pt.x, pt.y, button);
    }

    //doubleclicks at display mapped pt with button button
    static boolean postDoubleClick(Display display, Point pt, int button) {
        boolean ret = postClick(display, pt, button);
        ret &= postClick(display, pt, button);
//	  	try {
//	        Thread.sleep(1600);
//	    } catch(InterruptedException ie) {}
        return ret;
    }

    //post a key press
    static boolean postKeyPress(Display display, int ch, int keycode) {
        Event event = new Event();
        event.type = SWT.KeyDown;
        event.character = (char)ch;
        event.keyCode = keycode;
        if(!display.post(event)) {
            System.out.println("KeyDown not posted");
            return false;
        }
        event = new Event();
        event.type = SWT.KeyUp;
        event.character = (char)ch;
        event.keyCode = keycode;
        if(!display.post(event)) {
            System.out.println("KeyUp not posted");
            //TODO: potentially dangerous to have a keydown and no keyup
            //force the issue?
            return false;
        }
        return true;
    }

    //post pressing and holding ch1/keycode1 and then pressing ch2/keycode2
    static boolean postDoubleKeyPress(Display display, int ch1, int keycode1,
            						  int ch2, int keycode2) {
        Event event = new Event();
        event.type = SWT.KeyDown;
        event.character = (char)ch1;
        event.keyCode = keycode1;
        if(!display.post(event)) {
            System.out.println("KeyDown not posted");
            return false;
        }
        postKeyPress(display, ch2, keycode2);
        event = new Event();
        event.type = SWT.KeyUp;
        event.character = (char)ch1;
        event.keyCode = keycode1;
        if(!display.post(event)) {
            System.out.println("KeyUp not posted");
            //TODO: potentially dangerous to have a keydown and no keyup
            //force the issue?
            return false;
        }
        return true;
    }

    //posts a drag from display mapped origin to destination
    //the button to drag with is system dependent
    static boolean postDrag(Display display, Point origin, Point destination) {
        int button = determineDrag();
        Event event = new Event();
        event.type = SWT.MouseMove;
        event.x = origin.x;
        event.y = origin.y;
        if(!display.post(event))  {
            System.out.println("MouseMove not posted");
            return false;
        }

        event = new Event();
        event.type = SWT.MouseDown;
        event.button = button;
        if(!display.post(event)) {
            System.out.println("MouseDown not posted");
            return false;
        }

        event = new Event();
        event.type = SWT.MouseMove;
        event.x = destination.x;
        event.y = destination.y;
        if(!display.post(event))  {
            System.out.println("MouseMove not posted");
            return false;
        }

        event = new Event();
        event.type = SWT.MouseUp;
        event.button = button;
        if(!display.post(event)) {
            System.out.println("MouseUp not posted");
            //TODO: potentially dangerous to have a mousedown and no mouseup
            //force the issue?
            return false;
        }
        return true;
    }

    //determines which button to drag with
    private static int determineDrag() {
        if(SwtTestUtil.isWindows || SwtTestUtil.isGTK)
            return 1;
        return 2;
    }

    //posts a selection ie clicks on pt1, then click on pt2 (for example, selecting
    //one of the options in a combo by dropping down the list)
    static boolean postSelection(final Display display, Point pt1, Point pt2) {
        boolean ret = postClick(display, pt1, 1);
        display.syncExec(new Thread() {
            @Override
			public void run() {
                display.update();
        }});
        ret &= postClick(display, pt2, 1);
        return ret;
    }

    //iconifies the shell. pt is a system dependent point on the shell.
    static boolean postShellIconify(Display display, Point pt, int button) {
        int x = pt.x;
        int y = pt.y - 10;
        if(SwtTestUtil.isWindows) {
            x += -35;
        } else if(SwtTestUtil.isLinux) {
        	x += -16;
        }
        return postClick(display, x, y, button);
    }
}
