import { makeAppObjectRepo } from "@vived/core";
import { makeStateMachineEntity, StateMachineEntity, } from "./StateMachineEntity";
function makeTestRig() {
    const appObjects = makeAppObjectRepo();
    const appAO = appObjects.getOrCreate("App");
    const stateMachine = makeStateMachineEntity(appAO);
    const stateAppliedObserver = jest.fn();
    stateMachine.addChangeObserver(stateAppliedObserver);
    const mockSerializedSystem1 = new MockSerializedSystem();
    mockSerializedSystem1.name = "state1";
    stateMachine.registerSerializedSystem(mockSerializedSystem1);
    const mockSerializedSystem2 = new MockSerializedSystem();
    mockSerializedSystem2.name = "state2";
    stateMachine.registerSerializedSystem(mockSerializedSystem2);
    return {
        stateMachine,
        mockSerializedSystem1,
        mockSerializedSystem2,
        stateAppliedObserver,
        appObjects,
    };
}
describe("State Machine Entity", () => {
    it("Gets a serialized state", () => {
        const { stateMachine } = makeTestRig();
        const state = stateMachine.getSerializedStates();
        expect(state.version).toEqual(2);
        expect(state.systems).toHaveLength(2);
        const serializeState = state.systems[0];
        expect(serializeState.name).toEqual("state1");
        expect(serializeState.seriliziationVersion).toEqual(1);
        expect(serializeState.state).toEqual({ foo: "bar" });
    });
    it("Skips a serialized state that returns undefined", () => {
        const { stateMachine, mockSerializedSystem1 } = makeTestRig();
        mockSerializedSystem1.getSystemState = () => {
            return undefined;
        };
        const state = stateMachine.getSerializedStates();
        expect(state.version).toEqual(2);
        expect(state.systems).toHaveLength(1);
    });
    it("Set serialized state", () => {
        const { stateMachine, mockSerializedSystem1 } = makeTestRig();
        const state = makeSerializedState();
        stateMachine.setSerializedStates(state, 3);
        expect(mockSerializedSystem1.applySystemState).toHaveBeenCalledWith({
            foo: "bar1",
        }, 1, 3);
    });
    it("Submits an warning if trying to deserialize data with a bad version number", () => {
        const { stateMachine } = makeTestRig();
        stateMachine.warn = jest.fn();
        const state = {
            version: -1,
            systems: [],
        };
        stateMachine.setSerializedStates(state, 0);
        expect(stateMachine.warn).toHaveBeenCalled();
    });
    it("Sets an empty state", () => {
        const { stateMachine, mockSerializedSystem1 } = makeTestRig();
        stateMachine.setDefaultState(3);
        expect(mockSerializedSystem1.applyDefaultState).toHaveBeenCalledWith(3);
    });
    it("Logs an error if adding two systems with the same name", () => {
        const { stateMachine, mockSerializedSystem1 } = makeTestRig();
        stateMachine.warn = jest.fn();
        stateMachine.registerSerializedSystem(mockSerializedSystem1);
        expect(stateMachine.warn).toHaveBeenCalled();
    });
    it("Sets the default state and warns when passing in junk", () => {
        const { mockSerializedSystem1, stateMachine } = makeTestRig();
        stateMachine.warn = jest.fn();
        stateMachine.applySerializedStatesString("your mom goes to college", 5);
        expect(mockSerializedSystem1.applyDefaultState).toHaveBeenCalledWith(5);
        expect(stateMachine.warn).toHaveBeenCalled();
    });
    it("Set to default if a system is not in the saved state ", () => {
        const { stateMachine } = makeTestRig();
        const state = makeSerializedState();
        const secondSystem = new MockSerializedSystem();
        secondSystem.name = "second system";
        stateMachine.registerSerializedSystem(secondSystem);
        stateMachine.setSerializedStates(state, 3);
        expect(secondSystem.applyDefaultState).toHaveBeenCalledWith(3);
    });
    it("Notifies after a state has been applied", () => {
        const { stateMachine, stateAppliedObserver } = makeTestRig();
        const state = makeSerializedState();
        stateMachine.setSerializedStates(state, 3);
        expect(stateAppliedObserver).toHaveBeenCalled();
    });
    it("Notifies after an empty state has been set", () => {
        const { stateMachine, stateAppliedObserver } = makeTestRig();
        stateMachine.setDefaultState(3);
        expect(stateAppliedObserver).toHaveBeenCalled();
    });
    it("Gets the entity", () => {
        const { stateMachine, appObjects } = makeTestRig();
        expect(StateMachineEntity.get(appObjects)).toEqual(stateMachine);
    });
    it("Set serialized state in the order that they are added", () => {
        const { stateMachine, mockSerializedSystem1, mockSerializedSystem2 } = makeTestRig();
        const state = makeSerializedState();
        stateMachine.setSerializedStates(state, 3);
        const system1Order = mockSerializedSystem1.applySystemState.mock.invocationCallOrder[0];
        const system2Order = mockSerializedSystem2.applySystemState.mock.invocationCallOrder[0];
        expect(system1Order).toBeLessThan(system2Order);
    });
    it("Sets the default before setting states", () => {
        const { stateMachine, mockSerializedSystem1, mockSerializedSystem2 } = makeTestRig();
        const state = makeSerializedState();
        state.systems = [state.systems[0]]; // Removed state 2 data
        stateMachine.setSerializedStates(state, 3);
        const setSystemOrder = mockSerializedSystem1.applySystemState.mock.invocationCallOrder[0];
        const setDefaultOrder = mockSerializedSystem2.applyDefaultState.mock.invocationCallOrder[0];
        expect(setDefaultOrder).toBeLessThan(setSystemOrder);
    });
    it("Restores the last state", () => {
        const { stateMachine } = makeTestRig();
        const state = makeSerializedState();
        stateMachine.setSerializedStates(state, 3);
        stateMachine.setSerializedStates = jest.fn();
        stateMachine.restoreLastState();
        expect(stateMachine.setSerializedStates).toHaveBeenCalledWith(state, stateMachine.restoreDurationS);
    });
    it("Sets it to default if restore is called before a state is set", () => {
        const { stateMachine } = makeTestRig();
        stateMachine.setDefaultState = jest.fn();
        stateMachine.restoreLastState();
        expect(stateMachine.setDefaultState).toHaveBeenCalled();
    });
    it("Sets it to default if restore is called after a state is set and the default is set", () => {
        const { stateMachine } = makeTestRig();
        const state = makeSerializedState();
        stateMachine.setSerializedStates(state, 3);
        stateMachine.setDefaultState(5);
        stateMachine.setDefaultState = jest.fn();
        stateMachine.restoreLastState();
        expect(stateMachine.setDefaultState).toHaveBeenCalled();
    });
});
function makeSerializedState() {
    return {
        version: 2,
        systems: [
            {
                name: "state1",
                seriliziationVersion: 1,
                state: {
                    foo: "bar1",
                },
            },
            {
                name: "state2",
                seriliziationVersion: 1,
                state: {
                    foo: "bar2",
                },
            },
        ],
    };
}
class MockSerializedSystem {
    constructor() {
        this.seriliziationVersion = 1;
        this.name = "mockSystem";
        this.getSystemState = () => {
            return {
                foo: "bar",
            };
        };
        this.applyDefaultState = jest.fn();
        this.applySystemState = jest.fn();
    }
}
//# sourceMappingURL=StateMachineEntity.test.js.map