import { EventDispatcher } from "../../Utils";
import { Point } from "@devexpress/utils/lib/geometry/point";
import { DiagramMouseEvent, DiagramContextMenuEvent, DiagramFocusEvent, DiagramEvent, MouseEventElementType, IMouseOperationsListener, DiagramKeyboardEvent, MouseButton, ITextInputOperationListener } from "../Event";
import { ItemKey, ConnectionPointSide, DiagramItem } from "../../Model/DiagramItem";
import { KeyCode } from "@devexpress/utils/lib/utils/key";
import { IContextToolboxVisibilityChangesListener } from "../ContextToolboxHandler";
import { BatchUpdatableObject } from "@devexpress/utils/lib/class/batch-updatable";
import { Browser } from "@devexpress/utils/lib/browser";
import { Shape } from "../../Model/Shapes/Shape";
import { Size } from "@devexpress/utils/lib/geometry/size";

export interface IContextMenuVisibilityChangesListener {
    notifyShowContextMenu(eventPoint: Point, modelPoint: Point);
    notifyHideContextMenu();
}

export class ContextMenuHandler extends BatchUpdatableObject implements IMouseOperationsListener,
    IContextToolboxVisibilityChangesListener, ITextInputOperationListener {
    protected contextMenuVisible = false;
    protected textInputStarted = false;
    private canHideContextMenu = true;
    onVisibilityChanged: EventDispatcher<IContextMenuVisibilityChangesListener> = new EventDispatcher();

    onMouseDown(evt: DiagramMouseEvent): void {
        if(evt.button === MouseButton.Left && evt.source.type !== MouseEventElementType.Undefined)
            this.hideContextMenu();

    }
    onMouseUp(evt: DiagramMouseEvent): void {
        if(!Browser.MacOSPlatform || Browser.MacOSPlatform && this.canHideContextMenu)
            this.hideContextMenu();

        this.canHideContextMenu = true;
    }
    onContextMenu(evt: DiagramContextMenuEvent): void {
        if(Browser.MacOSPlatform)
            this.canHideContextMenu = false;
        this.showContextMenu(evt.eventPoint, evt.modelPoint);
    }
    onFocus(evt: DiagramEvent): void { }
    onBlur(evt: DiagramFocusEvent): void { }
    onTextInputFocus(evt: DiagramEvent): void { }
    onTextInputBlur(evt: DiagramFocusEvent): void { }
    onLongTouch(evt: DiagramMouseEvent): void { }
    onKeyDown(evt: DiagramKeyboardEvent): void {
        if(evt.keyCode === KeyCode.Esc)
            this.hideContextMenu();
    }
    onShortcut(evt: DiagramKeyboardEvent): void {
        this.hideContextMenu();
    }

    showContextMenu(eventPoint: Point, modelPoint: Point): void {
        if(this.textInputStarted) return;

        window.setTimeout(() => { 
            this.onVisibilityChanged.raise1(l => l.notifyShowContextMenu(eventPoint, modelPoint));
            this.contextMenuVisible = true;
        }, 1); 
    }
    hideContextMenu(): void {
        if(this.contextMenuVisible)
            window.setTimeout(() => { 
                this.onVisibilityChanged.raise1(l => l.notifyHideContextMenu());
                this.contextMenuVisible = false;
            }, 1); 
    }

    notifyDragStart(itemKeys: ItemKey[]): void { }
    notifyDragEnd(itemKeys: ItemKey[]): void { }
    notifyDragScrollStart(): void {}
    notifyDragScrollEnd(): void {}

    notifyShowContextToolbox(modelPoint: Point, getPositionToInsertShapeTo: (shape: Shape) => Point, side: ConnectionPointSide, category: string, callback: (shapeType: string) => void): void { }
    notifyHideContextToolbox(): void { }

    notifyTextInputStart(item: DiagramItem, text: string, position: Point, size?: Size): void {
        this.textInputStarted = true;
    }
    notifyTextInputEnd(item: DiagramItem, captureFocus?: boolean): void {
        this.textInputStarted = false;
    }
    notifyTextInputPermissionsCheck(item: DiagramItem, allowed: boolean): void {}

    onUpdateUnlocked(occurredEvents: number): void { }
}
