import { AppObjectUC, cubicOut, getSingletonComponent, interpolateNumber, Vector2, } from "@vived/core";
import { SceneRayPickUC } from "../../Babylon/UC/SceneRayPickUC";
import { BaseAppState } from "../../BaseApp/Entity/BaseAppState";
import { ChallengeEntity } from "../../Challenge/Entities/ChallengeEntity";
import { LabelDropDragMode, LabelDropRepo } from "../Entities/LabelDropRepo";
export class DragLabelDropUC extends AppObjectUC {
    static get(appObjects) {
        return getSingletonComponent(DragLabelDropUC.type, appObjects);
    }
}
DragLabelDropUC.type = "DragLabelDropUC";
export function makeDragLabelDropUC(appObject) {
    return new DragLabelDropUCImp(appObject);
}
class DragLabelDropUCImp extends DragLabelDropUC {
    get repo() {
        return this.getCachedSingleton(LabelDropRepo.type);
    }
    get challenge() {
        return this.getCachedSingleton(ChallengeEntity.type);
    }
    get baseApp() {
        return this.getCachedSingleton(BaseAppState.type);
    }
    initialize(labelDropID, pos) {
        if (!this.repo || !this.challenge)
            return;
        if (this.challenge.selectedChallenge !== "LABEL_DROP")
            return;
        if (this.baseApp?.isAuthoring === true)
            return;
        this.repo.draggingID = labelDropID;
        this.repo.dragMode = LabelDropDragMode.SCREEN;
        this.repo.dragAlpha = 1;
        this.initialPosition = pos;
        this.repo.screenPosition = new Vector2(pos.x, pos.y);
        this.isDragging = true;
    }
    setPosition2D(pos) {
        if (!this.isDragging)
            return;
        if (!this.repo || !this.challenge)
            return;
        if (this.challenge.selectedChallenge !== "LABEL_DROP")
            return;
        if (this.baseApp?.isAuthoring === true)
            return;
        this.repo.screenPosition = new Vector2(pos.x, pos.y);
    }
    release(ray) {
        if (!this.isDragging)
            return;
        this.isDragging = false;
        if (!this.repo || !this.challenge)
            return;
        if (this.challenge.selectedChallenge !== "LABEL_DROP")
            return;
        if (this.baseApp?.isAuthoring === true)
            return;
        if (!this.repo.draggingID) {
            this.warn("Trying to release a label drop without an ID");
            return;
        }
        const scenePick = SceneRayPickUC.get(this.appObjects)?.sceneRayPick(ray);
        this.appObjectID = undefined;
        this.hitObject = true;
        if (!scenePick ||
            !scenePick.worldPickPoint ||
            scenePick.hit === false ||
            !scenePick.normal ||
            !scenePick.objectPickMeta) {
            this.hitObject = false;
        }
        else {
            this.appObjectID = scenePick.objectPickMeta.appObjectID;
        }
        if (this.hitObject && this.appObjectID) {
            this.repo.submitLabelDrop(this.repo.draggingID, this.appObjectID);
        }
        this.onFinishRelease();
    }
    constructor(appObject) {
        super(appObject, DragLabelDropUC.type);
        this.isDragging = false;
        this.appObjectID = undefined;
        this.hitObject = false;
        this.initialPosition = Vector2.Zero();
        this.endPosition = Vector2.Zero();
        this.delta = 10;
        this.currentPercent = 0;
        this.correctFadeDurationMS = 200;
        this.incorrectFadeDurationMS = 300;
        this.doNothingFadeDurationMS = 500;
        this.onFinishRelease = async () => {
            if (!this.repo)
                return;
            if (this.interval) {
                clearInterval(this.interval);
            }
            this.currentPercent = 0;
            this.endPosition = this.repo.screenPosition;
            if (!this.hitObject) {
                // no hit
                this.interval = setInterval(() => {
                    this.animateLabelDrop(this.doNothingFadeDurationMS);
                }, this.delta);
            }
            else if (this.repo.resultIsCorrect) {
                // correct
                await new Promise((resolve) => setTimeout(resolve, 1000));
                this.initialPosition = this.endPosition;
                this.interval = setInterval(() => {
                    this.animateLabelDrop(this.correctFadeDurationMS);
                }, this.delta);
            }
            else {
                // incorrect
                await new Promise((resolve) => setTimeout(resolve, 1000));
                this.interval = setInterval(() => {
                    this.animateLabelDrop(this.incorrectFadeDurationMS);
                }, this.delta);
            }
        };
        this.animateLabelDrop = (duration) => {
            if (!this.baseApp)
                return;
            if (!this.repo)
                return;
            if (!this.interval)
                return;
            const difference = 1 / (duration / this.delta);
            this.currentPercent = this.currentPercent + difference;
            const newValue = cubicOut(this.currentPercent);
            if (newValue >= 1) {
                this.repo.draggingID = undefined;
                this.repo.dragAlpha = 0;
                this.repo.resultIsCorrect = undefined;
                clearInterval(this.interval);
                if (this.repo.getRemainingLabelDrops().length === 0) {
                    this.baseApp.isReviewing = true;
                }
            }
            else {
                this.repo.dragAlpha = 1 - newValue;
                const newX = interpolateNumber(this.endPosition.x, this.initialPosition.x, newValue);
                const newY = interpolateNumber(this.endPosition.y, this.initialPosition.y, newValue);
                this.repo.screenPosition = new Vector2(newX, newY);
            }
        };
    }
}
//# sourceMappingURL=DragLabelDropUC.js.map