import { makeAppObjectRepo } from "@vived/core";
import { ParametricLine, Vector2, Vector3 } from "@vived/core";
import { makeMockPixelToSceneRayUC, makeMockSceneRayPickUC, } from "../../Babylon/Mocks";
import { makeMockDispatchStateChange } from "../../Dispatcher/Mocks/MockDispatchStateChange";
import { makeTransform3D } from "../../Transform3D/Entities/Transform3D";
import { makeUndoRedoEntity } from "../../UndoRedo/Entities/UndoRedoEntity";
import { makeStickableEntity } from "../Entities/Stickable";
import { makePanTransformWithStickUC } from "./PanTransformWithStickUC";
import { makeTryPickStickTargetUC } from "./TryPickStickTarget";
function makeTestRig() {
    const appObjects = makeAppObjectRepo();
    const ao = appObjects.getOrCreate("transform");
    const transform = makeTransform3D(ao);
    const panUC = makePanTransformWithStickUC(ao);
    const stickable = makeStickableEntity(ao);
    const tryPickTarget = makeTryPickStickTargetUC(ao);
    tryPickTarget.tryPick = () => {
        return true;
    };
    const mockPick = makeMockSceneRayPickUC(appObjects);
    const mockDispatch = makeMockDispatchStateChange(appObjects);
    const doDispatchMock = jest.fn();
    mockDispatch.doDispatch = doDispatchMock;
    const mockPixelRay = makeMockPixelToSceneRayUC(appObjects);
    mockPixelRay.pixelToSceneRay = mockPicker;
    const undo = makeUndoRedoEntity(appObjects.getOrCreate("Undo"));
    return {
        panUC,
        transform,
        mockPick,
        doDispatchMock,
        appObjects,
        mockPixelRay,
        undo,
        stickable,
        tryPickTarget,
    };
}
function mockPicker(pixel) {
    return ParametricLine.FromPointDirection(new Vector3(pixel.x, pixel.y, 3), Vector3.Forward());
}
describe("Pan Transform With Stick UC", () => {
    it("Moves the transform", () => {
        const { transform, panUC } = makeTestRig();
        panUC.initializePixel(Vector2.Zero());
        panUC.updatePixel(new Vector2(1, 2));
        expect(transform.worldPosition).toEqual(new Vector3(1, 2, 0));
    });
    it("Moves the transform relative to the initial position", () => {
        const { transform, panUC } = makeTestRig();
        transform.worldPosition = new Vector3(10, 10, 10);
        panUC.initializePixel(Vector2.Zero());
        panUC.updatePixel(new Vector2(1, 2));
        expect(transform.worldPosition).toEqual(new Vector3(11, 12, 10));
    });
    it("Dispatches a state change if the position has changed since init", () => {
        const { transform, panUC, doDispatchMock } = makeTestRig();
        transform.worldPosition = new Vector3(1, 2, 3);
        panUC.initializePixel(Vector2.Zero());
        transform.worldPosition = new Vector3(4, 5, 6);
        panUC.finish();
        expect(doDispatchMock).toHaveBeenCalled();
    });
    it("Does not dispatch a state change if the position has not changed", () => {
        const { transform, panUC, doDispatchMock } = makeTestRig();
        transform.worldPosition = new Vector3(1, 2, 3);
        panUC.initializePixel(Vector2.Zero());
        panUC.finish();
        expect(doDispatchMock).not.toHaveBeenCalled();
    });
    it("Does not dispatch state change if dispatchStateChangeOnComplete is false", () => {
        const { transform, panUC, doDispatchMock } = makeTestRig();
        panUC.dispatchStateChangeOnComplete = false;
        transform.worldPosition = new Vector3(1, 2, 3);
        panUC.initializePixel(Vector2.Zero());
        transform.worldPosition = new Vector3(4, 5, 6);
        panUC.finish();
        expect(doDispatchMock).not.toHaveBeenCalled();
    });
    it("Doesn't not move the transform after cancel", () => {
        const { transform, panUC } = makeTestRig();
        panUC.initializePixel(Vector2.Zero());
        panUC.cancelPan();
        panUC.updatePixel(new Vector2(1, 2));
        expect(transform.worldPosition).toEqual(Vector3.Zero());
    });
    it("Limits the minimum X", () => {
        const { transform, panUC } = makeTestRig();
        panUC.minX = 0;
        panUC.initializePixel(Vector2.Zero());
        panUC.updatePixel(new Vector2(-1, 2));
        expect(transform.worldPosition).toEqual(new Vector3(0, 2, 0));
    });
    it("Limits the maximum X", () => {
        const { transform, panUC } = makeTestRig();
        panUC.maxX = 0;
        panUC.initializePixel(Vector2.Zero());
        panUC.updatePixel(new Vector2(1, 2));
        expect(transform.worldPosition).toEqual(new Vector3(0, 2, 0));
    });
    it("Limits the minimum Y", () => {
        const { transform, panUC } = makeTestRig();
        panUC.minY = 0;
        panUC.initializePixel(Vector2.Zero());
        panUC.updatePixel(new Vector2(-1, -2));
        expect(transform.worldPosition).toEqual(new Vector3(-1, 0, 0));
    });
    it("Limits the maximum Y", () => {
        const { transform, panUC } = makeTestRig();
        panUC.maxY = 0;
        panUC.initializePixel(Vector2.Zero());
        panUC.updatePixel(new Vector2(1, 2));
        expect(transform.worldPosition).toEqual(new Vector3(1, 0, 0));
    });
    it("Does not update if disabled", () => {
        const { transform, panUC } = makeTestRig();
        transform.worldPosition = Vector3.Zero();
        panUC.enabled = false;
        panUC.initializePixel(Vector2.Zero());
        panUC.updatePixel(new Vector2(10, 20));
        expect(transform.worldPosition).toEqual(Vector3.Zero());
    });
    it("Submits an undo on stop", () => {
        const { panUC, undo } = makeTestRig();
        panUC.initializePixel(Vector2.Zero());
        panUC.updatePixel(new Vector2(10, 20));
        panUC.finish();
        expect(undo.hasUndo).toEqual(true);
    });
    it("Does not submit an undo on stop if flag is set to false", () => {
        const { panUC, undo } = makeTestRig();
        panUC.submitUndoOnComplete = false;
        panUC.initializePixel(Vector2.Zero());
        panUC.updatePixel(new Vector2(10, 20));
        panUC.finish();
        expect(undo.hasUndo).toEqual(false);
    });
    it("Does not submit an undo on stop if there was no movement", () => {
        const { panUC, undo } = makeTestRig();
        panUC.initializePixel(Vector2.Zero());
        panUC.finish();
        expect(undo.hasUndo).toEqual(false);
    });
    it("Wires up the dispatch for undo and redo", () => {
        const { panUC, undo, doDispatchMock } = makeTestRig();
        panUC.initializePixel(Vector2.Zero());
        panUC.updatePixel(new Vector2(10, 20));
        panUC.finish();
        doDispatchMock.mockClear();
        undo.doUndo();
        expect(doDispatchMock).toHaveBeenCalledTimes(1);
        undo.doRedo();
        expect(doDispatchMock).toHaveBeenCalledTimes(2);
    });
    it("Undoes and redoes the move", () => {
        const { panUC, undo, transform } = makeTestRig();
        const initialPos = transform.localPosition;
        panUC.initializePixel(Vector2.Zero());
        panUC.updatePixel(new Vector2(10, 20));
        panUC.finish();
        const fianlPos = transform.localPosition;
        undo.doUndo();
        expect(transform.localPosition).toEqual(initialPos);
        undo.doRedo();
        expect(transform.localPosition).toEqual(fianlPos);
    });
});
//# sourceMappingURL=PanTransformWithStickUC.test.js.map