//initialize variable for singleton instance
let groupManagerInstance = undefined;

export class groupManager {

    static getInstance() {
        if (!groupManagerInstance) {
            groupManagerInstance = new groupManager();
        }
        return groupManagerInstance;
    }

    constructor() {
        //define zones needed for overload
        this.zones = [
            "10:Zone1",
            "10:Zone2",
            "10:Zone3",
            "10:Zone4",
            "10:Zone5",
            "10:Zone6",
            "10:Zone7",
            "10:Zone8",
            "10:Zone9",
            "10:Zone10",
            "10:Zone11",
            "10:Zone12",
            "10:Zone13",
            "10:Zone14",
            "10:Zone15",
            "10:Zone16",
            "10:Zone17",
            "10:Zone18",
            "10:Zone19",
            "10:Zone20",
            "10:Zone21",
            "10:Zone22",
            "10:Zone23",
            "10:Zone24"
        ];
        //define setpoint managers belonging to zones
        this.setPointManagers = [
            "10:SetPointManager1.GroupID_LVD",
            "10:SetPointManager2.GroupID_LVD",
            "10:SetPointManager3.GroupID_LVD",
            "10:SetPointManager4.GroupID_LVD",
            "10:SetPointManager5.GroupID_LVD",
            "10:SetPointManager6.GroupID_LVD",
            "10:SetPointManager7.GroupID_LVD",
            "10:SetPointManager8.GroupID_LVD",
            "10:SetPointManager9.GroupID_LVD",
            "10:SetPointManager10.GroupID_LVD",
            "10:SetPointManager11.GroupID_LVD",
            "10:SetPointManager12.GroupID_LVD",
            "10:SetPointManager13.GroupID_LVD",
            "10:SetPointManager14.GroupID_LVD",
            "10:SetPointManager15.GroupID_LVD",
            "10:SetPointManager16.GroupID_LVD",
            "10:SetPointManager17.GroupID_LVD",
            "10:SetPointManager18.GroupID_LVD",
            "10:SetPointManager19.GroupID_LVD",
            "10:SetPointManager20.GroupID_LVD",
            "10:SetPointManager21.GroupID_LVD",
            "10:SetPointManager22.GroupID_LVD",
            "10:SetPointManager23.GroupID_LVD",
            "10:SetPointManager24.GroupID_LVD"          
        ];        
        // IMPORTANT: sigApi is not accessible until ready
        window.sigApiReadyPromise.then(() => {
            // IMPORTANT: Commands that communicate with station(s) must wait until all of the required station(s) are available and in Run RAM state!
            // For more information see cm_demo_api_state.js
            window.eventReadyPromises.get(sigApi.SIG_CONST.EVENT_READY_PROMISE_STATIONS_READY).then(() => {
                //check for station and init
                this.init();
            });
        });
    }

    init() {
        this._getGroupedZones().then((groupedZones) => {
            this.groupedZones = groupedZones;
            //go through setpoints and add observer to get informed if group changes
            for (let i=0;i<this.setPointManagers.length;i++) {
                //get datapoint
                const datapoint = sigApi.datapointManager.getDatapoint(this.setPointManagers[i]);
                if (datapoint) {
                    //add observer
                    datapoint.addObserver((value) => {
                        //get old value of server
                        const oldValue = this.groupedZones[i].group;
                        //set new value of server
                        this.groupedZones[i].group = value;
                        //send event to update group content instances
                        dispatchEvent(new CustomEvent('GHT-ZONE-GROUP-CHANGED', {
                            detail: {
                                oldValue: oldValue,
                                newValue: value
                            }
                        }));
                    });
                }
                else {
                    console.log('init(): failed to get datapoint');
                }
            }
        }).catch((error) => console.log('init(): failed to get grouped zones -> ' + error));

    }

    /****************************************************************************************************
     * method is used to get zones configured in this group
     *
     * @memberof LasalRuntimeGroupContentElement
     ****************************************************************************************************/
     async _getGroupedZones() {
        //get group ids of setpoint managers
        try {
            const dpValues = await window.sigApi.datapointManager.readDataPoint(this.setPointManagers);
            if ((dpValues) && (dpValues.length === this.setPointManagers.length)) {
                //initialize grouped zones
                let groupedZones = [];
                //go through values and check if the group id is configured
                for (let i=0;i<dpValues.length;i++) {
                    groupedZones.push({
                        zone: this.zones[i],
                        group: dpValues[i].value
                    });
                }
                //return zones
                return groupedZones;
            }
        }
        catch(error) {
            this._log('_getGroupedZones(): failed to get group ids','ERROR');
        }
    }   
    
    /****************************************************************************************************
     * used to get an array of zones of a specific group
     *
     * @param {*} groupId - id of the group to be read
     * @memberof groupManager
     ****************************************************************************************************/
    getZones(groupId) {
        //check if groupedZones available
        if ((this.groupedZones) && (this.groupedZones.length > 0)) {
            //iterate through zones and filter those with specific group
            let zones = [];
            for (let i=0;i<this.groupedZones.length;i++) {
                if (this.groupedZones[i].group === groupId) {
                    zones.push(this.groupedZones[i].zone);
                }
            }
            return zones;
        }
        else {
            console.log('getZones(): zones not available');
        }
    }
}

// Register the singleton module for global access
window.registerGlobalModule('ght_group_manager', groupManager.getInstance);
//create instance immediatly
window.codemoduleFactory.GlobalModules.requestInstances('ght_group_manager');