import BaseMachine from '../slotMachines/BaseMachine';
import { ScreenMapRecord } from '../types/ScreenInputMap';
import BaseSystem from './BaseSystem';

export type InitMap = ScreenMapRecord[];

/**
 * @class InitSystem
 * @extends BaseSystem
 * @description A system responsible for initializing symbols in the slot machine. It only runs once, adding
 * symbols based on `initMap` data to the main scene and marking initialization as complete.
 */
export default class InitSystem extends BaseSystem
{
    /**
     * List of flags required by InitSystem.
     * @type {string[]}
     */
    static override requiredFlags: string[] = ['init'];

    /**
     * List of maps required by InitSystem.
     * @type {string[]}
     */
    static override requiredMaps: string[] = ['symbols'];

    /**
     * List of inputs required by InitSystem.
     * @type {string[]}
     */
    static override requiredInputs: string[] = ['initMap'];

    /**
     * List of methods required by InitSystem.
     * @type {string[]}
     */
    static override requiredMethods: string[] = ['createSymbol', 'addChild'];

    /**
     * @class
     * @param {BaseMachine} machine - The slot machine instance that requires initialization.
     */
    constructor(machine: BaseMachine)
    {
        super(machine);
    }

    /**
     * @override
     * @method onEnter
     * @description Called when `InitSystem` is activated. Currently unused but defined for consistency with BaseSystem.
     */
    onEnter(): void
    {
    // Can be used to prepare or reset the system if needed
    }

    /**
     * @override
     * @method update
     * @description Initializes symbols if they haven't been initialized already.
     * - Creates an array in `machine.maps.symbols` to store references.
     * - Iterates over `machine.inputs.initMap` to create and add each symbol.
     * - Sets `machine.flags.init` to true after initialization.
     */
    update(): void
    {
        const initMap = this.machine.inputs.initMap as InitMap;

        if (!initMap) return; // Exit if no data
        if (this.machine.flags.init) return; // Exit if already initialized

        this.machine.maps.symbols = [];

        initMap.forEach((record: ScreenMapRecord) =>
        {
            if (!record.key)
            {
                console.warn('InitSystem: Missing \'key\' property in record', record);

                return;
            }

            const symbol = this.machine.createSymbol(record.key);

            if (symbol)
            {
                symbol.value = record.value;
                this.machine.addChild(symbol);
                this.machine.maps.symbols.push(symbol.name);
            }
            else
            {
                console.warn(`InitSystem: Failed to create symbol for key: ${record.key}`);
            }
        });

        this.machine.flags.init = true;
    }

    /**
     * @override
     * @method onLeave
     * @description Called when `InitSystem` is deactivated. Currently unused but defined for consistency with BaseSystem.
     */
    onLeave(): void
    {
    // Can be used to clean up or reset the system if needed
    }
}
