"use strict";
var __importDefault = (this && this.__importDefault) || function (mod) {
    return (mod && mod.__esModule) ? mod : { "default": mod };
};
Object.defineProperty(exports, "__esModule", { value: true });
const domUtils_1 = require("../../sharedUtils/domUtils");
const dom_util_1 = require("@mablhq-internal/mablscript-find/dom-util");
const OverlayHandler_1 = __importDefault(require("./OverlayHandler"));
const actions_1 = require("../actions");
const messages_1 = require("../../sharedUtils/messages");
const domTools_1 = require("../domTools");
const walkthrough_1 = require("../../sharedUtils/walkthrough");
const util_1 = require("./util");
const MORE_OPTIONS_HINT_SUBTEXT = 'Hold Shift for more options';
const OVERLAPPING_ELEMENTS_HINT_SUBTEXT = 'Press "Up" or "Down" keys to select a different overlapping element';
const QUICK_ASSERT_HINT_SUBTEXT = 'Click to Quick Assert';
const quickAssertHighlightBoxStyleOverrides = {
    'border-radius': '6px',
    background: 'rgba(110, 105, 209, 0.3)',
};
function applyMoreOptionsHighlightBoxStyleOverrides() {
    const highlightBox = document.getElementById(domUtils_1.MABL_HIGHLIGHT_ID);
    if (highlightBox) {
        Object.entries(quickAssertHighlightBoxStyleOverrides).forEach(([key, value]) => {
            highlightBox.style.setProperty(key, value);
        });
    }
}
function removeMoreOptionsHighlightBoxStyleOverrides() {
    const highlightBox = document.getElementById(domUtils_1.MABL_HIGHLIGHT_ID);
    if (highlightBox) {
        Object.keys(quickAssertHighlightBoxStyleOverrides).forEach((key) => {
            highlightBox.style.removeProperty(key);
        });
    }
}
class SelectionClickEventHandler extends OverlayHandler_1.default {
    constructor(mouseHoverEventHandler, store, selectorCache) {
        super('Select an element', store, selectorCache, 'Selection Event Handler', true);
        this.lastPosition = {
            clientX: 0,
            clientY: 0,
        };
        this.mouseHoverEventHandler = mouseHoverEventHandler;
        this.handleSelection = this.handleSelection.bind(this);
        this.handleKeyDown = this.handleKeyDown.bind(this);
        this.handleKeyUp = this.handleKeyUp.bind(this);
        this.handleClick = this.handleClick.bind(this);
        this.handleMove = this.handleMove.bind(this);
        this.handleMouseOut = this.handleMouseOut.bind(this);
        this.handleMouseEnter = this.handleMouseEnter.bind(this);
        this.setSelectionModeCause = this.setSelectionModeCause.bind(this);
        this.isCreatingAssertion = this.isCreatingAssertion.bind(this);
        this.isInWalkthrough = this.isInWalkthrough.bind(this);
        this.moreOptionsEnabled = this.moreOptionsEnabled.bind(this);
        this.highlightedElement = undefined;
        this.overlappingElementsIndex = 0;
    }
    setSelectionModeCause(cause) {
        this.selectionModeCause = cause;
        this.overlaySubtext = this.moreOptionsEnabled()
            ? MORE_OPTIONS_HINT_SUBTEXT
            : undefined;
    }
    isCreatingAssertion() {
        return this.selectionModeCause === 'assert';
    }
    isInWalkthrough() {
        return this.store.getState().walkthrough.isInProgress;
    }
    moreOptionsEnabled() {
        return !this.isInWalkthrough();
    }
    register() {
        super.register();
        window.addEventListener('mousemove', this.handleMove, true);
        window.addEventListener('click', this.handleClick, true);
        window.addEventListener('keydown', this.handleKeyDown, true);
        window.addEventListener('keyup', this.handleKeyUp, true);
        window.addEventListener('pointerover', this.handleMouseEnter, true);
        window.addEventListener('pointerout', this.handleMouseOut, true);
    }
    unregister() {
        super.unregister();
        window.removeEventListener('mousemove', this.handleMove, true);
        window.removeEventListener('click', this.handleClick, true);
        window.removeEventListener('keydown', this.handleKeyDown, true);
        window.removeEventListener('keyup', this.handleKeyUp, true);
        window.removeEventListener('pointerover', this.handleMouseEnter, true);
        window.removeEventListener('pointerout', this.handleMouseOut, true);
    }
    updateHighlightBoxAfterOverlapIndexChange(clientX, clientY) {
        this.highlightedElement = (0, domUtils_1.positionSelectionHighlight)({ clientX, clientY }, this.isInWalkthrough(), this.overlappingElementsIndex);
    }
    handleMove(event) {
        this.lastPosition = {
            clientX: event.clientX,
            clientY: event.clientY,
        };
        const oldHighlightedElement = this.highlightedElement;
        this.highlightedElement = (0, domUtils_1.positionSelectionHighlight)({ clientX: event.clientX, clientY: event.clientY }, this.isInWalkthrough(), this.overlappingElementsIndex);
        if (this.highlightedElement !== oldHighlightedElement) {
            this.overlappingElementsIndex = 0;
        }
        this.checkAndApplyIframeHandling(event);
    }
    handleMouseOut() {
        const highlightBox = document.getElementById(domUtils_1.MABL_HIGHLIGHT_ID);
        if (highlightBox) {
            highlightBox.style.display = 'none';
        }
        this.overlappingElementsIndex = 0;
    }
    handleMouseEnter() {
        const highlightBox = document.getElementById(domUtils_1.MABL_HIGHLIGHT_ID);
        if (highlightBox) {
            highlightBox.style.display = 'block';
        }
        this.overlappingElementsIndex = 0;
    }
    isTrustedEvent(event) {
        return event.isTrusted;
    }
    async handleKeyDown(event) {
        if (!this.isTrustedEvent(event)) {
            return;
        }
        if (event.key === 'Enter') {
            event.stopPropagation();
            event.preventDefault();
            await this.handleSelection(event);
        }
        if (event.key === 'Shift' && this.moreOptionsEnabled()) {
            applyMoreOptionsHighlightBoxStyleOverrides();
            const overlaySubtext = document.getElementById(domUtils_1.MABL_OVERLAY_SUBTEXT_ID);
            if (overlaySubtext) {
                overlaySubtext.replaceChildren();
                if (this.isCreatingAssertion()) {
                    overlaySubtext.appendChild(document.createTextNode(OVERLAPPING_ELEMENTS_HINT_SUBTEXT));
                    overlaySubtext.appendChild(document.createElement('br'));
                    overlaySubtext.appendChild(document.createTextNode(QUICK_ASSERT_HINT_SUBTEXT));
                }
                else {
                    overlaySubtext.textContent = OVERLAPPING_ELEMENTS_HINT_SUBTEXT;
                }
            }
            return;
        }
        if (event.shiftKey &&
            this.moreOptionsEnabled() &&
            (event.key === 'ArrowUp' || event.key === 'ArrowDown')) {
            event.stopPropagation();
            event.preventDefault();
            if (event.key === 'ArrowUp') {
                this.overlappingElementsIndex++;
            }
            else {
                this.overlappingElementsIndex--;
            }
            this.updateHighlightBoxAfterOverlapIndexChange(this.lastPosition.clientX, this.lastPosition.clientY);
        }
    }
    handleKeyUp(event) {
        if (!(this.isTrustedEvent(event) &&
            event.key === 'Shift' &&
            this.moreOptionsEnabled())) {
            return;
        }
        removeMoreOptionsHighlightBoxStyleOverrides();
        const overlaySubtext = document.getElementById(domUtils_1.MABL_OVERLAY_SUBTEXT_ID);
        if (overlaySubtext) {
            overlaySubtext.textContent = MORE_OPTIONS_HINT_SUBTEXT;
        }
    }
    async handleClick(event) {
        if (this.shouldIgnoreClicks() || !this.isTrustedEvent(event)) {
            return;
        }
        await this.handleSelection(event);
        event.stopPropagation();
    }
    async handleSelection(event) {
        const target = (0, domUtils_1.getElementToHighlightFromPoints)(this.lastPosition.clientX, this.lastPosition.clientY, undefined, this.overlappingElementsIndex);
        const xPath = (0, dom_util_1.createXPathFromElement)(target);
        if (!target) {
            throw new Error(`No target to handle ${event.type} event on`);
        }
        const eventMessage = await (0, domTools_1.createEventMessageWithShadowParents)(target, messages_1.RECORD_SELECTION, 'mouse-select', xPath, event.timeStamp);
        eventMessage.availableAttrProps = (0, dom_util_1.getAttributePropertyMap)(target);
        eventMessage.availableCssProps = (0, dom_util_1.getCssPropertyMap)(target);
        eventMessage.selectionType = 'element';
        if (this.isInWalkthrough()) {
            const isInTrainerContext = this.store.getState().walkthrough.activeContext ===
                walkthrough_1.ActiveWalkthroughContext.TRAINER;
            if (isInTrainerContext || !(0, util_1.isWalkthroughTarget)(target)) {
                return;
            }
            if (event.type === 'click') {
                target?.click?.();
            }
        }
        if (event.shiftKey &&
            this.moreOptionsEnabled() &&
            this.isCreatingAssertion()) {
            eventMessage.skipAssertionForm = true;
        }
        if (this.overlappingElementsIndex !== 0) {
            eventMessage.overlappingElementsIndex = this.overlappingElementsIndex;
        }
        this.unregister();
        (0, actions_1.sendSnapshotMessage)();
        this.mouseHoverEventHandler.recordHovers();
        void (0, actions_1.sendEventMessage)(eventMessage);
    }
    handleScroll() {
        (0, domUtils_1.positionSelectionHighlight)(this.lastPosition);
    }
}
exports.default = SelectionClickEventHandler;
