import { makeAppObjectRepo } from "@vived/core";
import { Angle, Quaternion, Vector3 } from "@vived/core";
import { makeSceneRootEntity, SceneRootEntity, } from "./SceneRootEntity";
function makeTestRig() {
    const appObjects = makeAppObjectRepo();
    const rootAO = appObjects.getOrCreate("Scene Root");
    const sceneRoot = makeSceneRootEntity(rootAO);
    const observer = jest.fn();
    sceneRoot.addChangeObserver(observer);
    return { sceneRoot, observer, appObjects };
}
describe("Scene Root Entity", () => {
    it("Initializes the default position to zero", () => {
        const { sceneRoot } = makeTestRig();
        expect(sceneRoot.defaultPosition).toEqual(Vector3.Zero());
    });
    it("Initializes the default rotation to identity", () => {
        const { sceneRoot } = makeTestRig();
        expect(sceneRoot.defaultRotation).toEqual(Quaternion.Identity());
    });
    it("Initializes the default scale to one", () => {
        const { sceneRoot } = makeTestRig();
        expect(sceneRoot.defaultScale).toEqual(1);
    });
    it("Forwards notifications when the transform changes", () => {
        const { sceneRoot, observer } = makeTestRig();
        sceneRoot.transform.localPosition = new Vector3(1, 2, 3);
        expect(observer).toHaveBeenCalled();
    });
    it("Allows an observer to be removed", () => {
        const { sceneRoot, observer } = makeTestRig();
        sceneRoot.removeChangeObserver(observer);
        sceneRoot.transform.localPosition = new Vector3(1, 2, 3);
        expect(observer).not.toHaveBeenCalled();
    });
    it("Sets the default data", () => {
        const { sceneRoot } = makeTestRig();
        const data = {
            maxScale: 33,
            minScale: 11,
            position: [1, 2, 3],
            rotation: [4, 5, 6, 7],
            scale: 8,
        };
        sceneRoot.applyDefaultData(data);
        expect(sceneRoot.maxScale).toEqual(data.maxScale);
        expect(sceneRoot.minScale).toEqual(data.minScale);
        expect(sceneRoot.defaultPosition).toEqual(Vector3.FromArray(data.position));
        expect(sceneRoot.defaultRotation).toEqual(Quaternion.FromArray(data.rotation));
        expect(sceneRoot.defaultScale).toEqual(8);
    });
    it("Sets the position", () => {
        const { sceneRoot, observer } = makeTestRig();
        observer.mockClear();
        expect(sceneRoot.position).toEqual(Vector3.Zero());
        sceneRoot.position = new Vector3(1, 2, 3);
        expect(observer).toHaveBeenCalled();
        expect(sceneRoot.position).toEqual(new Vector3(1, 2, 3));
        expect(sceneRoot.transform.localPosition).toEqual(new Vector3(1, 2, 3));
    });
    it("Sets the rotation", () => {
        const { sceneRoot, observer } = makeTestRig();
        observer.mockClear();
        expect(sceneRoot.rotation).toEqual(Quaternion.Identity());
        const rotQ = Quaternion.FromAngleAxis(new Vector3(1, 2, 3), Angle.FromDegrees(25));
        sceneRoot.rotation = rotQ;
        expect(observer).toHaveBeenCalled();
        expect(Quaternion.Close(sceneRoot.rotation, rotQ)).toEqual(true);
        expect(Quaternion.Close(sceneRoot.transform.localRotation, rotQ)).toEqual(true);
    });
    it("Sets the scale", () => {
        const { sceneRoot, observer } = makeTestRig();
        observer.mockClear();
        expect(sceneRoot.scale).toEqual(1);
        sceneRoot.scale = 5;
        expect(observer).toHaveBeenCalled();
        expect(sceneRoot.scale).toEqual(5);
        expect(sceneRoot.transform.localScale).toEqual(new Vector3(5, 5, 5));
    });
    it("Centers on a point", () => {
        const { sceneRoot } = makeTestRig();
        const centerOnPoint = new Vector3(10, 20, 30);
        const initialPos = new Vector3(1, 2, 3);
        const initialRotation = Quaternion.FromAngleAxis(new Vector3(4, 5, 6), Angle.FromDegrees(37));
        sceneRoot.position = initialPos;
        sceneRoot.rotation = initialRotation;
        const mockLerp = jest.fn();
        sceneRoot.transform.lerp = mockLerp;
        const expectedFinalPos = Vector3.Subtract(initialPos, centerOnPoint);
        const competedCallback = jest.fn();
        const linealEase = (val) => {
            return val;
        };
        const duration = 500;
        sceneRoot.centerOnPoint(centerOnPoint, duration, linealEase, competedCallback);
        const expectedDTO = {
            durationMS: 500,
            ease: linealEase,
            desiredPosition: expectedFinalPos,
            onCompletedCallback: competedCallback,
        };
        expect(mockLerp).toHaveBeenCalledWith(expectedDTO);
    });
    it("Lerps to the default point", () => {
        const { sceneRoot } = makeTestRig();
        const defaultPosition = new Vector3(1, 2, 3);
        const defaultRotation = Quaternion.FromAngleAxis(new Vector3(4, 5, 6), Angle.FromDegrees(37));
        const defaultScale = new Vector3(8, 8, 8);
        const competedCallback = jest.fn();
        const data = {
            maxScale: 33,
            minScale: 1,
            position: defaultPosition.array,
            rotation: defaultRotation.toArray(),
            scale: defaultScale.x,
        };
        sceneRoot.applyDefaultData(data);
        const mockLerp = jest.fn();
        sceneRoot.transform.lerp = mockLerp;
        const linealEase = (val) => {
            return val;
        };
        const duration = 500;
        sceneRoot.lerpToDefault(duration, linealEase, competedCallback);
        const expectedDTO = {
            durationMS: 500,
            ease: linealEase,
            desiredPosition: defaultPosition,
            desiredRotation: defaultRotation,
            desiredScale: defaultScale,
            onCompletedCallback: competedCallback,
        };
        expect(mockLerp).toHaveBeenCalledWith(expectedDTO);
        expect(mockLerp).toHaveBeenCalledWith(expectedDTO);
    });
    it("Bumps the scale around the origin", () => {
        const { sceneRoot } = makeTestRig();
        expect(sceneRoot.position).toEqual(Vector3.Zero());
        expect(sceneRoot.scale).toEqual(1);
        sceneRoot.bumpScaleAboutPoint(1, Vector3.Zero());
        expect(sceneRoot.position).toEqual(Vector3.Zero());
        expect(sceneRoot.scale).toEqual(2);
    });
    it("Bumps the scale around a pick point", () => {
        const { sceneRoot } = makeTestRig();
        expect(sceneRoot.position).toEqual(Vector3.Zero());
        expect(sceneRoot.scale).toEqual(1);
        sceneRoot.bumpScaleAboutPoint(2, new Vector3(1, 2, 3));
        const expectPos = new Vector3(1 * -2, -2 * 2, 3 * -2);
        expect(sceneRoot.position).toEqual(expectPos);
    });
    it("Clamps the scale bump to the upper limit", () => {
        const { sceneRoot } = makeTestRig();
        const data = {
            maxScale: 33,
            minScale: 0.11,
            position: [1, 2, 3],
            rotation: [4, 5, 6, 7],
            scale: 8,
        };
        sceneRoot.applyDefaultData(data);
        expect(sceneRoot.scale).toEqual(1);
        sceneRoot.bumpScaleAboutPoint(1000, Vector3.Zero());
        expect(sceneRoot.scale).toEqual(33);
    });
    it("Clamps the scale bump to the lower limit", () => {
        const { sceneRoot } = makeTestRig();
        const data = {
            maxScale: 33,
            minScale: 0.11,
            position: [1, 2, 3],
            rotation: [4, 5, 6, 7],
            scale: 8,
        };
        sceneRoot.applyDefaultData(data);
        expect(sceneRoot.scale).toEqual(1);
        sceneRoot.bumpScaleAboutPoint(-1000, Vector3.Zero());
        expect(sceneRoot.scale).toEqual(0.11);
    });
    it("Gets the Entity", () => {
        const { sceneRoot, appObjects } = makeTestRig();
        expect(SceneRootEntity.get(appObjects)).toEqual(sceneRoot);
    });
});
//# sourceMappingURL=SceneRootEntity.test.js.map