/**
 * multiple instance manager
 */
import { MultipleInstanceInterface } from "./multipleInstanceInterface";

export default class MultipleInstanceManager<T extends MultipleInstanceInterface> {
    private instances: {[key: string]: T} = {};
    private instanceType: new (token: string) => T;
    
    constructor(type: new (token: string) => T){
        this.instanceType = type;
    }

    newInstance(token: string = ""): T{
        let instance = new this.instanceType(token);

        if(token != null && token != "")
            this.set(instance, token);

        return instance;
    }
    get(token: string = "global"): T | null{
        let instance = this.instances != null ? this.instances[token] : null;
        if(token == "global" && instance == null){
            instance = this.newInstance("global");
        }
        return instance;
    }
    getValues(): T[]{
        let tokens: string[] = this.getTokensList();
        let values: T[] = [];
        tokens.forEach(token => {
            let val = this.get(token);
            if(val != null){
                values.push(val);
            }
        });
        return values;
    }

    getTokensList(): string[] {
        return Object.keys(this.instances);
    }
    set(instance: T, token: string): void{
        this.delete(token);
        this.instances[token] = instance;
    }
    delete(token: string = "global"){
        let instance = this.instances != null ? this.instances[token] : null;
        if(instance != null){
            if(typeof instance.destroy === "function"){
                instance.destroy();                
            }
            delete this.instances[token];            
        }
    }
    getStatus(): {[key: string]: string} | string{
        let body: {[key: string]: string} | string = {};

        if(this.instances != null){
            for (var key in this.instances) {
                let instance = this.instances[key];
                if(typeof instance.getStatus === "function"){
                    body[key] = instance.getStatus();                
                }
            }
        }

        if(Object.keys(body).length === 0){
            body = "inactive";
        }

        return body;
    }
    isFunctional(): boolean{
        let isFunctional = true;

        if(this.instances != null){
            for (var key in this.instances) {
                let instance = this.instances[key];
                if(typeof instance.isFunctional === "function"){
                    if(isFunctional && !instance.isFunctional()){
                        isFunctional = false;
                    }                
                }
            }
        }

        return isFunctional;
    }

    reset(){
        if(this.instances != null){
            for (var key in this.instances) {
                let instance = this.instances[key];
                if(typeof instance.destroy === "function"){
                    instance.destroy();               
                }
            }
        }
        this.instances = {};
    }
}    