"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.StateMachineEntity = void 0;
exports.makeStateMachineEntity = makeStateMachineEntity;
const core_1 = require("@vived/core");
const core_2 = require("@vived/core");
class StateMachineEntity extends core_2.AppObjectEntity {
}
exports.StateMachineEntity = StateMachineEntity;
StateMachineEntity.type = "StateMachineEntity";
StateMachineEntity.get = (appObjects) => (0, core_1.getSingletonComponent)(StateMachineEntity.type, appObjects);
function makeStateMachineEntity(appObject) {
    return new StateMachineImp(appObject);
}
class StateMachineImp extends StateMachineEntity {
    restoreLastState() {
        if (this.lastState) {
            this.setSerializedStates(this.lastState, this.restoreDurationS);
        }
        else {
            this.setDefaultState(this.restoreDurationS);
        }
    }
    constructor(appObject) {
        super(appObject, StateMachineEntity.type);
        this.serializedSystems = new Map();
        this.serilizationVersion = 2;
        this.restoreDurationS = 1;
        this.transitionEaseFunction = (normalizedTime) => {
            return normalizedTime; // default to a linear function
        };
        this.applySerializedStatesString = (state, duration = 0) => {
            if (state === "") {
                this.setDefaultState(duration);
            }
            else {
                try {
                    const stateObj = JSON.parse(state);
                    this.setSerializedStates(stateObj, duration);
                }
                catch (e) {
                    this.setDefaultState(duration);
                    const errorMessage = e instanceof Error ? e.message : 'unknown error';
                    this.warn(`Failed to deserialize state string ${state} with Error ${errorMessage}`);
                }
            }
        };
        this.registerSerializedSystem = (serializedSystem) => {
            if (this.serializedSystems.has(serializedSystem.name)) {
                this.warn(`Duplicate stateable systems encountered: ${serializedSystem.name}`);
                return;
            }
            this.serializedSystems.set(serializedSystem.name, serializedSystem);
            return;
        };
        this.getSerializedStates = () => {
            const systems = Array.from(this.serializedSystems.values());
            const serializedStates = [];
            systems.forEach((system) => {
                const state = system.getSystemState();
                if (!state)
                    return;
                const systemState = {
                    seriliziationVersion: system.seriliziationVersion,
                    name: system.name,
                    state,
                };
                serializedStates.push(systemState);
            });
            return {
                version: this.serilizationVersion,
                systems: serializedStates,
            };
        };
        this.setSerializedStates = (states, duration) => {
            if (states.version === 2) {
                const systemStateLookup = new Map();
                states.systems.forEach((systemState) => {
                    if (this.serializedSystems.has(systemState.name)) {
                        systemStateLookup.set(systemState.name, systemState);
                    }
                    else {
                        this.warn(`Unable to find serializedSystem ${systemState.name}`);
                    }
                });
                // Apply default states first
                this.serializedSystems.forEach((system) => {
                    if (!systemStateLookup.has(system.name)) {
                        system.applyDefaultState(duration);
                    }
                });
                this.serializedSystems.forEach((system) => {
                    const systemState = systemStateLookup.get(system.name);
                    if (systemState) {
                        system.applySystemState(systemState.state, systemState.seriliziationVersion, duration);
                    }
                });
                this.lastState = states;
                this.notifyOnChange();
                return;
            }
            // Here is where we will add support for future versions
            else {
                this.warn(`Unsupported serialized state encountered: ${states.version}`);
                return;
            }
        };
        this.setDefaultState = (duration) => {
            this.serializedSystems.forEach((system) => {
                system.applyDefaultState(duration);
            });
            this.lastState = undefined;
            this.notifyOnChange();
        };
    }
}
//# sourceMappingURL=StateMachineEntity.js.map