/**
 * Filename: ClockControls.ts
 * Author: Stevan Bosanac
 * Created Date: 2024-09-17
 *
 * Description:
 * The ClockControls class in TypeScript creates a user interface for controlling the timescale
 * and pause functionality of a clock.
 *
 * Revision History:
 * 2024-09-17: Initial creation
 *
 */

import Locator from '../../../services/Locator';
import { PaneExtended } from '../interfaces/PaneExtended';

/*
 * The ClockControls class in TypeScript creates a user interface for controlling the timescale
 * and pause functionality of a clock.
 */
export class ClockControls
{
    static controlName = 'ClockControls';
    pane: PaneExtended;

    /**
     * The constructor function initializes a PaneExtended object and a locator in TypeScript.
     * @param {PaneExtended} pane - The `pane` parameter is an instance of the `PaneExtended` class.
     * @param {any} locator - The `locator` parameter is typically used to identify and locate elements on
     * a web page. It can be a CSS selector, XPath expression, or any other method used by automation tools
     * to find elements on a webpage.
     */
    constructor(pane: PaneExtended)
    {
        this.pane = pane;
    }

    /** The `initialize` function in TypeScript adds clock controls. */
    initialize()
    {
        const mainFolder: PaneExtended = this.pane.addFolder({ title: 'Game Speed', expanded: false }) as any;

        this.addClockControls(mainFolder);
        // @ts-expect-error method
        if (Locator.clock.animSpeedConfig)
        {
            const animSpeedFolder: any = mainFolder.addFolder({ title: 'Animation Speed', expanded: false });

            const tab = animSpeedFolder.addTab({
                // @ts-expect-error method
                pages: [...Object.keys(Locator.clock.animSpeedConfig).map((key) => ({ title: key }))],
            });

            tab.pages.forEach((page: any) => this.addAnimSpeedControls(page, page.title === 'normal' ? 4 : 6));
            this.exportConfig(animSpeedFolder);
        }
    }

    /**
     * The `addClockControls` function sets up UI controls for adjusting the timescale and
     * pausing/resuming a clock in a TypeScript application.
     * @param mainFolder
     */
    addClockControls(mainFolder: PaneExtended)
    {
        const folder = mainFolder.addFolder({ title: 'Timescale', expanded: false }) as any;
        const clockSlider = folder.addBlade({
            view: 'slider',
            label: 'Clock:',
            min: 0,
            max: 5,
            value: Locator.clock.timeScale,
        });

        clockSlider.on('change', (e: { value: any; }) =>
        {
            Locator.clock.setTimeScale(e.value);
            (document.activeElement as HTMLElement).blur();
        });
        const clockSliderUpdater = folder.addBinding(Locator.clock, 'timeScale', { readonly: true, hidden: true });

        clockSliderUpdater.on('change', () => clockSlider.value = Locator.clock.timeScale);

        const pause = folder.addBinding(Locator.clock, 'paused', { label: 'Pause:' });

        pause.on('change', (e: { value: any; }) =>
        {
            if (e.value)
            {
                Locator.clock.pause();
            }
            else
            {
                Locator.clock.resume();
            }
        });
        // @ts-expect-error method
        Locator.clock.addListener('paused', () =>
        {
            pause.controller.value.rawValue = true;
        }, this);
        // @ts-expect-error method
        Locator.clock.addListener('resumed', () =>
        {
            pause.controller.value.rawValue = false;
        }, this);
    }

    addAnimSpeedControls(page: any, max: any)
    {
        // @ts-expect-error method
        Object.keys(Locator.clock.animSpeedConfig[page.title]).forEach((key) =>
        {
            // @ts-expect-error method
            const speedConfig = page.addBinding(Locator.clock.animSpeedConfig[page.title], key, { min: 0, max });

            speedConfig.on('change', () =>
            {
                // @ts-expect-error method
                if (Locator.clock.setAnimSpeed)
                {
                    // @ts-expect-error method
                    Locator.clock.setAnimSpeed();
                }
            });
        });
    }

    exportConfig(mainFolder: PaneExtended)
    {
        const button = (mainFolder as any).addButton({ title: 'Export speedModes.json' });

        button.on('click', () =>
        {
            // @ts-expect-error method
            const blob = new Blob([JSON.stringify(Locator.clock.animSpeedConfig, null, 2)], {
                type: 'application/json',
            });
            const url = URL.createObjectURL(blob);
            const a = document.createElement('a');

            a.href = url;
            a.download = 'speedModes.json';
            a.click();
            URL.revokeObjectURL(url);
        });
    }
}
