const ARIMELODY_CONFIG_NAME = "arimelody-web-config";

class Config {
    _crt = false;
    _cursor = false;
    _cursorFunMode = false;

    /** @type Map<string, Array<Function>> */
    #listeners = new Map();

    constructor(values) {
        function thisOrElse(values, name, defaultValue) {
            if (values === null) return defaultValue;
            if (values[name] === undefined) return defaultValue;
            return values[name];
        }

        this.#listeners.set('crt', new Array());
        this.crt = thisOrElse(values, 'crt', false);
        this.#listeners.set('cursor', new Array());
        this.cursor = thisOrElse(values, 'cursor', false);
        this.#listeners.set('cursorFunMode', new Array());
        this.cursorFunMode = thisOrElse(values, 'cursorFunMode', false);
        this.save();
    }

    /**
     * Appends a listener function to be called when the config value of `name`
     * is changed.
     */
    addListener(name, callback) {
        const callbacks = this.#listeners.get(name);
        if (!callbacks) return;
        callbacks.push(callback);
    }

    /**
     * Removes the listener function `callback` from the list of callbacks when
     * the config value of `name` is changed.
     */
    removeListener(name, callback) {
        const callbacks = this.#listeners.get(name);
        if (!callbacks) return;
        callbacks.set(name, callbacks.filter(c => c !== callback));
    }

    save() {
        localStorage.setItem(ARIMELODY_CONFIG_NAME, JSON.stringify({
            crt: this.crt,
            cursor: this.cursor,
            cursorFunMode: this.cursorFunMode
        }));
    }

    get crt() { return this._crt }
    set crt(/** @type boolean */ enabled) {
        this._crt = enabled;
        this.save();

        if (enabled) {
            document.body.classList.add("crt");
        } else {
            document.body.classList.remove("crt");
        }
        document.getElementById('toggle-crt').className = enabled ? "" : "disabled";

        this.#listeners.get('crt').forEach(callback => {
            callback(this._crt);
        })
    }

    get cursor() { return this._cursor }
    set cursor(/** @type boolean */ value) {
        this._cursor = value;
        this.save();
        this.#listeners.get('cursor').forEach(callback => {
            callback(this._cursor);
        })
    }

    get cursorFunMode() { return this._cursorFunMode }
    set cursorFunMode(/** @type boolean */ value) {
        this._cursorFunMode = value;
        this.save();
        this.#listeners.get('cursorFunMode').forEach(callback => {
            callback(this._cursorFunMode);
        })
    }
}

const config = (() => {
    let values = null;

    const saved = localStorage.getItem(ARIMELODY_CONFIG_NAME);
    if (saved)
        values = JSON.parse(saved);

    return new Config(values);
})();

document.getElementById("toggle-crt").addEventListener("click", () => {
    config.crt = !config.crt;
});

window.config = config;
export default config;
