package guitests;

import javafx.scene.input.KeyCode;
import org.junit.Test;
import ui.UI;
import ui.components.KeyboardShortcuts;
import ui.listpanel.ListPanel;
import util.events.PanelClickedEventHandler;
import util.events.IssueSelectedEventHandler;
import util.events.testevents.UIComponentFocusEvent;
import util.events.testevents.UIComponentFocusEventHandler;

import static org.junit.Assert.assertEquals;
import static ui.components.KeyboardShortcuts.DOUBLE_PRESS;

public class KeyboardShortcutsTest extends UITest {

    private UIComponentFocusEvent.EventType uiComponentFocusEventType;
    private int selectedIssueId;
    private int panelIndex;

    @Test
    public void keyboardShortcutsTest() {
        UI.events.registerEvent((IssueSelectedEventHandler) e -> selectedIssueId = e.id);
        UI.events.registerEvent((UIComponentFocusEventHandler) e -> uiComponentFocusEventType = e.eventType);
        UI.events.registerEvent((PanelClickedEventHandler) e -> panelIndex = e.panelIndex);
        clearSelectedIssueId();
        clearUiComponentFocusEventType();
        clearPanelIndex();

        // maximize
        assertEquals(false, stage.getMinWidth() > 500);
        press(KeyCode.CONTROL).press(KeyCode.X).release(KeyCode.X).release(KeyCode.CONTROL);
        assertEquals(true, stage.getMinWidth() > 500);

        // mid-sized window
        press(KeyCode.CONTROL).press(KeyCode.D).release(KeyCode.D).release(KeyCode.CONTROL);
        assertEquals(false, stage.getMinWidth() > 500);

        // jump from filter box to first issue
        press(KeyCode.CONTROL).press(KeyCode.DOWN).release(KeyCode.DOWN).release(KeyCode.CONTROL);
        assertEquals(10, selectedIssueId);
        clearSelectedIssueId();

        // jump from issue list to filter box
        press(KeyCode.CONTROL).press(KeyCode.UP).release(KeyCode.UP).release(KeyCode.CONTROL);
        assertEquals(UIComponentFocusEvent.EventType.FILTER_BOX, uiComponentFocusEventType);
        clearUiComponentFocusEventType();

        // jump from filter box to first issue
        push(DOUBLE_PRESS).push(DOUBLE_PRESS);
        assertEquals(10, selectedIssueId);
        clearSelectedIssueId();

        // jump from issue list to filter box
        push(DOUBLE_PRESS).push(DOUBLE_PRESS);
        assertEquals(UIComponentFocusEvent.EventType.FILTER_BOX, uiComponentFocusEventType);
        clearUiComponentFocusEventType();

        push(DOUBLE_PRESS).push(DOUBLE_PRESS);

        // jump to last issue
        push(KeyCode.END);
        assertEquals(1, selectedIssueId);
        clearSelectedIssueId();

        // jump to first issue
        push(KeyCode.HOME);
        sleep(1000);
        assertEquals(10, selectedIssueId);
        clearSelectedIssueId();

        push(getKeyCode("DOWN_ISSUE"));
        assertEquals(9, selectedIssueId);
        clearSelectedIssueId();
        push(getKeyCode("DOWN_ISSUE"));
        assertEquals(8, selectedIssueId);
        clearSelectedIssueId();
        push(getKeyCode("UP_ISSUE"));
        assertEquals(9, selectedIssueId);
        clearSelectedIssueId();

        press(KeyCode.CONTROL).press(KeyCode.P).release(KeyCode.P).release(KeyCode.CONTROL);
        push(DOUBLE_PRESS).push(DOUBLE_PRESS);

        push(getKeyCode("RIGHT_PANEL"));
        assertEquals(0, panelIndex);
        clearPanelIndex();
        push(getKeyCode("LEFT_PANEL"));
        assertEquals(1, panelIndex);
        clearPanelIndex();
        push(getKeyCode("RIGHT_PANEL"));
        assertEquals(0, panelIndex);
        clearPanelIndex();
        push(getKeyCode("LEFT_PANEL"));
        assertEquals(1, panelIndex);
        clearPanelIndex();

        click("#dummy/dummy_col1_1");

        // mark as read
        ListPanel issuePanel = find("#dummy/dummy_col1");
        push(KeyCode.HOME);
        int issueIdBeforeMark = selectedIssueId;
        int issueIdExpected = issueIdBeforeMark - 1;
        push(getKeyCode("MARK_AS_READ"));
        assertEquals(issueIdExpected, selectedIssueId);
        push(getKeyCode("UP_ISSUE")); //required since focus has changed to next issue
        assertEquals(true, issuePanel.getSelectedIssue().isCurrentlyRead());
        
        push(KeyCode.END);
        push(getKeyCode("MARK_AS_READ"));
        assertEquals(1, selectedIssueId);
        assertEquals(true, issuePanel.getSelectedIssue().isCurrentlyRead());
        
        // mark as unread
        push(getKeyCode("MARK_AS_UNREAD"));
        assertEquals(false, issuePanel.getSelectedIssue().isCurrentlyRead());

        // minimize window
        press(KeyCode.CONTROL).press(KeyCode.N).release(KeyCode.N).release(KeyCode.CONTROL); // run this last
        assertEquals(true, stage.isIconified());
    }

    public KeyCode getKeyCode(String shortcut) {
        return KeyCode.getKeyCode(KeyboardShortcuts.getDefaultKeyboardShortcuts().get(shortcut));
    }

    public void clearSelectedIssueId() {
        selectedIssueId = 0;
    }

    public void clearPanelIndex() {
        panelIndex = -1;
    }

    public void clearUiComponentFocusEventType() {
        uiComponentFocusEventType = UIComponentFocusEvent.EventType.NONE;
    }
}

@@ -3765,35 +3765,150 @@
         
-push(KeyCode.HOME);
+// mark as read an issue that has another issue below it%0A        push(KeyCode.HOME);%0A        // focus should change to the issue below
 %0A       
@@ -4265,32 +4265,79 @@
 ad());%0A        %0A
+        // mark as read an issue at the bottom%0A
         push(Key
@@ -4381,32 +4381,79 @@
 ARK_AS_READ%22));%0A
+        // focus should remain at bottom issue%0A
         assertEq
@@ -4626,32 +4626,32 @@
 K_AS_UNREAD%22));%0A
-
         assertEq
@@ -4711,16 +4711,558 @@
 Read());
+%0A        clearSelectedIssueId();%0A        %0A        // testing corner case for mark as read where there is only one issue displayed%0A        click(%22#dummy/dummy_col1_filterTextField%22);%0A        type(%22id%22);%0A        press(KeyCode.SHIFT).press(KeyCode.SEMICOLON).release(KeyCode.SEMICOLON).release(KeyCode.SHIFT);%0A        type(%225%22);%0A        push(KeyCode.ENTER);%0A        push(KeyCode.SPACE).push(KeyCode.SPACE);%0A        push(getKeyCode(%22MARK_AS_READ%22));%0A        // focus should remain at the only issue shown%0A        assertEquals(5, selectedIssueId);
 %0A%0A      

Improve testing for mark as read