import { Assets, Container } from 'pixi.js';
import { Spine } from 'pixi-spine';
import { Entity, Updatable } from '../types/Entity';
import { SymbolConfig } from '../types/SlotMachineConfig';
import { getUniqueId } from '../utils/getUniqueId';

/**
 * @class Symbol
 * @extends Container
 * @description Represents a symbol in the slot machine with various animations and states.
 */
export default class Symbol extends Container implements Entity, Updatable
{
    protected config: SymbolConfig;
    private _id?: string;
    protected spine: Spine;

    /** Returns a unique identifier for the symbol instance. */
    override get name(): string
    {
        if (!this._id)
        {
            this._id = getUniqueId();
        }

        return this._id;
    }

    /** Gets or sets the animation time scale for the symbol's spine animation. */
    get timeScale(): number
    {
        return this.spine.state.timeScale;
    }

    set timeScale(timeScale: number)
    {
        this.spine.state.timeScale = timeScale;
    }

    /** Returns the key associated with the symbol configuration. */
    get key(): string
    {
        return this.config.key;
    }

    /**
     * Initializes a symbol with the provided configuration.
     * @class
     * @param config - Configuration settings for the symbol, including spine asset and skin.
     */
    constructor(config: SymbolConfig)
    {
        super();
        this.config = config;
        this._create();
    }

    /**
     * Creates and initializes the spine animation for the symbol based on its configuration.
     * @private
     */
    private _create(): void
    {
        this.spine = new Spine(Assets.get(this.config.spine).spineData);
        this.spine.autoUpdate = false;
        this.spine.skeleton.setSkinByName(this.config.skin);
        this.spine.stateData.defaultMix = 0.5;
        this.addChild(this.spine);
    }

    /**
     * Updates the spine animation based on delta time.
     * @param dt - Delta time in milliseconds since the last update.
     */
    update(dt: number): void
    {
        this.spine.update(dt * 0.001);
    }

    public tint(hexColor: number): void
    {
        this.spine.tint = hexColor;
    }

    public reset()
    {
        this.spine.state.setEmptyAnimation(0, 0.1);
    }
}
