"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
const core_1 = require("@vived/core");
const core_2 = require("@vived/core");
const MockSceneRayPickUC_1 = require("../../Babylon/Mocks/MockSceneRayPickUC");
const BaseAppState_1 = require("../../BaseApp/Entity/BaseAppState");
const ChallengeEntityMock_1 = require("../../Challenge/Mocks/ChallengeEntityMock");
const Transform3D_1 = require("../../Transform3D/Entities/Transform3D");
const LabelDropRepo_1 = require("../Entities/LabelDropRepo");
const MockCorrectAnimation_1 = require("../Mocks/MockCorrectAnimation");
const MockDropAnimation_1 = require("../Mocks/MockDropAnimation");
const MockIncorrectAnimation_1 = require("../Mocks/MockIncorrectAnimation");
const DragLabelDropWorldUC_1 = require("./DragLabelDropWorldUC");
// Default setup
// Hit is 1,2,3 (world)
// Stylus is 1,2,0 (world)
// Local hit is 0,0,3 (stylus)
function makeTestRig() {
    const appObjects = (0, core_1.makeAppObjectRepo)();
    const challenge = (0, ChallengeEntityMock_1.makeChallengeEntityMock)(appObjects);
    const baseApp = (0, BaseAppState_1.makeBaseAppState)(appObjects.getOrCreate("BaseApp"));
    const labelDropAO = appObjects.getOrCreate("labelDrop");
    const mockDropAnimation = (0, MockDropAnimation_1.makeMockDropAnimation)(appObjects);
    const mockCorrectAnimation = (0, MockCorrectAnimation_1.makeMockLabelDropCorrectAnimationUC)(appObjects);
    const mockIncorrectAnimation = (0, MockIncorrectAnimation_1.makeMockLabelDropIncorrectAnimationUC)(appObjects);
    const labelDrop = (0, LabelDropRepo_1.makeLabelDropRepo)(labelDropAO);
    const changeObserver = jest.fn();
    labelDrop.addChangeObserver(changeObserver);
    const mockRayPick = (0, MockSceneRayPickUC_1.makeMockSceneRayPickUC)(appObjects);
    const mockPick = jest.fn().mockReturnValue({
        hit: true,
        worldPickPoint: new core_2.Vector3(1, 2, 3),
    });
    mockRayPick.sceneRayPick = mockPick;
    const mockStylusTransform = (0, Transform3D_1.makeTransform3D)(appObjects.getOrCreate("stylus"));
    labelDrop.dragHelperTransform.parent = mockStylusTransform;
    mockStylusTransform.worldPosition = new core_2.Vector3(1, 2, 0);
    const uc = (0, DragLabelDropWorldUC_1.makeDragLabelDropWorldUC)(labelDropAO);
    challenge.selectedChallenge = "LABEL_DROP";
    baseApp.isAuthoring = false;
    return {
        appObjects,
        labelDrop,
        uc,
        changeObserver,
        baseApp,
        challenge,
        mockPick,
        mockStylusTransform,
        mockDropAnimation,
        mockCorrectAnimation,
        mockIncorrectAnimation,
    };
}
describe("Drag Label Drop UC", () => {
    it("initializes id on press, mode and alpha", () => {
        const { uc, labelDrop } = makeTestRig();
        expect(labelDrop.draggingID).toBeUndefined();
        uc.initializeDrag("id1", core_2.ParametricLine.Forward());
        expect(labelDrop.draggingID).toEqual("id1");
        expect(labelDrop.dragMode).toEqual(LabelDropRepo_1.LabelDropDragMode.WORLD);
        expect(labelDrop.dragAlpha).toEqual(1);
    });
    it("Sets the world position of the label", () => {
        const { uc, labelDrop } = makeTestRig();
        uc.initializeDrag("id1", core_2.ParametricLine.Forward());
        const expectPos = new core_2.Vector3(1, 2, 3 * uc.percentOfPickDepth);
        expect(labelDrop.dragLabelTransform.worldPosition).toEqual(expectPos);
    });
    it("Sets the world rotation of the label", () => {
        const { uc, labelDrop, mockStylusTransform } = makeTestRig();
        const rot = core_2.Quaternion.FromYawPitchRoll(core_2.Angle.FromDegrees(10), core_2.Angle.FromDegrees(20), core_2.Angle.FromDegrees(30));
        mockStylusTransform.worldRotation = rot;
        uc.initializeDrag("id1", core_2.ParametricLine.Forward());
        expect(core_2.Quaternion.Close(labelDrop.dragLabelTransform.worldRotation, rot)).toEqual(true);
    });
    it("Does not initialize if challenge is not label drop", () => {
        const { uc, labelDrop, challenge } = makeTestRig();
        challenge.selectedChallenge = "NONE";
        uc.initializeDrag("id1", core_2.ParametricLine.Forward());
        expect(labelDrop.draggingID).toBeUndefined();
    });
    it("Does not initialize if authoring", () => {
        const { uc, labelDrop, baseApp } = makeTestRig();
        baseApp.isAuthoring = true;
        uc.initializeDrag("id1", core_2.ParametricLine.Forward());
        expect(labelDrop.draggingID).toBeUndefined();
    });
    it("Updates the position on drag", () => {
        const { uc, labelDrop, mockPick, mockStylusTransform } = makeTestRig();
        uc.initializeDrag("id", core_2.ParametricLine.Forward());
        // Move stylus to 10,20,30 (world)
        // Set pick to 10,20,0 (world)
        // Local pick is 0,0, 30 (local stylus)
        // Reduced is 0,0, 28.5 (assume 95%)
        // Reduced is 10,20,1.5 (world)
        mockStylusTransform.worldPosition = new core_2.Vector3(10, 20, 30);
        const mockPickResult = {
            hit: true,
            worldPickPoint: new core_2.Vector3(10, 20, 0),
        };
        mockPick.mockReturnValue(mockPickResult);
        uc.updateDrag(core_2.ParametricLine.Forward());
        const expectedDepth = 30 * (1 - uc.percentOfPickDepth);
        const expectedPos = new core_2.Vector3(10, 20, expectedDepth);
        expect(core_2.Vector3.Close(labelDrop.dragLabelTransform.worldPosition, expectedPos)).toEqual(true);
    });
    it("Sets the position at zero parallax if there is no intersection", () => {
        const { uc, labelDrop, mockPick } = makeTestRig();
        uc.initializeDrag("id", core_2.ParametricLine.Forward());
        const mockPickResult = {
            hit: false,
        };
        mockPick.mockReturnValue(mockPickResult);
        uc.updateDrag(core_2.ParametricLine.Forward());
        const expectedPos = new core_2.Vector3(1, 2, 0);
        expect(core_2.Vector3.Close(labelDrop.dragLabelTransform.worldPosition, expectedPos)).toEqual(true);
    });
    it("Updates the rotation on drag", () => {
        const { uc, labelDrop, mockStylusTransform } = makeTestRig();
        uc.initializeDrag("id", core_2.ParametricLine.Forward());
        expect(core_2.Quaternion.Close(labelDrop.dragLabelTransform.worldRotation, core_2.Quaternion.Identity())).toEqual(true);
        const rot = core_2.Quaternion.FromYawPitchRoll(core_2.Angle.FromDegrees(10), core_2.Angle.FromDegrees(20), core_2.Angle.FromDegrees(30));
        mockStylusTransform.worldRotation = rot;
        uc.updateDrag(core_2.ParametricLine.Forward());
        expect(core_2.Quaternion.Close(labelDrop.dragLabelTransform.worldRotation, rot)).toEqual(true);
    });
    it("Does not set the 3D position if it did not initialize", () => {
        const { uc, labelDrop, mockPick } = makeTestRig();
        labelDrop.dragLabelTransform.worldPosition = core_2.Vector3.Zero();
        mockPick.mockReturnValue({
            worldPickPoint: new core_2.Vector3(1, 2, 3),
            hit: true,
            normal: new core_2.Vector3(4, 5, 6),
            objectPickMeta: {
                appObjectID: "appObj1",
            },
        });
        uc.updateDrag(core_2.ParametricLine.Forward());
        expect(labelDrop.dragLabelTransform.worldPosition).toEqual(core_2.Vector3.Zero());
    });
    it("Submits the object hit when released", () => {
        const { uc, labelDrop, mockPick } = makeTestRig();
        const mockPickResult = {
            hit: true,
            worldPickPoint: new core_2.Vector3(1, 2, 3),
            appObjectID: "appObj1",
        };
        mockPick.mockReturnValue(mockPickResult);
        uc.initializeDrag("labelDrop1", core_2.ParametricLine.Forward());
        labelDrop.submitLabelDrop = jest.fn();
        uc.releaseDrag(core_2.ParametricLine.Forward());
        expect(labelDrop.submitLabelDrop).toHaveBeenCalledWith("labelDrop1", "appObj1");
    });
    it("submits a label drop answer if an app object is hit", () => {
        const { uc, labelDrop, mockPick } = makeTestRig();
        const mockPickResult = {
            hit: true,
            worldPickPoint: new core_2.Vector3(1, 2, 3),
            appObjectID: "appObj1",
        };
        mockPick.mockReturnValue(mockPickResult);
        labelDrop.submitLabelDrop = jest.fn();
        uc.initializeDrag("labelDrop1", core_2.ParametricLine.Forward());
        uc.releaseDrag(core_2.ParametricLine.Forward());
        expect(labelDrop.submitLabelDrop).toHaveBeenCalled();
    });
    it("Does not submit a label drop answer if an app object is not hit", async () => {
        const { uc, labelDrop, mockPick } = makeTestRig();
        labelDrop.submitLabelDrop = jest.fn();
        uc.initializeDrag("labelDrop1", core_2.ParametricLine.Forward());
        const mockPickResult = {
            hit: false,
        };
        mockPick.mockReturnValue(mockPickResult);
        uc.releaseDrag(core_2.ParametricLine.Forward());
        expect(labelDrop.submitLabelDrop).not.toHaveBeenCalled();
    });
    it("Kicks off the drop animation", () => {
        const { uc, mockPick, mockDropAnimation } = makeTestRig();
        uc.initializeDrag("labelDrop1", core_2.ParametricLine.Forward());
        const mockPickResult = {
            hit: false,
        };
        mockPick.mockReturnValue(mockPickResult);
        uc.releaseDrag(core_2.ParametricLine.Forward());
        expect(mockDropAnimation.start).toHaveBeenCalled();
    });
    it("Sets the desired position for the drop animation", () => {
        const { uc, mockPick, mockDropAnimation } = makeTestRig();
        expect(mockDropAnimation.desiredFinalPosition).toEqual(core_2.Vector3.Zero());
        uc.initializeDrag("labelDrop1", core_2.ParametricLine.Forward());
        const mockPickResult = {
            hit: false,
        };
        mockPick.mockReturnValue(mockPickResult);
        uc.releaseDrag(core_2.ParametricLine.Forward());
        expect(mockDropAnimation.desiredFinalPosition).toEqual(new core_2.Vector3(1, 2, 3));
    });
    it("Kicks off the incorrect animation", () => {
        const { uc, mockPick, mockIncorrectAnimation, labelDrop } = makeTestRig();
        uc.initializeDrag("labelDrop1", core_2.ParametricLine.Forward());
        const mockPickResult = {
            hit: true,
            worldPickPoint: new core_2.Vector3(1, 2, 3),
            appObjectID: "appObj",
        };
        mockPick.mockReturnValue(mockPickResult);
        labelDrop.submitLabelDrop = jest.fn().mockReturnValue(false);
        uc.releaseDrag(core_2.ParametricLine.Forward());
        expect(mockIncorrectAnimation.start).toHaveBeenCalled();
    });
    it("Sets the desired position for the incorrect animation", () => {
        const { uc, mockPick, mockIncorrectAnimation, labelDrop } = makeTestRig();
        expect(mockIncorrectAnimation.desiredFinalPosition).toEqual(core_2.Vector3.Zero());
        uc.initializeDrag("labelDrop1", core_2.ParametricLine.Forward());
        const mockPickResult = {
            hit: true,
            worldPickPoint: new core_2.Vector3(1, 2, 3),
            appObjectID: "appObj",
        };
        mockPick.mockReturnValue(mockPickResult);
        labelDrop.submitLabelDrop = jest.fn().mockReturnValue(false);
        uc.releaseDrag(core_2.ParametricLine.Forward());
        expect(mockIncorrectAnimation.desiredFinalPosition).toEqual(new core_2.Vector3(1, 2, 3));
    });
    it("Kicks off the correct animation", () => {
        const { uc, mockPick, mockCorrectAnimation, labelDrop } = makeTestRig();
        uc.initializeDrag("labelDrop1", core_2.ParametricLine.Forward());
        const mockPickResult = {
            hit: true,
            worldPickPoint: new core_2.Vector3(1, 2, 3),
            appObjectID: "appObj",
        };
        mockPick.mockReturnValue(mockPickResult);
        labelDrop.submitLabelDrop = jest.fn().mockReturnValue(true);
        uc.releaseDrag(core_2.ParametricLine.Forward());
        expect(mockCorrectAnimation.start).toHaveBeenCalled();
    });
    it("Does not submit if no object hit on release", () => {
        const { uc, labelDrop, mockPick } = makeTestRig();
        mockPick.mockReturnValue({
            worldPickPoint: new core_2.Vector3(1, 2, 3),
            hit: false,
            normal: new core_2.Vector3(4, 5, 6),
            objectPickMeta: {},
        });
        uc.initializeDrag("labelDrop1", core_2.ParametricLine.Forward());
        labelDrop.submitLabelDrop = jest.fn();
        uc.releaseDrag(core_2.ParametricLine.Forward());
        expect(labelDrop.submitLabelDrop).not.toHaveBeenCalled();
    });
    it("Resets dragging ID after the animation ends", async () => {
        const { uc, labelDrop } = makeTestRig();
        uc.initializeDrag("labelDrop1", core_2.ParametricLine.Forward());
        expect(labelDrop.draggingID).toEqual("labelDrop1");
        await uc.releaseDrag(core_2.ParametricLine.Forward());
        expect(labelDrop.draggingID).toBeUndefined();
    });
    it("Resets the result after the animation ends", async () => {
        const { uc, labelDrop } = makeTestRig();
        uc.initializeDrag("labelDrop1", core_2.ParametricLine.Forward());
        expect(labelDrop.draggingID).toEqual("labelDrop1");
        const spy = jest.spyOn(labelDrop, "resultIsCorrect", "set");
        await uc.releaseDrag(core_2.ParametricLine.Forward());
        expect(spy).toHaveBeenCalledWith(undefined);
    });
    it("Sets mode to review if correct if there are no more labels after the animation has completed", async () => {
        const { uc, labelDrop, baseApp, mockPick } = makeTestRig();
        expect(baseApp.isReviewing).toEqual(false);
        const mockPickResult = {
            hit: true,
            worldPickPoint: new core_2.Vector3(1, 2, 3),
            appObjectID: "appObj",
        };
        mockPick.mockReturnValue(mockPickResult);
        labelDrop.getRemainingLabelDrops = jest.fn().mockReturnValue([]);
        labelDrop.submitLabelDrop = jest.fn().mockReturnValue(true);
        uc.initializeDrag("labelDrop1", core_2.ParametricLine.Forward());
        await uc.releaseDrag(core_2.ParametricLine.Forward());
        expect(baseApp.isReviewing).toEqual(true);
    });
    it("Does not set the mode to review  if there are  more labels", () => {
        const { uc, labelDrop, baseApp } = makeTestRig();
        expect(baseApp.isReviewing).toEqual(false);
        labelDrop.getRemainingLabelDrops = jest
            .fn()
            .mockReturnValue(["anbotherLabel"]);
        labelDrop.submitLabelDrop = jest.fn().mockReturnValue(true);
        uc.initializeDrag("labelDrop1", core_2.ParametricLine.Forward());
        uc.releaseDrag(core_2.ParametricLine.Forward());
        expect(baseApp.isReviewing).toEqual(false);
    });
    it("Cancels any running animations on initialization", () => {
        const { uc, labelDrop, mockDropAnimation } = makeTestRig();
        labelDrop.getRemainingLabelDrops = jest.fn().mockReturnValue([]);
        uc.initializeDrag("labelDrop1", core_2.ParametricLine.Forward());
        uc.releaseDrag(core_2.ParametricLine.Forward());
        expect(mockDropAnimation.start).toHaveBeenCalled();
        uc.initializeDrag("labelDrop2", core_2.ParametricLine.Forward());
        expect(mockDropAnimation.cancel).toHaveBeenCalled();
    });
});
//# sourceMappingURL=DragLabelDropWorldUC.test.js.map