import { makeAppObject, makeAppObjectRepo } from "@vived/core";
import { Angle, Quaternion, Vector3 } from "@vived/core";
import { makeStateMachineEntity } from "../../StateMachine/Entities/StateMachineEntity";
import { makeStoredView } from "../../StoredView";
import { makeSceneRootEntity } from "../Entities";
import { makeSerializeSceneRoot, SerializeSceneRoot, } from "./SerializeSceneRoot";
function makeTestRig() {
    const appObjects = makeAppObjectRepo();
    const appObj = appObjects.getOrCreate("Scene Root");
    const storedView = makeStoredView(appObj);
    const sceneRoot = makeSceneRootEntity(appObj);
    const stateMachine = makeStateMachineEntity(appObj);
    const mockRegister = jest.fn();
    stateMachine.registerSerializedSystem = mockRegister;
    const serializer = makeSerializeSceneRoot(appObj);
    return {
        mockRegister,
        sceneRoot,
        storedView,
        stateMachine,
        serializer,
        appObj,
        appObjects,
    };
}
describe("Serializing the Scene Root", () => {
    it("Registers with the state machine on construction", () => {
        const { mockRegister } = makeTestRig();
        expect(mockRegister).toHaveBeenCalled();
    });
    it("Serializes the Scene Root as expected", () => {
        const { sceneRoot, serializer } = makeTestRig();
        sceneRoot.position = new Vector3(1, 2, 3);
        const rot = Quaternion.FromAngleAxis(new Vector3(4, 5, 6), Angle.FromDegrees(35));
        sceneRoot.rotation = rot;
        sceneRoot.scale = 5;
        const state = serializer.getSystemState();
        expect(state.position).toEqual(sceneRoot.position.dto);
        expect(state.scale).toEqual(5);
        expect(state.rotation).toEqual(sceneRoot.rotation.dto);
    });
    it("Applies V1 state", () => {
        const { sceneRoot, serializer, stateMachine } = makeTestRig();
        const desiredPos = new Vector3(1, 2, 3);
        const desiredRot = Quaternion.FromAngleAxis(new Vector3(4, 5, 6), Angle.FromDegrees(35));
        const desiredScale = new Vector3(5, 5, 5);
        const state = {
            position: desiredPos.array,
            rotation: desiredRot.toArray(),
            scale: desiredScale.array,
        };
        const lerpMock = jest.fn();
        sceneRoot.transform.lerp = lerpMock;
        serializer.applySystemState(state, 1, 1);
        const expectedDTO = {
            durationMS: 1000,
            ease: stateMachine.transitionEaseFunction,
            desiredPosition: desiredPos,
            desiredRotation: desiredRot,
            desiredScale,
        };
        expect(lerpMock).toHaveBeenCalledWith(expectedDTO);
    });
    it("Applies V2 state", () => {
        const { sceneRoot, serializer, stateMachine } = makeTestRig();
        const desiredPos = new Vector3(1, 2, 3);
        const desiredRot = Quaternion.FromAngleAxis(new Vector3(4, 5, 6), Angle.FromDegrees(35));
        const desiredScale = 5;
        const state = {
            position: desiredPos.dto,
            rotation: desiredRot.dto,
            scale: desiredScale,
        };
        const lerpMock = jest.fn();
        sceneRoot.transform.lerp = lerpMock;
        serializer.applySystemState(state, 2, 1);
        const expectedDTO = {
            durationMS: 1000,
            ease: stateMachine.transitionEaseFunction,
            desiredPosition: desiredPos,
            desiredRotation: desiredRot,
            desiredScale: new Vector3(5, 5, 5),
        };
        expect(lerpMock).toHaveBeenCalledWith(expectedDTO);
    });
    it("Applies the default state", () => {
        const { sceneRoot, serializer, stateMachine } = makeTestRig();
        sceneRoot.position = new Vector3(1, 2, 3);
        sceneRoot.rotation = Quaternion.FromAngleAxis(new Vector3(4, 5, 6), Angle.FromDegrees(35));
        sceneRoot.scale = 5;
        sceneRoot.lerpToDefault = jest.fn();
        serializer.applyDefaultState(2);
        expect(sceneRoot.lerpToDefault).toHaveBeenCalledWith(2000, stateMachine.transitionEaseFunction);
    });
    it("Warns and applies default if the version is not supported", () => {
        const { sceneRoot, serializer } = makeTestRig();
        sceneRoot.position = new Vector3(1, 2, 3);
        sceneRoot.rotation = Quaternion.FromAngleAxis(new Vector3(4, 5, 6), Angle.FromDegrees(35));
        sceneRoot.scale = 5;
        serializer.applyDefaultState = jest.fn();
        console.warn = jest.fn();
        serializer.applySystemState({ foo: "bar" }, -1, 1);
        expect(console.warn).toHaveBeenCalled();
        expect(serializer.applyDefaultState).toHaveBeenCalled();
    });
    it("Adds itself as a UC to the App Object", () => {
        const { appObj, serializer } = makeTestRig();
        expect(appObj.hasComponent(SerializeSceneRoot.type)).toEqual(true);
        expect(appObj.getComponent(SerializeSceneRoot.type)).toEqual(serializer);
    });
    it("Warns if it is added to a App Object that does not have transform", () => {
        const { appObjects } = makeTestRig();
        const appObj = makeAppObject("anotherObj", appObjects);
        console.warn = jest.fn();
        makeSerializeSceneRoot(appObj);
        expect(console.warn).toHaveBeenCalled();
    });
    it("Does not add itself to an App Object that does not have transform", () => {
        const { appObjects } = makeTestRig();
        const appObj = makeAppObject("anotherObj", appObjects);
        console.warn = jest.fn();
        makeSerializeSceneRoot(appObj);
        expect(appObj.hasComponent(SerializeSceneRoot.type)).toEqual(false);
    });
    it("Serializes the Stored View if it exists", () => {
        const { sceneRoot, storedView, serializer } = makeTestRig();
        storedView.position = new Vector3(4, 5, 6);
        const rot1 = Quaternion.FromAngleAxis(new Vector3(7, 8, 9), Angle.FromDegrees(10));
        storedView.rotation = rot1;
        storedView.scale = 11;
        storedView.hasStoredView = true;
        sceneRoot.position = new Vector3(1, 2, 3);
        const rot2 = Quaternion.FromAngleAxis(new Vector3(4, 5, 6), Angle.FromDegrees(35));
        sceneRoot.rotation = rot2;
        sceneRoot.scale = 5;
        const state = serializer.getSystemState();
        expect(state.position).toEqual(storedView.position.dto);
        expect(state.scale).toEqual(11);
        expect(state.rotation).toEqual(storedView.rotation.dto);
    });
    it("Applies V1 state even when there is no stored view", () => {
        const appObjects = makeAppObjectRepo();
        const appObj = appObjects.getOrCreate("Scene Root");
        const sceneRoot = makeSceneRootEntity(appObj);
        const stateMachine = makeStateMachineEntity(appObj);
        const mockRegister = jest.fn();
        stateMachine.registerSerializedSystem = mockRegister;
        const serializer = makeSerializeSceneRoot(appObj);
        const desiredPos = new Vector3(1, 2, 3);
        const desiredRot = Quaternion.FromAngleAxis(new Vector3(4, 5, 6), Angle.FromDegrees(35));
        const desiredScale = new Vector3(5, 5, 5);
        const state = {
            position: desiredPos.array,
            rotation: desiredRot.toArray(),
            scale: desiredScale.array,
        };
        const lerpMock = jest.fn();
        sceneRoot.transform.lerp = lerpMock;
        serializer.applySystemState(state, 1, 1);
        const expectedDTO = {
            durationMS: 1000,
            ease: stateMachine.transitionEaseFunction,
            desiredPosition: desiredPos,
            desiredRotation: desiredRot,
            desiredScale,
        };
        expect(lerpMock).toHaveBeenCalledWith(expectedDTO);
    });
});
//# sourceMappingURL=SerializeSceneRoot.test.js.map