"use strict";
var __importDefault = (this && this.__importDefault) || function (mod) {
    return (mod && mod.__esModule) ? mod : { "default": mod };
};
Object.defineProperty(exports, "__esModule", { value: true });
exports.WrongReleaseTypeMessage = exports.InvalidStepsBetweenDragAndDropMessage = void 0;
const ClickAndHoldStep_1 = require("./canonical/ClickAndHoldStep");
const HoverStep_1 = __importDefault(require("./canonical/HoverStep"));
const ReleaseStep_1 = require("./canonical/ReleaseStep");
const SwitchContextToStep_1 = __importDefault(require("./canonical/SwitchContextToStep"));
const FlowValidationClass_1 = require("./FlowValidationClass");
exports.InvalidStepsBetweenDragAndDropMessage = `Only switch context and hover steps can be between a click and hold and release`;
exports.WrongReleaseTypeMessage = `Release step does not match HTML5 setting of click and hold step`;
const validInterleavedStepsTypes = [
    SwitchContextToStep_1.default.getStepType(),
    HoverStep_1.default.getStepType(),
];
function isValidInterleavedStep(stepType) {
    return validInterleavedStepsTypes.includes(stepType);
}
class FlowValidationDragDrop extends FlowValidationClass_1.FlowValidationClass {
    constructor() {
        super();
        this.flowsTracked = {};
    }
    trackFlow(flowId) {
        if (!this.flowsTracked[flowId]) {
            this.flowsTracked[flowId] = {
                currentClickAndHold: undefined,
                accumulatedInterleavedSteps: [],
                clickAndHoldMissingRelease: [],
                releaseMissingClickAndHold: [],
                invalidInterleavedSteps: [],
                wrongReleaseTypeSteps: [],
            };
        }
    }
    getTrackedId(flow) {
        if (flow?.reusable && flow?.flow_type === 'mablscript') {
            return `${flow.id}:${flow.description}`;
        }
        return 'root';
    }
    getTrackedState(flow) {
        const trackedId = this.getTrackedId(flow);
        if (!this.flowsTracked[trackedId]) {
            this.trackFlow(trackedId);
        }
        return this.flowsTracked[trackedId];
    }
    processStep(step, humanizedStep, flow) {
        if (humanizedStep.isDisabledStep) {
            return humanizedStep;
        }
        const trackedState = this.getTrackedState(flow);
        if (trackedState.currentClickAndHold) {
            if (humanizedStep.flowInstanceId !==
                trackedState.currentClickAndHold.humanizedStep.flowInstanceId) {
                trackedState.clickAndHoldMissingRelease.push(trackedState.currentClickAndHold.humanizedStep);
                trackedState.currentClickAndHold = undefined;
            }
        }
        if ((0, ClickAndHoldStep_1.isClickAndHoldStep)(step)) {
            this.processClickAndHold(step, humanizedStep, trackedState);
        }
        else if ((0, ReleaseStep_1.isReleaseStep)(step)) {
            this.processRelease(step, humanizedStep, trackedState);
        }
        else {
            this.processOtherStepType(humanizedStep, trackedState, step.stepType);
        }
        return humanizedStep;
    }
    processClickAndHold(step, humanizedStep, trackedState) {
        if (trackedState.currentClickAndHold) {
            trackedState.clickAndHoldMissingRelease.push(trackedState.currentClickAndHold.humanizedStep);
        }
        trackedState.currentClickAndHold = { humanizedStep, isHtml5: step.isHtml5 };
        trackedState.accumulatedInterleavedSteps = [];
    }
    processRelease(releaseStep, humanizedStep, trackedState) {
        if (trackedState.currentClickAndHold) {
            const clickAndHoldIsHtml5 = trackedState.currentClickAndHold.isHtml5;
            trackedState.currentClickAndHold = undefined;
            const interleaved = trackedState.accumulatedInterleavedSteps;
            const invalidInterleavedSteps = interleaved.filter((step) => !isValidInterleavedStep(step.stepType));
            trackedState.invalidInterleavedSteps.push(...invalidInterleavedSteps);
            if (clickAndHoldIsHtml5 !== releaseStep.releaseArgs.isHtml5) {
                trackedState.wrongReleaseTypeSteps.push(humanizedStep);
            }
        }
        else {
            trackedState.releaseMissingClickAndHold.push(humanizedStep);
        }
        trackedState.accumulatedInterleavedSteps = [];
    }
    processOtherStepType(humanizedStep, trackedState, stepType) {
        if (trackedState.currentClickAndHold) {
            trackedState.accumulatedInterleavedSteps.push({
                ...humanizedStep,
                stepType,
            });
        }
    }
    finalizeValidations(humanizedSteps) {
        Object.entries(this.flowsTracked).forEach(([_flow, trackedValidation]) => {
            if (trackedValidation.currentClickAndHold) {
                trackedValidation.clickAndHoldMissingRelease.push(trackedValidation.currentClickAndHold.humanizedStep);
            }
            trackedValidation.clickAndHoldMissingRelease.forEach((clickNoRelease) => {
                clickNoRelease.validation.push({
                    name: 'clickNoRelease',
                    humanized: `Click and hold step without following release step`,
                });
            });
            trackedValidation.releaseMissingClickAndHold.forEach((releaseNoClick) => {
                releaseNoClick.validation.push({
                    name: 'releaseNoClick',
                    humanized: `Release step without preceding click and hold step`,
                });
            });
            trackedValidation.invalidInterleavedSteps.forEach((interleavedStep) => {
                interleavedStep.validation.push({
                    name: 'dragDropNoInterleaved',
                    humanized: exports.InvalidStepsBetweenDragAndDropMessage,
                });
            });
            trackedValidation.wrongReleaseTypeSteps.forEach((wrongReleaseType) => {
                wrongReleaseType.validation.push({
                    name: 'wrongReleaseType',
                    humanized: exports.WrongReleaseTypeMessage,
                });
            });
        });
        return humanizedSteps;
    }
}
exports.default = FlowValidationDragDrop;
