import { makeAppObjectRepo } from "@vived/core";
import { ParametricLine, Vector2, Vector3 } from "@vived/core";
import { PixelToSceneRayUC, ScenePixelPickUC } from "../../Babylon";
import { makeMockDispatchStateChange } from "../../Dispatcher";
import { makeSceneRootEntity } from "../Entities";
import { makePinchSceneRootUC, PinchSceneRootUC } from "./PinchSceneRoot";
class MockPick extends ScenePixelPickUC {
    constructor() {
        super(...arguments);
        this.scenePixelPick = jest.fn();
    }
}
class MockPixelToRay extends PixelToSceneRayUC {
    constructor() {
        super(...arguments);
        this.pixelToSceneRay = (pixelPos) => {
            return ParametricLine.FromPointDirection(new Vector3(pixelPos.x, pixelPos.y, -10), Vector3.Forward());
        };
    }
}
function makeTestRig() {
    const appObjects = makeAppObjectRepo();
    const sceneRootAO = appObjects.getOrCreate("sceneRoot");
    const sceneRoot = makeSceneRootEntity(sceneRootAO);
    const pinchUC = makePinchSceneRootUC(sceneRootAO);
    const appAO = appObjects.getOrCreate("appAO");
    const mockPick = new MockPick(appAO, ScenePixelPickUC.type);
    const mockRay = new MockPixelToRay(appAO, PixelToSceneRayUC.type);
    const mockDispatch = makeMockDispatchStateChange(appObjects);
    const doDispatchMock = jest.fn();
    mockDispatch.doDispatch = doDispatchMock;
    return {
        appObjects,
        pinchUC,
        sceneRoot,
        mockPick,
        mockDispatch,
        doDispatchMock,
        mockRay,
    };
}
describe("Pinch Scene Root Use Case", () => {
    it("Move with no scaling adjusts the root as expected", () => {
        const { pinchUC, sceneRoot } = makeTestRig();
        sceneRoot.position = new Vector3(1, 2, 3);
        const touch1 = new Vector2(5, 8);
        const touch2 = new Vector2(5, 0);
        pinchUC.initializePinch(touch1, touch2);
        const touch3 = new Vector2(0, 8);
        const touch4 = new Vector2(0, 0);
        pinchUC.doPinch(touch3, touch4);
        const expected = new Vector3(-4, 2, 3); // -5 in the x
        const wPos = sceneRoot.position;
        expect(Vector3.Close(wPos, expected)).toEqual(true);
    });
    it("Plane pick is relative", () => {
        const { pinchUC, sceneRoot, mockPick } = makeTestRig();
        mockPick.scenePixelPick.mockReturnValue(new Vector3(10, 20, 60));
        sceneRoot.position = new Vector3(1, 2, 3);
        const touch1 = new Vector2(5, 8);
        const touch2 = new Vector2(5, 0);
        pinchUC.initializePinch(touch1, touch2);
        const touch3 = new Vector2(0, 8);
        const touch4 = new Vector2(0, 0);
        pinchUC.doPinch(touch3, touch4);
        const expected = new Vector3(-4, 2, 3); // -5 in the x
        const wPos = sceneRoot.position;
        expect(Vector3.Close(wPos, expected)).toEqual(true);
    });
    it("Scales smaller with a pinch that moves closer", () => {
        const { pinchUC, sceneRoot } = makeTestRig();
        sceneRoot.position = new Vector3(0, 0, 0);
        sceneRoot.scale = 1;
        const touch1 = new Vector2(0, 8);
        const touch2 = new Vector2(0, -8);
        pinchUC.initializePinch(touch1, touch2);
        const touch3 = new Vector2(0, 4);
        const touch4 = new Vector2(0, -4);
        pinchUC.doPinch(touch3, touch4);
        const expectedScaleDelta = pinchUC.sensitivity * 8;
        expect(sceneRoot.scale).toEqual(1 - expectedScaleDelta);
    });
    it("Scales larger with a pinch that moves further", () => {
        const { pinchUC, sceneRoot } = makeTestRig();
        sceneRoot.position = new Vector3(0, 0, 0);
        sceneRoot.scale = 1;
        const touch1 = new Vector2(0, 8);
        const touch2 = new Vector2(0, -8);
        pinchUC.initializePinch(touch1, touch2);
        const touch3 = new Vector2(0, 12);
        const touch4 = new Vector2(0, -12);
        pinchUC.doPinch(touch3, touch4);
        const expectedScaleDelta = pinchUC.sensitivity * 8;
        expect(sceneRoot.scale).toEqual(1 + expectedScaleDelta);
    });
    it("Dispatches a state change if the position has changed since init", () => {
        const { sceneRoot, pinchUC, doDispatchMock, mockPick } = makeTestRig();
        sceneRoot.scale = 5;
        const touch1 = new Vector2(0, 8);
        const touch2 = new Vector2(0, -8);
        pinchUC.initializePinch(touch1, touch2);
        sceneRoot.scale = 6;
        pinchUC.finishPinch();
        expect(doDispatchMock).toHaveBeenCalled();
    });
    it("Does not dispatch a state change if the scale has not changed", () => {
        const { sceneRoot, pinchUC, doDispatchMock } = makeTestRig();
        sceneRoot.scale = 5;
        const touch1 = new Vector2(0, 8);
        const touch2 = new Vector2(0, -8);
        pinchUC.initializePinch(touch1, touch2);
        pinchUC.finishPinch();
        expect(doDispatchMock).not.toHaveBeenCalled();
    });
    it("Gets the UC", () => {
        const { pinchUC, appObjects } = makeTestRig();
        expect(PinchSceneRootUC.get(appObjects)).toEqual(pinchUC);
    });
});
//# sourceMappingURL=PinchSceneRoot.test.js.map