
const IDWriterTargetName1 = 'invox-textarea-1';
const IDWriterTargetName2 = 'invox-textarea-2';

var dictionaryComponent = undefined;
var templatesComponent = undefined;
var transformationsComponent = undefined;

window.addEventListener('load', function (event) {
    InitPageInformation(COMPONENTS_PAGE);

    const loginForm = document.querySelector("invox-login-form");
    loginForm.setAttribute("host", CONFIG.remoteDictationServiceHost);
    loginForm.setAttribute("port", CONFIG.remoteDictationServicePort);
    loginForm.setAttribute("use-remote-service", CONFIG.useRemoteDictationService);
    loginForm.setAttribute("username", CONFIG.defaultLogin);
    loginForm.setAttribute("password", CONFIG.defaultPassword);
    loginForm.onClickLogin = Login;
    loginForm.onClickLogout = Logout;

    SetDictationControllersBehaviour();

    EventHandler();

    const containerId = "invox-quick-integrations-container";
    dictionaryComponent = INVOXMDComponent_Dictionary.create(containerId);
    templatesComponent = INVOXMDComponent_Templates.create(containerId);
    transformationsComponent = INVOXMDComponent_Transformations.create(containerId);
});

function Login(credentials, connectionConfig) {

    return new Promise((resolve, reject) => {
        INVOX.CustomizeComponents(CustomizeComponentsBehaviour);
        const loginForm = document.querySelector("invox-login-form");
        if (loginForm) {
            if (loginForm.hasAttribute("host")) {
                loginForm.setAttribute("host", connectionConfig.host);
            }
            if (loginForm.hasAttribute("port")) {
                loginForm.setAttribute("port", connectionConfig.port);
            }
        }
        INVOX.Login(credentials, connectionConfig)
            .catch(e => {
            e && ShowMessage(INVOX.MessageType.ERROR, e);
            ShowLicenseOrAgentInstructions();
            reject(e);
        });
    })
}

function Logout() {
    INVOX.Logout()
    .catch(e => e && ShowMessage(INVOX.MessageType.ERROR, e));
    ReloadValues();
}

function EventHandler() {  
    document.addEventListener(INVOX.eventTypeReport.LOGIN_ERROR, e => {
        ReloadValues();
        ShowMessage(INVOX.MessageType.ERROR, e.detail);
    });
    document.addEventListener(INVOX.eventTypeReport.LOGIN_SUCCESS, e => {
        const editorInstance =  document.getElementById(IDWriterTargetName1)
        ChangeFocusToTextArea(editorInstance);
    });
    document.addEventListener(INVOX.eventTypeReport.NOT_CUSTOMIZED_COMPONENTS, e => {
        ShowMessage(INVOX.MessageType.WARNING, e.detail);
    });
}


//#region Override the public functions of INVOX Medical SDK.
function CustomizeComponentsBehaviour() {

    //#region Audio permissions
    
    /**
     * Override the public function that is executed when audio source is granted 
     * @constructor
     * @param {function} function - Function that overrides the default behaviour
     */
    INVOX.OnGrantedAudioSource(function () {
        let HTMLMicrophoneName = document.getElementById("invox-microphone-name");
        let micName = INVOX.GetMicrophoneName();
        HTMLMicrophoneName.innerText = micName;
        HTMLMicrophoneName.title = `Using microphone: ${micName}`;
    });

    /**
     * Override the public function that is executed when audio source is denied 
     * @constructor
     * @param {function} function - Function that overrides the default behaviour
     */
    INVOX.OnDeniedAudioSource(function () {
        INVOX.SetDictationPaused();
        let HTMLMicrophoneName = document.getElementById("invox-microphone-name");
        HTMLMicrophoneName.innerText = "";
    });

    //#endregion

    //#region Login Progress Bar

    let HTMLProgressBar = document.getElementById("invox-progressbar");
    let description = null;
    /**
     * Override the public function for customizing the progress bar
     * @constructor
     * @param {function} function - Function that overrides the default behaviour
     * @param {object} function.msg - Loading status message {Percent, PercentStep, Description}
     */
    INVOX.OnChangeProgressBar(function (msg) {
        if (msg.Description != undefined) {
            description = ` ${msg.Description}`;
        }
        HTMLProgressBar.innerText = `${+msg.Percent}% ${description}`;
        HTMLProgressBar.style.width = `${+msg.Percent}%`;
    });

    /**
     * Override the public function for customizing the load finished event
     * @constructor
     * @param {function} function - Function that overrides the default behaviour
     */
    INVOX.OnFinishProgressBar(function () {
        HTMLProgressBar.innerText = "100% Successful login!"
    });
    //#endregion

    //#region VUMeter

    let HTMLVUMeter = document.getElementById("invox-progress-vumeter");
    let HTMLVUMeterValue = document.getElementById("invox-vumeter-value");

    /**
     * Override the public function for customizing the vumeter updater
     * @constructor
     * @param {function} function - Function that overrides the default behaviour
     * @param {number} function.activity - Percentage of vumeter activity
     */
    INVOX.OnUpdateVumeterMicActivity(function (activity) {
        HTMLVUMeter.style.width = `${parseInt(activity)}%`;
        HTMLVUMeterValue.innerText = `${parseInt(activity)}%`;
    });
    //#endregion

    //#region Recognizer

    let HTMLButtonDictationPaused = document.getElementById('invox-btn-dictation-off');
    let HTMLButtonDictationRunning = document.getElementById('invox-btn-dictation-on');
    let HTMLButtonDictationSwitch = document.getElementById('invox-btn-switch-dictation');

    /**
     * Override the public function for customizing the recognizer when is started
     * @constructor
     * @param {function} function - Function that overrides the default behaviour
     */
    INVOX.OnStartedRecognizer(function () {
        INVOX.SetDictationPaused();
    });

    /**
     * Override the public function for customizing the recognizer when is paused
     * @constructor
     * @param {function} function - Function that overrides the default behaviour
     */
    INVOX.OnPausedRecognizer(function () {
        HTMLButtonDictationSwitch.innerHTML = "Switch to On";
        HTMLButtonDictationSwitch.classList.remove('invox-off-btn');
        HTMLButtonDictationSwitch.classList.add('invox-on-btn');

        HTMLButtonDictationPaused.classList.add('invox-off-focus-btn');
        HTMLButtonDictationRunning.classList.remove('invox-on-focus-btn');

        ChangeWriterColorFocus(ClassWriterTargetFocusDictationOFF, ClassWriterTargetFocusDictationON);
    });

    /**
     * Override the public function for customizing the recognizer when is running
     * @constructor
     * @param {function} function - Function that overrides the default behaviour
     */
    INVOX.OnRunningRecognizer(function () {
        HTMLButtonDictationSwitch.innerHTML = "Switch to Off";
        HTMLButtonDictationSwitch.classList.remove('invox-on-btn');
        HTMLButtonDictationSwitch.classList.add('invox-off-btn');

        HTMLButtonDictationPaused.classList.remove('invox-off-focus-btn');
        HTMLButtonDictationRunning.classList.add('invox-on-focus-btn');

        ChangeWriterColorFocus(ClassWriterTargetFocusDictationON, ClassWriterTargetFocusDictationOFF);
    });

    /**
     * Override the public function for customizing the recognizer when triggered an error
     * @constructor
     * @param {function} function - Function that overrides the default behaviour
     */
    INVOX.OnErrorRecognizer(function () {
        /* do nothing */
    });
    //#endregion

    //#region Status Bar

    let HTMLStatusBar = document.getElementById("invox-statusbar");
    let statusBarInfoColor = getComputedStyle(document.documentElement).getPropertyValue('--invox-highlight-normal-color');
    let statusBarErrorColor = getComputedStyle(document.documentElement).getPropertyValue('--invox-highlight-error-color');

    /**
     * Override the public function for customizing the status bar
     * @constructor
     * @param {function} function - Function that overrides the default behaviour
     * @param {string} function.msg - Status message
     * @param {object} function.type - Type of message (info, error, warning, success)
     */
    INVOX.OnChangeStatusBar(function (msg, type) {
        HTMLStatusBar.value = `[${type}] ${msg}`;
        HTMLStatusBar.style.backgroundColor = type == INVOX.MessageType.ERROR ? statusBarErrorColor : statusBarInfoColor;
    });
    //#endregion
    
    //#region Visor Hypothesis

    let HTMLVisor = document.getElementById("invox-hyphotesis-viewer");

    /**
     * Override the public functions for customizing the hypothesis viewer
     * @constructor
     * @param {function} function - Function that overrides the default behaviour
     * @param {string} function.msg - Hypothesis message
     * @param {Enumerator} function.dictationEventType - Type of hyphotesis
     */
    INVOX.OnChangeVisorHypothesis(function (msg, dictationEventType) {

        let dictationType = {};
        dictationType[INVOX.dictationEventType.ACCEPTED] = 'ACCEPTED';
        dictationType[INVOX.dictationEventType.REJECTED] = 'REJECTED';
        dictationType[INVOX.dictationEventType.PARTIAL] = 'PARTIAL';
        dictationType[INVOX.dictationEventType.COMMAND] = 'COMMAND';
        dictationType[INVOX.dictationEventType.MACRO] = 'MACRO';

        HTMLVisor.innerText = `[${dictationType[dictationEventType]}] ${msg}`;
    });
    //#endregion

    //#region Adaptation Events

    const HTMLAdaptationHistory = document.querySelector("#invox-adapt-events-history");

    /**
     * Override the public functions to provide feedback about adaptation events 
     * @constructor
     * @param {function} function - Function that overrides the default behaviour
     * @param {string} function.message - Message about rejected adaptation
     */
    INVOX.OnRejectAdaptation(function(message) {
        recordAdaptationEvent("REJECTED", message);
    })

    /**
     * Override the public functions to provide feedback about adaptation events 
     * @constructor
     * @param {function} function - Function that overrides the default behaviour
     * @param {string} function.message - Message about started adaptation
     */    
    INVOX.OnStartAdaptation(function(message) {
        recordAdaptationEvent("STARTED", message);
    })

    /**
     * Override the public functions to provide feedback about adaptation events 
     * @constructor
     * @param {function} function - Function that overrides the default behaviour
     * @param {string} function.message - Message about finish adaptation
     * @param {object} function.adaptationInfo - Information about the adaptation process
     */    
    INVOX.OnFinishAdaptation(function(message, adaptationInfo) {
        const { duration } = adaptationInfo;
        recordAdaptationEvent("FINISHED", `${message}. Duration: ${duration}s`);
    })

    /**
     * Override the public functions to provide feedback about adaptation events 
     * @constructor
     * @param {function} function - Function that overrides the default behaviour
     * @param {string} function.message - Message about started adaptation
     * @param {string} function.error - Error message
     */    
    INVOX.OnErrorAdaptation(function(message, error) {
        recordAdaptationEvent("ERROR", `${message}. ${error}`);
    })

    function recordAdaptationEvent(type, message) {
        const record = `[${new Date().toLocaleString()}] - [${type}]: ${message}.`
        HTMLAdaptationHistory.value = record + HTMLAdaptationHistory.value
    }

    //#endregion

}

(function CustomizeMicrophoneControls() {
    INVOX.DeviceActionManager[INVOX.deviceActionId.DEVICE_ADDED] = function(session) {
        let deviceName = INVOX.GetMicrophoneName();
        if (deviceName) {
            let HTMLMicrophoneName = document.getElementById("invox-microphone-name");
            HTMLMicrophoneName.innerText = deviceName;
            HTMLMicrophoneName.title = `Using microphone: ${deviceName}`;
        }
    }

    INVOX.DeviceActionManager[INVOX.deviceActionId.DEVICE_REMOVED] = function(session) {
        INVOX.SetDictationPaused();
        
        let deviceName = INVOX.GetMicrophoneName();
        if (deviceName) {
            let HTMLMicrophoneName = document.getElementById("invox-microphone-name");
            HTMLMicrophoneName.innerText = deviceName;
            HTMLMicrophoneName.title = `Using microphone: ${deviceName}`;
        }
    }
})();

//#endregion


//#region Auxiliar methods
let ReloadValues = function () {
    (function RestartProgressBar () {
        document.getElementById("invox-progressbar").style.width = "0%";
    })();
    (function RestartVUMeter () {
        document.getElementById("invox-progress-vumeter").style.width = "0%";
    })();
}

let ShowUserInfo = function () {
    try {
        let HTMLModalUserInfo = document.getElementById("invox-modal-user-info");
        if (!HTMLModalUserInfo) {
            throw "Element \'invox-modal-user-info\' not found";
        }
        let userInfo = INVOX.GetUserInfo();
        document.getElementById("invox-modal-user-info-name").value = userInfo.Login || '-';
        document.getElementById("invox-modal-user-info-login").value = userInfo.Name || '-';
        document.getElementById("invox-modal-user-info-specialty").value = userInfo.Specialty || '-';
        document.getElementById("invox-modal-user-info-email").value = userInfo.Email || '-';
        document.getElementById("invox-modal-user-info-org").value = userInfo.Organization || '-';
        document.getElementById("invox-modal-user-info-lastlogin").value = FormatDate(userInfo.LastLogin) || '-';
        document.getElementById("invox-modal-user-info-isfirstlogin").value = userInfo.IsFirstLogin ? 'Yes' : 'No' || '-';

        let modal = new bootstrap.Modal(HTMLModalUserInfo, {});
        modal.show();
    } catch (e) {
        ShowMessage(INVOX.MessageType.ERROR, e);
    }

    function FormatDate (dateString) {
        const options = { year: "numeric", month: "long", day: "numeric", hour: 'numeric', minute: 'numeric', second: 'numeric', timeZoneName: 'short'}
        return new Date(dateString).toLocaleDateString(undefined, options)
    }
}

let ShowDictionary = () => dictionaryComponent && dictionaryComponent.show();
let ShowTemplates = () => templatesComponent && templatesComponent.show();
let ShowTransformations = () => transformationsComponent && transformationsComponent.show();

let SetDictationControllersBehaviour = function () {

    let HTMLButtonDictationPaused = document.getElementById('invox-btn-dictation-off');
    let HTMLButtonDictationRunning = document.getElementById('invox-btn-dictation-on');
    let HTMLButtonDictationSwitch = document.getElementById('invox-btn-switch-dictation');

    HTMLButtonDictationPaused.onclick = OnDictationPaused;
    HTMLButtonDictationRunning.onclick = OnDictationRunning;
    HTMLButtonDictationSwitch.onclick = OnDictationSwitch;

    function OnDictationPaused () {
        try {
            INVOX.SetDictationPaused();
        } catch(e) {
            ShowMessage(INVOX.MessageType.ERROR, e);
        }
    }
    function OnDictationRunning () {
        try {
            INVOX.SetDictationRunning();
        } catch(e) {
            ShowMessage(INVOX.MessageType.ERROR, e);
        }
    }
    function OnDictationSwitch () {
        try {
            INVOX.SwitchDictation();
        } catch(e) {
            ShowMessage(INVOX.MessageType.ERROR, e);
        }
    }
}
//#endregion


