import {deleteKeyframeAndResetVars} from "./deleteKeyframeAndResetVars.js";
import {applyActionSelection, applyGlobalKeyframeDeselection} from "../actionProcessorOperations/applyActionChange.js";
import Vector2 from "../../../../core/geom/Vector2.js";
import {readPositionFromMouseEvent} from "../../../input/devices/PointerDevice.js";
import {Keyframe} from "../Keyframe.js";
import {AddKeyframeAction} from "../actionProcessorOperations/curveActions.js";
import {isInjectedKeyframeInBounds} from "../draw/isInjectedKeyframeInBounds.js";
import {downloadAsFile} from "../../../../core/binary/downloadAsFile.js";

const keyType = {
    deleteKey: 'delete',
    alignTangentKey: 'a',
    holdSelectionKey: 'shift',
    controlKey: 'ctrl',
    undoSecondaryKey: 'z',
    redoSecondaryKey: 'y',
    saveSecondaryKey: 's',
}

/**
 *
 * @param {KeyboardEvent} event
 * @param {KeyboardDevice} keyboard
 * @param {AnimationCurve} curve
 * @param {KeyframeStateManager} keyframeStateManager
 * @param {ActionProcessor} actionProcessor
 * @param {keyframesContext}actionProcessorCTX
 */
export function handleKeyDownEvents(event, keyboard, curve, keyframeStateManager, actionProcessor, actionProcessorCTX) {
    const {keys} = keyboard;

    if (keys[keyType.deleteKey].is_down) {
        deleteKeyframeAndResetVars(actionProcessor, actionProcessorCTX, keyframeStateManager);
    }

    if (keys[keyType.alignTangentKey].is_down
        && keyframeStateManager.observedActiveKeyframe.get() !== keyframeStateManager.NULL_KEYFRAME) {
        keyframeStateManager.tangentAlignmentEnabled.invert();
    }

    if (keys[keyType.controlKey].is_down) {
        if (keys[keyType.undoSecondaryKey].is_down) {
            keyframeStateManager.observedActiveKeyframe.set(keyframeStateManager.NULL_KEYFRAME);
            actionProcessor.undo();
        }

        if (keys[keyType.redoSecondaryKey].is_down) {
            keyframeStateManager.observedActiveKeyframe.set(keyframeStateManager.NULL_KEYFRAME);
            actionProcessor.redo();
        }

        if (keys[keyType.saveSecondaryKey].is_down) {
            event.preventDefault(); // prevent browser save dialog
            const data = JSON.stringify(curve)
            downloadAsFile(data, "curve.json")
            // console.log(`${data}`)
        }
    }
}

/**
 *
 * @param {MouseEvent} e
 * @param {CanvasView} graph
 * @param {KeyboardDevice} keyboardElement
 * @param {ActionProcessor} actionProcessor
 * @param {keyframesContext} actionProcessorCTX
 * @param {KeyframeStateManager} keyframeStateManager
 */
export function handleMouseDownEvents(e, graph, keyboardElement, actionProcessor, actionProcessorCTX, keyframeStateManager) {
    const isClickedOnGraph = e.target === graph.el;
    const isSelectionKeyHeld = keyboardElement.keys[keyType.holdSelectionKey].is_down;

    applyGlobalKeyframeDeselection(isClickedOnGraph, isSelectionKeyHeld, actionProcessor, actionProcessorCTX, keyframeStateManager);
}

export function handleMouseDoubleClickEvents(e, vContainer, graph, frame, margin, curve, validEditableBounds, actionProcessor, actionProcessorCTX) {
    const mousePosition = new Vector2();
    readPositionFromMouseEvent(mousePosition, e, vContainer.el);

    const newKeyframe = new Keyframe();

    if (isInjectedKeyframeInBounds(graph, frame, margin, curve, validEditableBounds, mousePosition, newKeyframe)) {
        actionProcessor.mark('add keyframe');
        actionProcessor.do(new AddKeyframeAction(newKeyframe, actionProcessorCTX))
    }
}

/**
 *
 * @param {KeyboardDevice} keyboardElement
 * @param {Keyframe} keyframe
 * @param {ActionProcessor} actionProcessor
 * @param {keyframesContext} actionProcessorCTX
 * @param {KeyframeStateManager} keyframeStateManager
 */
export function handleKeyframeSelectedByDevice(keyboardElement, keyframe, actionProcessor, actionProcessorCTX, keyframeStateManager) {
    const isSelectionKeyHeld = keyboardElement.keys[keyType.holdSelectionKey].is_down;
    const isKeyframeNotInSelection = !keyframeStateManager.curKeyframeList.find(kf => kf === keyframe);
    const isActiveKeyframeNotInSelection = !keyframeStateManager.curKeyframeList.find(kf => kf === keyframeStateManager.observedActiveKeyframe.get());

    keyframeStateManager.prevKeyframeList.copy(keyframeStateManager.selectedKeyframes);
    keyframeStateManager.curKeyframeList.copy(keyframeStateManager.selectedKeyframes);

    if (isSelectionKeyHeld) {
        if (isKeyframeNotInSelection) {
            if (isActiveKeyframeNotInSelection)
                keyframeStateManager.curKeyframeList.add(keyframeStateManager.observedActiveKeyframe.get());

            keyframeStateManager.curKeyframeList.add(keyframe);
            applyActionSelection('Selection', keyframeStateManager, actionProcessor, actionProcessorCTX);
        } else {
            keyframeStateManager.curKeyframeList.removeIf(k => k === keyframe);
            applyActionSelection('Deselection', keyframeStateManager, actionProcessor, actionProcessorCTX);
        }
    } else {
        keyframeStateManager.tangentAlignmentEnabled.setFalse();
        keyframeStateManager.observedActiveKeyframe.set(keyframe);

        if (isKeyframeNotInSelection) {
            keyframeStateManager.curKeyframeList.reset();
            applyActionSelection('Deselection', keyframeStateManager, actionProcessor, actionProcessorCTX);
        }
    }
}