import { makeAppObjectRepo } from "@vived/core";
import { Angle, ParametricLine, Quaternion, Vector3 } from "@vived/core";
import { makeMockDispatchStateChange } from "../../Dispatcher/Mocks/MockDispatchStateChange";
import { makeTransform3D } from "../../Transform3D/Entities/Transform3D";
import { makeUndoRedoEntity } from "../../UndoRedo/Entities/UndoRedoEntity";
import { makeStickableEntity } from "../Entities/Stickable";
import { makeMoveTransformWithStickUC } from "./MoveTransformWithStickUC";
import { makeTryPickStickTargetUC } from "./TryPickStickTarget";
function makeTestRig() {
    const appObjects = makeAppObjectRepo();
    const ao = appObjects.getOrCreate("transform");
    const transform = makeTransform3D(ao);
    const moveUC = makeMoveTransformWithStickUC(ao);
    const stickable = makeStickableEntity(ao);
    const tryPickTarget = makeTryPickStickTargetUC(ao);
    tryPickTarget.tryPick = () => {
        return true;
    };
    const mockDispatch = makeMockDispatchStateChange(appObjects);
    const doDispatchMock = jest.fn();
    mockDispatch.doDispatch = doDispatchMock;
    const undo = makeUndoRedoEntity(appObjects.getOrCreate("Undo"));
    const helper = makeTransform3D(appObjects.getOrCreate("Helper"));
    return {
        moveUC,
        transform,
        doDispatchMock,
        appObjects,
        undo,
        stickable,
        tryPickTarget,
        helper,
    };
}
describe("Pan Transform With Stick UC", () => {
    it("Shows the targets on the first move if the pick ray does not hit the targets", () => {
        const { stickable, moveUC, helper, tryPickTarget } = makeTestRig();
        tryPickTarget.tryPick = () => {
            return false;
        };
        moveUC.initialize(helper);
        expect(stickable.showStickTarget).toEqual(false);
        moveUC.update(helper, ParametricLine.Forward());
        expect(stickable.showStickTarget).toEqual(true);
        expect(stickable.highlightTarget).toEqual(false);
    });
    it("Hides the targets on the first if the pick ray hit the targets", () => {
        const { stickable, moveUC, helper, tryPickTarget } = makeTestRig();
        tryPickTarget.tryPick = () => {
            return true;
        };
        moveUC.initialize(helper);
        expect(stickable.showStickTarget).toEqual(false);
        moveUC.update(helper, ParametricLine.Forward());
        expect(stickable.showStickTarget).toEqual(false);
        expect(stickable.highlightTarget).toEqual(false);
    });
    it("Shows the targets after moving so that there is no target pick on the first if the pick ray hit the targets", () => {
        const { stickable, moveUC, helper, tryPickTarget } = makeTestRig();
        tryPickTarget.tryPick = () => {
            return true;
        };
        moveUC.initialize(helper);
        expect(stickable.showStickTarget).toEqual(false);
        moveUC.update(helper, ParametricLine.Forward());
        expect(stickable.showStickTarget).toEqual(false);
        tryPickTarget.tryPick = () => {
            return false;
        };
        moveUC.update(helper, ParametricLine.Forward());
        expect(stickable.showStickTarget).toEqual(true);
    });
    it("Highlights the targets when the start to pick on them after a move", () => {
        const { stickable, moveUC, helper, tryPickTarget } = makeTestRig();
        tryPickTarget.tryPick = () => {
            return false;
        };
        moveUC.initialize(helper);
        moveUC.update(helper, ParametricLine.Forward());
        expect(stickable.highlightTarget).toEqual(false);
        tryPickTarget.tryPick = () => {
            return true;
        };
        moveUC.update(helper, ParametricLine.Forward());
        expect(stickable.highlightTarget).toEqual(true);
    });
    it("Hides the targets on finish", () => {
        const { stickable, moveUC, helper, tryPickTarget } = makeTestRig();
        tryPickTarget.tryPick = () => {
            return false;
        };
        moveUC.initialize(helper);
        moveUC.update(helper, ParametricLine.Forward());
        expect(stickable.showStickTarget).toEqual(true);
        moveUC.finish();
        expect(stickable.showStickTarget).toEqual(false);
    });
    it("Hides the targets on cancel", () => {
        const { stickable, moveUC, helper, tryPickTarget } = makeTestRig();
        tryPickTarget.tryPick = () => {
            return false;
        };
        moveUC.initialize(helper);
        moveUC.update(helper, ParametricLine.Forward());
        expect(stickable.showStickTarget).toEqual(true);
        moveUC.cancel();
        expect(stickable.showStickTarget).toEqual(false);
    });
    it("Triggers a stick on finish if picking on a target", () => {
        const { stickable, moveUC, helper, tryPickTarget } = makeTestRig();
        stickable.doStick = jest.fn();
        tryPickTarget.tryPick = () => {
            return false;
        };
        moveUC.initialize(helper);
        moveUC.update(helper, ParametricLine.Forward());
        tryPickTarget.tryPick = () => {
            return true;
        };
        moveUC.update(helper, ParametricLine.Forward());
        expect(stickable.highlightTarget).toEqual(true);
        moveUC.finish();
        expect(stickable.doStick).toHaveBeenCalled();
    });
    it("Does not trigger a stick on finish if picking on a target", () => {
        const { stickable, moveUC, helper, tryPickTarget } = makeTestRig();
        stickable.doStick = jest.fn();
        tryPickTarget.tryPick = () => {
            return false;
        };
        moveUC.initialize(helper);
        moveUC.update(helper, ParametricLine.Forward());
        expect(stickable.highlightTarget).toEqual(false);
        moveUC.finish();
        expect(stickable.doStick).not.toHaveBeenCalled();
    });
    it("Tells stick to dispatch a state change on complete if the flag is set", () => {
        const { stickable, moveUC, helper, tryPickTarget, doDispatchMock } = makeTestRig();
        moveUC.dispatchStateChangeOnComplete = true;
        stickable.doStick = jest.fn();
        tryPickTarget.tryPick = () => {
            return false;
        };
        moveUC.initialize(helper);
        moveUC.update(helper, ParametricLine.Forward());
        tryPickTarget.tryPick = () => {
            return true;
        };
        moveUC.update(helper, ParametricLine.Forward());
        expect(stickable.highlightTarget).toEqual(true);
        moveUC.finish();
        expect(stickable.doStick).toHaveBeenCalledWith(doDispatchMock);
    });
    it("Does not tell stick to dispatch a state change on complete if the flag is set", () => {
        const { stickable, moveUC, helper, tryPickTarget } = makeTestRig();
        moveUC.dispatchStateChangeOnComplete = false;
        stickable.doStick = jest.fn();
        tryPickTarget.tryPick = () => {
            return false;
        };
        moveUC.initialize(helper);
        moveUC.update(helper, ParametricLine.Forward());
        tryPickTarget.tryPick = () => {
            return true;
        };
        moveUC.update(helper, ParametricLine.Forward());
        expect(stickable.highlightTarget).toEqual(true);
        moveUC.finish();
        expect(stickable.doStick).toHaveBeenCalledWith();
    });
    it("Submits an undo when stuck if the flag is set", () => {
        const { stickable, moveUC, helper, tryPickTarget, undo } = makeTestRig();
        moveUC.submitUndoOnComplete = true;
        stickable.doStick = jest.fn();
        tryPickTarget.tryPick = () => {
            return false;
        };
        moveUC.initialize(helper);
        moveUC.update(helper, ParametricLine.Forward());
        tryPickTarget.tryPick = () => {
            return true;
        };
        moveUC.update(helper, ParametricLine.Forward());
        expect(stickable.highlightTarget).toEqual(true);
        moveUC.finish();
        expect(undo.hasUndo).toEqual(true);
    });
    it("Does not submit an undo when stuck if the flag is set", () => {
        const { stickable, moveUC, helper, tryPickTarget, undo } = makeTestRig();
        moveUC.submitUndoOnComplete = false;
        stickable.doStick = jest.fn();
        tryPickTarget.tryPick = () => {
            return false;
        };
        moveUC.initialize(helper);
        moveUC.update(helper, ParametricLine.Forward());
        tryPickTarget.tryPick = () => {
            return true;
        };
        moveUC.update(helper, ParametricLine.Forward());
        expect(stickable.highlightTarget).toEqual(true);
        moveUC.finish();
        expect(undo.hasUndo).toEqual(false);
    });
    it("Wires up the dispatch for undo and redo", () => {
        const { stickable, moveUC, helper, tryPickTarget, undo, doDispatchMock } = makeTestRig();
        stickable.doStick = jest.fn();
        tryPickTarget.tryPick = () => {
            return false;
        };
        moveUC.initialize(helper);
        moveUC.update(helper, ParametricLine.Forward());
        tryPickTarget.tryPick = () => {
            return true;
        };
        moveUC.update(helper, ParametricLine.Forward());
        expect(stickable.highlightTarget).toEqual(true);
        moveUC.finish();
        doDispatchMock.mockClear();
        undo.doUndo();
        expect(doDispatchMock).toHaveBeenCalledTimes(1);
        undo.doRedo();
        expect(doDispatchMock).toHaveBeenCalledTimes(2);
    });
    it("Undoes and redoes the move", () => {
        const { stickable, moveUC, helper, tryPickTarget, undo, transform } = makeTestRig();
        stickable.doStick = jest.fn();
        const initialPos = new Vector3(1, 2, 3);
        const initialRot = Quaternion.FromAngleAxis(new Vector3(4, 5, 6), Angle.FromDegrees(7));
        transform.localPosition = initialPos;
        transform.localRotation = initialRot;
        stickable.stickPosition = Vector3.Zero();
        stickable.stickRotation = Quaternion.Identity();
        tryPickTarget.tryPick = () => {
            return false;
        };
        moveUC.initialize(helper);
        moveUC.update(helper, ParametricLine.Forward());
        tryPickTarget.tryPick = () => {
            return true;
        };
        moveUC.update(helper, ParametricLine.Forward());
        expect(stickable.highlightTarget).toEqual(true);
        moveUC.finish();
        undo.doUndo();
        expect(transform.localPosition).toEqual(initialPos);
        expect(Quaternion.Close(transform.localRotation, initialRot)).toEqual(true);
        undo.doRedo();
        expect(transform.localPosition).toEqual(Vector3.Zero());
        expect(Quaternion.Close(transform.localRotation, Quaternion.Identity())).toEqual(true);
    });
});
//# sourceMappingURL=MoveTransformWithStickUC.test.js.map