import { AppObjectUC, getSingletonComponent, } from "@vived/core";
import { ParametricPlane, Quaternion, Vector3, } from "@vived/core";
import { sceneRayPick } from "../../Babylon/UC/SceneRayPickUC";
import { BaseAppState } from "../../BaseApp/Entity/BaseAppState";
import { ChallengeEntity } from "../../Challenge/Entities/ChallengeEntity";
import { LabelDropDragMode, LabelDropRepo } from "../Entities/LabelDropRepo";
import { LabelDropCorrectAnimationUC } from "./CorrectAnimationUC";
import { LabelDropOnNothingAnimationUC } from "./DropOnNothingAnimationUC";
import { LabelDropIncorrectAnimationUC } from "./IncorrectAnimationUC";
export class DragLabelDropWorldUC extends AppObjectUC {
    static get(appObjects) {
        return getSingletonComponent(DragLabelDropWorldUC.type, appObjects);
    }
}
DragLabelDropWorldUC.type = "DragLabelDropWorldUC";
export function makeDragLabelDropWorldUC(appObject) {
    return new DragLabelDropWorldUCImp(appObject);
}
class DragLabelDropWorldUCImp extends DragLabelDropWorldUC {
    get repo() {
        return this.getCachedSingleton(LabelDropRepo.type);
    }
    get challenge() {
        return this.getCachedSingleton(ChallengeEntity.type);
    }
    get baseApp() {
        return this.getCachedSingleton(BaseAppState.type);
    }
    initializeDrag(labelDropID, ray) {
        if (!this.repo || !this.challenge)
            return;
        if (this.challenge.selectedChallenge !== "LABEL_DROP")
            return;
        if (this.baseApp?.isAuthoring === true)
            return;
        if (this.currentAnimation) {
            this.currentAnimation.cancel();
            this.repo.resultIsCorrect = undefined;
            this.repo.draggingID = undefined;
        }
        const pick = this.doPick(ray);
        if (!pick)
            return;
        this.positionHelper(pick);
        this.positionDragLabelFromHelper();
        this.repo.draggingID = labelDropID;
        this.repo.dragMode = LabelDropDragMode.WORLD;
        this.repo.dragAlpha = 1;
        this.dragStartPosition = pick;
        this.isDragging = true;
    }
    positionHelper(worldPosition) {
        if (!this.repo)
            return;
        const helper = this.repo.dragHelperTransform;
        helper.worldPosition = worldPosition;
        const localZ = helper.localPosition.z * this.percentOfPickDepth;
        helper.localPosition = new Vector3(0, 0, localZ);
        helper.localRotation = Quaternion.Identity();
    }
    doPick(ray) {
        const scenePick = sceneRayPick(ray, this.appObjects);
        if (scenePick && scenePick.worldPickPoint) {
            return scenePick.worldPickPoint;
        }
        const zeroParallaxPlane = ParametricPlane.FromPointNormal(Vector3.Zero(), Vector3.Forward());
        const zeroParallaxPick = zeroParallaxPlane.intersectLine(ray);
        return zeroParallaxPick;
    }
    positionDragLabelFromHelper() {
        if (!this.repo)
            return;
        this.repo.dragLabelTransform.worldPosition = this.repo.dragHelperTransform.worldPosition;
        this.repo.dragLabelTransform.worldRotation = this.repo.dragHelperTransform.worldRotation;
    }
    updateDrag(ray) {
        if (!this.isDragging)
            return;
        if (!this.repo || !this.challenge)
            return;
        if (this.challenge.selectedChallenge !== "LABEL_DROP")
            return;
        if (this.baseApp?.isAuthoring === true)
            return;
        const pick = this.doPick(ray);
        if (!pick)
            return;
        this.positionHelper(pick);
        this.positionDragLabelFromHelper();
    }
    async releaseDrag(ray) {
        if (!this.baseApp)
            return;
        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 pickID = sceneRayPick(ray, this.appObjects)?.appObjectID;
        if (!pickID) {
            const animationUC = LabelDropOnNothingAnimationUC.get(this.appObjects);
            if (!animationUC) {
                this.warn("Unable to find LabelDropOnNothingAnimationUC");
                return;
            }
            this.currentAnimation = animationUC;
            animationUC.desiredFinalPosition = this.dragStartPosition;
            const didComplete = await animationUC.start();
            if (didComplete)
                this.onAnimationComplete();
            return;
        }
        const isCorrect = this.repo.submitLabelDrop(this.repo.draggingID, pickID);
        if (isCorrect) {
            const animationUC = LabelDropCorrectAnimationUC.get(this.appObjects);
            if (!animationUC) {
                this.warn("Unable to find LabelDropCorrectAnimationUC");
                return;
            }
            this.currentAnimation = animationUC;
            const didComplete = await animationUC.start();
            if (didComplete)
                this.onAnimationComplete();
        }
        else {
            const animationUC = LabelDropIncorrectAnimationUC.get(this.appObjects);
            if (!animationUC) {
                this.warn("Unable to find LabelDropIncorrectAnimationUC");
                return;
            }
            this.currentAnimation = animationUC;
            animationUC.desiredFinalPosition = this.dragStartPosition;
            const didComplete = await animationUC.start();
            if (didComplete)
                this.onAnimationComplete();
        }
    }
    onAnimationComplete() {
        this.currentAnimation = undefined;
        if (!this.repo || !this.baseApp)
            return;
        this.repo.draggingID = undefined;
        this.repo.resultIsCorrect = undefined;
        if (this.repo.getRemainingLabelDrops().length === 0) {
            this.baseApp.isReviewing = true;
        }
    }
    constructor(appObject) {
        super(appObject, DragLabelDropWorldUC.type);
        this.percentOfPickDepth = 0.95;
        this.isDragging = false;
        this.dragStartPosition = Vector3.Zero();
    }
}
//# sourceMappingURL=DragLabelDropWorldUC.js.map