"use strict";

import Luci from "../luci.js";
import ApiMqttIn from "./api-mqtt-in.js";
import ApiMqttOut from "./api-mqtt-out.js";

class Api {

    static isConnected = false;

    static baseURL = "/api/";
    // /api/luci/
    static callbackGetLuci = null;
    /**
     * gets the luci of the user from the server
     * @returns {*} all the lights of the user
     */
    static getLuci = callback => {
        Api.callbackGetLuci = callback;
        ApiMqttOut.getStatusLuci();
    };
    static sendLuciWeb = luci => {
        if( Api.callbackGetLuci == null)
            return;
        const callback = Api.callbackGetLuci;
        Api.callbackGetLuci = null;
        callback(luci);
    }
    /**
     * adds a new luce to the server
     * @param {luceTemplate} luce the luce to add to the server
     * @returns {*} null if the light was added
     */
    static makeNewLuci = async luce => {
        if (luce == null)
            throw new Error("luce must be defined");
        const url = Api.baseURL + "luci/";
        const response = await fetch(url, {
            method: "POST",
            headers: {
                "Content-Type": "application/json"
            },
            body: JSON.stringify(luce)
        });
        if (response.ok)
            return null;
        else
            throw await response.json();
    };
    static callbackLuciStato = null;
    static toggleForLuciStato = null;
    static fixedCallbackLuciStato = null;
    // /api/luci/stato/
    /**
     * changes the status of a luce on the server
     * @param {luceTemplate} luce the luce to change the status of
     * @returns {*} null if the light's status was changed
     */
    static setLuciStato = (luce,toggle,callback,fixedCallback) => {
        if(Api.fixedCallbackLuciStato == null)
            Api.fixedCallbackLuciStato = fixedCallback;
        Api.callbackLuciStato = callback;
        Api.toggleForLuciStato = toggle;
        ApiMqttOut.setLuciStato(luce);
    }
    static sendLuciStatoWeb = response => {
        if(response == null){
            const callback = Api.callbackLuciStato;
            const toggle = Api.toggleForLuciStato;
            Api.callbackLuciStato = null;
            Api.toggleForLuciStato = null;
            callback(toggle);
        } else {
            Api.fixedCallbackLuciStato(response);
        }
    }
    // /api/scenari/
    static callbackGetScenari = null;
    /**
     * gets the scenari of the user from the server
     * @returns {*} all the scenarios of the user
     */
    static getScenari = callback => {
        Api.callbackGetScenari = callback;
        ApiMqttOut.getAllFromScenari();
    };
    static sendScenariWeb = scenari => {
        if( Api.callbackGetScenari == null)
            return;
        const callback = Api.callbackGetScenari;
        Api.callbackGetScenari = null;
        callback(scenari);
    }
    // /api/scenari/attiva/
    static callbackSetScenarioStatus = null;
    static scenarioSetScenarioStatus = null;
    static activatingSetScenarioStatus = null;
    static isActivatingNewScenarioSetScenarioStatus = null;

    /**
     * activates or deactivates a scenario on the server
     * @param {scenarioTemplate} scenario the scenario to activate or deactivate
     * @returns {*} null if the scenario was activated or deactivated
     */
    static setScenarioStatus = (scenario,activating,isActivatingNewScenario,callback) => {
        Api.callbackSetScenarioStatus = callback;
        Api.scenarioSetScenarioStatus = scenario;
        Api.activatingSetScenarioStatus = activating;
        Api.isActivatingNewScenarioSetScenarioStatus = isActivatingNewScenario;
        ApiMqttOut.setScenarioStatus(scenario);
    };
    static sendWebNewScenarioStatus = scenarioNome => {
        if( Api.callbackSetScenarioStatus == null)
            return;
        const callback = Api.callbackSetScenarioStatus;
        const scenario = Api.scenarioSetScenarioStatus;
        const activating = Api.activatingSetScenarioStatus;
        const isActivatingNewScenario = Api.isActivatingNewScenarioSetScenarioStatus;
        Api.callbackSetScenarioStatus = null;
        Api.scenarioSetScenarioStatus = null;
        Api.activatingSetScenarioStatus = null;
        Api.isActivatingNewScenarioSetScenarioStatus = null;
        // FIXME forse dovrei controllare scenarioNome
        callback(scenario,activating,isActivatingNewScenario);
    }
    // /api/scenari/registra/
    static recordingRecordScenario = null;
    static endRecordingModalLauncherRecordScenario = null;
    static registraBtnRecordScenario = null;
    static learnINBtnRecordScenario = null;
    static callbackRecordScenario = null;
    /**
     * starts/stop the recording of a scenario
     * @param {Boolean} recording true to start the recording, false to stop it
     * @returns {*} null if the recording was started or stopped
     */
    static recordScenario = (recording,endRecordingModalLauncher,registraBtn,learnINBtn,callback) => {
        Api.recordingRecordScenario = recording;//true se voglio registrare
        Api.endRecordingModalLauncherRecordScenario = endRecordingModalLauncher;
        Api.callbackRecordScenario = callback;
        Api.learnINBtnRecordScenario = learnINBtn;
        Api.registraBtnRecordScenario = registraBtn;
        ApiMqttOut.recordScenario(learnINBtn);
    }
    static retriesRecordScenario = 0;
    static sendWebScenarioAutoma = stato => {
        if( Api.callbackRecordScenario == null)
            return;
        const recording = Api.recordingRecordScenario;
        const statoAspettato = recording ? 1 : 0;
        if(stato !== statoAspettato && Api.retriesRecordScenario < 3){
            Api.retriesRecordScenario++;
            ApiMqttOut.recordScenario(Api.learnINBtnRecordScenario);
        }
        const endRecordingModalLauncher = Api.endRecordingModalLauncherRecordScenario;
        const callback = Api.callbackRecordScenario;
        const registraBtn = Api.registraBtnRecordScenario;
        Api.recordingRecordScenario = null;
        Api.endRecordingModalLauncherRecordScenario = null;
        Api.callbackRecordScenario = null;
        Api.learnINBtnRecordScenario = null;
        Api.registraBtnRecordScenario = null;
        Api.retriesRecordScenario = 0;
        callback(recording,endRecordingModalLauncher,registraBtn);
    }
    // /api/scenari/salva/
    static callbackSaveScenario = null;
    /**
     * tells the server to save the currently recorded scenario
     * @returns {*} the scenario if it was saved
     */
    static saveScenario = (nome,callback) => {
        Api.callbackSaveScenario = callback;
        ApiMqttOut.saveScenario(nome);
    };

    static sendWebSavedScenario = scenario => {
        if( Api.callbackSaveScenario == null)
            return;
        const callback = Api.callbackSaveScenario;
        Api.callbackSaveScenario = null;
        callback(scenario);
    }
    // /api/antifurto/
    /**
     * gets everything about the antifurto (stato, allarme, attenzione (valore progress bar), soglia, sensori)
     * @returns {*} the antifurto's values
     */
    static getAntifurto = async () => {
        
        // const url = Api.baseURL + "antifurto/";
        // const response = await fetch(url);
        // const data = await response.json();
        // if (response.ok)
        //     return data;
        // else
        //     throw data;
    };
    // /api/antifurto/stato/
    /**
     * gets the status of the antifurto
     * @returns {*} the antifurto's status
     */
    /*static getAntifurtoStatus = async () => {
        const url = Api.baseURL + "antifurto/stato/";
        const response = await fetch(url);
        const data = await response.json();
        if (response.ok)
            return data;
        else
            throw data;
    };*/
    static newStatusSetAntifurtoStatus = null;
    static antifurtoINbtnSetAntifurtoStatus = null;
    static payloadSetAntifurtoStatus = null;
    static callbackSetAntifurtoStatus = null;
    /**
     * sets the status of the antifurto
     * @param {Boolean} status the new status of the antifurto
     * @returns {*} null if the status was changed
     */
    static setAntifurtoStatus = (newStatus,antifurtoINbtn,payload,callback) => {
        Api.newStatusSetAntifurtoStatus = newStatus;
        Api.antifurtoINbtnSetAntifurtoStatus = antifurtoINbtn;
        Api.payloadSetAntifurtoStatus = payload;
        Api.callbackSetAntifurtoStatus = callback;
        ApiMqttOut.setAntifurtoStatus(antifurtoINbtn);
    };
    static retriesSetAntifurtoStatus = 0;
    static sendWebAntifurtoAutoma = stato => {
        if( Api.callbackSetAntifurtoStatus == null)
            return;
        const newStatus = Api.newStatusSetAntifurtoStatus;
        const expectedStatus = newStatus ? 2 : 0;
        if(stato !== expectedStatus && Api.retriesSetAntifurtoStatus < 3){
            Api.retriesSetAntifurtoStatus++;
            ApiMqttOut.setAntifurtoStatus(Api.antifurtoINbtnSetAntifurtoStatus);
        }
        const payload = Api.payloadSetAntifurtoStatus;
        const callback = Api.callbackSetAntifurtoStatus;
        Api.newStatusSetAntifurtoStatus = null;
        Api.antifurtoINbtnSetAntifurtoStatus = null;
        Api.payloadSetAntifurtoStatus = null;
        Api.callbackSetAntifurtoStatus = null;
        Api.retriesSetAntifurtoStatus = 0;
        callback(payload.previousStatus,newStatus,payload.fromScenari,payload.fromServer,payload.fromBellClick);
    }
    // /api/antifurto/allarme/
    /**
     * gets the status of the antifurto's alarm
     * @returns {*} the antifurto's alarm status
     */
    /*static getAntifurtoAllarme = async () => {
        const url = Api.baseURL + "antifurto/allarme/";
        const response = await fetch(url);
        const data = await response.json();
        if (response.ok)
            return data;
        else
            throw data;
    };*/
    /**
     * sets the status of the antifurto's alarm
     * @param {Boolean} allarme the new status of the antifurto's alarm
     * @returns {*} null if the status was changed
     */
    static setAntifurtoAllarme = async allarme => {
        if (allarme == null || typeof allarme.stato !== 'boolean')
            throw new Error("allarme must be a set boolean");
        const url = Api.baseURL + "antifurto/allarme/";
        const response = await fetch(url, {
            method: "PUT",
            headers: {
                "Content-Type": "application/json"
            },
            body: JSON.stringify(allarme)
        });
        if (response.ok)
            return null;
        else
            throw await response.json();
    };
    // /api/antifurto/attenzione/
    /**
     * sets the status for the progress bar of the antifurto's alarm
     * @param {Number} attenzione the new value of the antifurto's attention
     * @returns {*} null if the value was changed 
     */
    static setAntifurtoAttenzione = async attenzione => {
        if (attenzione == null || isNaN(parseInt(attenzione)))
            throw new Error("attenzione must be a set integer");
        const val = parseInt(attenzione);
        if (val < 0 || val > 100)
            throw new Error("attenzione must be between 0 and 100");
        const url = Api.baseURL + "antifurto/attenzione/";
        const response = await fetch(url, {
            method: "PUT",
            headers: {
                "Content-Type": "application/json"
            },
            body: JSON.stringify({attenzione:val})
        });
        if (response.ok)
            return null;
        else
            throw await response.json();
    };
    // /api/antifurto/soglia/
    /**
     * sets the value of the antifurto's threshold
     * @param {Number} soglia the user's value of the antifurto's threshold
     * @returns {*} null if the value was changed
     */
    static setAntifurtoSoglia = async soglia => {
        if (soglia == null || isNaN(parseInt(soglia)))
            throw new Error("soglia must be a set integer");
        const val = parseInt(soglia);
        if (val < 0 || val > 100)
            throw new Error("soglia must be between 0 and 100");
        const url = Api.baseURL + "antifurto/soglia/";
        const response = await fetch(url, {
            method: "PUT",
            headers: {
                "Content-Type": "application/json"
            },
            body: JSON.stringify({soglia:val})
        });
        if (response.ok)
            return null;
        else
            throw await response.json();
    };
}

export default Api;