enum RunnerStates {
    Running,
    Waiting
}

type Command = {
    module: string,
    functionName: string,
    args: Array<any>
}

export default class DeferredRunner {
    private state = RunnerStates.Waiting
    private commands:Array<Command> = []
    private library;

    private executeQueued() {
        this.commands.forEach( ({module, functionName, args}) => {
            if (!this.library[module] || !this.library[module][functionName]) {
                console.warn(`Module [${module}] or function [${functionName}] not loaded`)
                return
            }

            this.securedExecute(module, functionName, args)
        })

        this.commands = []
    }

    private securedExecute(module, functionName, args) {
        try {
            this.library[module][functionName](...args)   
        } catch (e) {
            console.log(`error executing ${module}:${functionName}`)
            console.log(e)
        }
    }

    public activate(lib): void {
        this.library = lib
        this.state = RunnerStates.Running

        this.executeQueued()
    }

    public execute(module, functionName, args): void {
        if (this.state === RunnerStates.Waiting) {

            this.commands.push({
                module,
                functionName,
                args
            })
            return;
        }

        this.securedExecute(module, functionName, args)
    }

}