interface StoredVariableOptions<T> {
    id : string;
    value : T;
}

/**
 * StoredVariables are the only thing that gets stored on a Save/Reload.
 * It's only allowed to have StoredVariables that are either primitive or simple objects.
 */
class StoredVariable<T> {
    public id : string;
    public value : T;
    public defValue : T;

    public constructor (options : StoredVariableOptions<T>) {
        this.id = options.id;
        this.value = options.value;
        this.defValue = this.value;

        StoredVariable.registerVariable(this);
    }

    public reset () {
        this.value = this.defValue;
    }

    public updateFromObject (obj : T) {
        this.value = obj;
    }

    public exportAsObject () {
        return this.value;
    }

    private static storedVariables : {[id : string] : StoredVariable<any>} = {};

    public static registerVariable (variable : StoredVariable<any>) {
        if (StoredVariable.storedVariables[variable.id] == undefined) {
            StoredVariable.storedVariables[variable.id] = variable;
        } else {
            console.warn("[StoredVariable] " + variable.id + " already defined. Ignoring:", variable);
        }
    }

    public static getVariable (id : string) {
        return StoredVariable.storedVariables[id];
    }

    public static getVariables () : Array<StoredVariable<any>>{
        let list = [];
        for (let key in StoredVariable.storedVariables) {
            list.push(StoredVariable.storedVariables[key]);
        }
        return list;
    }

    public static exportAsObject () : {[id : string] : any} {
        let list = {};
        for (let key in StoredVariable.storedVariables) {
            list[key] = StoredVariable.storedVariables[key].value;
        }
        return list;
    }

    public static updateFromObject (obj : {[id : string] : any}) {
        for (let key in StoredVariable.storedVariables) {
            if (obj[key] != undefined) {
                StoredVariable.storedVariables[key].updateFromObject(obj[key]);
            } else {
                StoredVariable.storedVariables[key].reset();
            }
        }
    }
}