/**
 * Copyright (c) 2020
 *
 * CENTIRM HotelTV Core javascript.
 *
 * @summary short description for the file
 * @author Joel <joel.kim@centirm.com>
 *
 * Created at     : 2020-11-26 02:21:56
 * Last modified  : 2020-11-26 15:31:40
 */


var HotelTV = HotelTV || {
    'devinfo': {},
    'svrinfo': {},
    'services': {},
    'settings': {},
    'hotelinfo': {},
    'guestinfo': {},
    'opening': {},
    'flight': {},
    'weather': {},
    'epg': {},
    'news': {},
    'widget': {},
    'tvguide': {},
    'message': {},
    'translation': {},
    'state': {
        'lang': 'kr',
        'menu': {
            'stage': {
                'cur':null,
                'prev':null,
            },
            'main': {
                'cnt': 0,
                'cur': null,
                'prev': null,
            },
        },
        'flight': {
            'cur_location': null,
        },
        'weather': {
            'default_location': null,
        },
        'media': {
            'playing': false,
        },
        'tv':{
            'playing': false,
            'shortkey': {
                'idx': null,            // 바로가기 번호 UI의 행번호(0부터 시작)
                'ch_item_idx': null,
                'scroll_offset': null,
            },
        },
        'hotkey': {
            "mm": {}
        },
        'schedule': {
            'flight_reflash': false,
            'weather_reflash': false,
            'widget_reflash': false
        },
        'theme_root': null,
        'token': null
    },
    'carts': {
        'amenity': {

        },
        'roomservice': {

        }
    },
    'orders': {
        'amenity': {

        },
        'roomservice': {

        }
    },
    'dbginfo': {
        'en': false,
        'emulator': false, //PC 브라우저를 이용할때, true로 설정, 타겟 셋트에서는 false로 설정할것
        'hcap_ipc': false,
        'output': 'osd'
    },
    'media_hndl': null,
};



HotelTV.namespace = function(ns_string) {
    var parts = ns_string.split('.'),
        parent = HotelTV,
        i; // 처음에 중복되는 전역 객체명은 제거한다.
    if (parts[0] == 'HotelTV') {
        parts = parts.slice(1);
    }
    for (i = 0; i < parts.length; i += 1) {
        if (typeof parent[parts[i]] == 'undefined') {
            parent[parts[i]] = {};
        }
        parent = parent[parts[i]];
    }
    return parent;
};




//// 비공개 매써드
/**
 * HCAP Wrapper Function::> Get ProCentric Server Info(Realted HCAP API:hcap.system.getHotelMode)
 * @param {string} sz_key property key name.
 * @param {callback} callback is callback object
 */
function __fxn_Set_DebugOpt() {
    HotelTV.dbginfo['en'] = true;
    HotelTV.dbginfo['output'] = 'native';

    HotelTV.hcap.Init();

    /** Develop Mode definitions */
    console.log("OPT" + navigator.appVersion);
    if (navigator.appVersion.includes("Web0S") == true) {
        HotelTV.dbginfo['emulator'] = false;
    } else {
        HotelTV.dbginfo['emulator'] = true;
    }

    if (HotelTV.dbginfo['output'] == 'osd') {
        if (HotelTV.dbginfo['en'] == true) {
            (function() {
                var old = console.log;
                var logger = document.getElementById('debugwin');
                var dateNow = new Date();
                var hours = dateNow.getHours();
                var minutes = dateNow.getMinutes();
                var seconds = dateNow.getSeconds();
                if (hours < 10) {
                    hours = "0" + hours;
                }
                if (minutes < 10) {
                    minutes = "0" + minutes;
                }
                if (seconds < 10) {
                    seconds = "0" + seconds;
                }
                console.log = function(logmsg) {
                    var _dispMsg = hours + ":" + minutes + ":" + seconds + "-> ";
                    if (typeof logmsg == 'object') {
                        _dispMsg += (JSON && JSON.stringify ? JSON.stringify(logmsg) : logmsg) + '<br />';
                    } else {
                        _dispMsg += logmsg + '<br />';
                    }
                    _dispMsg += logger.innerHTML;

                    logger.innerHTML = _dispMsg;
                }
            })();
        }
    } else {
        /** Set HCAP Debug Options */
        if (HotelTV.dbginfo['emulator'] == false) {
            //Enable/Disable browser debug mode
            HotelTV.hcap.SetBrowserDebug(HotelTV.dbginfo['hcap_ipc'], HotelTV.dbginfo['en']);
        } else {
            //Below for Non WebOS
        }
    }
};




HotelTV.Init = async function() {
    console.log("Start Initialization:: ");

    //STEP#01::> Shutdown Channel
    HotelTV.hcap.ChannelShutDown();

    //SETP#02::> Set Debug Options
    __fxn_Set_DebugOpt();

    //STEP#03::> Get Device Info
    HotelTV.ui_utils.SetBusy(true);
    try {
        await HotelTV.hcap.GetDevInfo();
        //await HotelTV.hcap.ShowDevInfo();
    } catch (_error) {
        let _tmval = 10;
        HotelTV.ui_utils.ShowErrMsg(true,
            "system.error.get-devinfo",
            "SYSTEM ERROR",
            "Fail to get System Information.\r\nplease contact your system administrator.", {
                "timeout": _tmval,
                "cb_disp": function() {
                    _tmval -= 1;
                    console.log("time..." + _tmval);
                    if ($('.error #countdown').css("display") == "none") {
                        $('.error #countdown').fadeIn(1000);
                    }
                    $('.error #countdown #message').text(`System will be reboot in ${_tmval} second...`);
                },
                "cb_eoe": function() {
                    setTimeout(HotelTV.hcap.Reboot(), 500);
                }
            });
    }

    //STEP#04::> API Module INIT
    await HotelTV.api.Init(HotelTV.svrinfo.ipaddr, HotelTV.svrinfo.port, HotelTV.devinfo.model_name.substring(2, HotelTV.devinfo.model_name.length - 1), HotelTV.devinfo.serial_number);

    try {
        let __apiRet = await HotelTV.api.CheckRegistration();
        HotelTV.state['registration'] = await HotelTV.api.CheckRegistration();
    } catch (_error) {
        let _tmval = 50;
        HotelTV.ui_utils.ShowErrMsg(true,
            "system.error.check-registration",
            "SYSTEM ERROR",
            "Un registered device.\r\nplease contact your system administrator.", {
                "timeout": _tmval,
                "cb_disp": function() {
                    _tmval -= 1;
                    console.log("time..." + _tmval);
                    if ($('.error #countdown').css("display") == "none") {
                        $('.error #countdown').fadeIn(1000);
                    }
                    $('.error #countdown #message').text(`The Device ID is ${HotelTV.devinfo.serial_number}.\r\n\r\nSystem will be reboot in ${_tmval} second...`);
                },
                "cb_eoe": function() {
                    setTimeout(HotelTV.hcap.Reboot(), 500);
                }
            });
    }

    if (HotelTV.state['registration'].registered != true) {
        console.log("Show up and unregistered device");
    }

    //STEP05::> CHECK HOTELTV LICENSE
    if (HotelTV.state['registration'].license == 'hotel-full') {
        // FULL LICENSE MODE
        try {
            HotelTV.settings = await HotelTV.api.GetSettings();
            let need_reboot = await HotelTV.hcap.SetDevice(HotelTV.settings);
            if (need_reboot == true) {
                console.log("System Need to Reboot");
                HotelTV.ui_utils.SetBusy(false);

                let _tmval = 20;
                HotelTV.ui_utils.ShowErrMsg(true,
                    "system.info.change-configuration",
                    "SYSTEM INFO",
                    `System configuration was changed.\r\n\r\nSystem information summary::\r\nDevice Serial Number: ${HotelTV.devinfo.serial_number}\r\nThe Device Model Name: ${HotelTV.devinfo.model_name}\r\nNetwork Configuration:${HotelTV.devinfo.network_info.ip_address}/${HotelTV.devinfo.network_info.subnet_mask}/${HotelTV.devinfo.network_info.gateway}`, {
                        "timeout": _tmval,
                        "cb_disp": function() {
                            _tmval -= 1;
                            //console.log("time..." + _tmval);
                            if ($('.error #countdown').css("display") == "none") {
                                $('.error #countdown').fadeIn(1000);
                            }
                            $('.error #countdown #message').text(`System will be reboot in ${_tmval} second...`);
                        },
                        "cb_eoe": function() {
                            setTimeout(HotelTV.hcap.Reboot(), 500);
                        }
                    });
                return;
            }
        } catch (_error) {
            let _tmval = 50;
            HotelTV.ui_utils.ShowErrMsg(true,
                "system.set-devinfo",
                "SYSTEM ERROR",
                "Fail to configure device.\r\nplease contact your system administrator.", {
                    "timeout": _tmval,
                    "cb_disp": function() {
                        _tmval -= 1;
                        //console.log("time..." + _tmval);
                        if ($('.error #countdown').css("display") == "none") {
                            $('.error #countdown').fadeIn(1000);
                        }
                        $('.error #countdown #message').text(`The Device ID is ${HotelTV.devinfo.serial_number}.\r\n\r\nSystem will be reboot in ${_tmval} second...`);
                    },
                    "cb_eoe": function() {
                        setTimeout(HotelTV.hcap.Reboot(), 500);
                    }
                });
        }

        try {
            HotelTV.hotelinfo = await HotelTV.api.GetHotelInfo();
        } catch (_error) {
            let _tmval = 50;
            HotelTV.ui_utils.ShowErrMsg(true,
                "system.error.get-hotelinfo",
                "SYSTEM ERROR",
                "Fail to get hotel information.\r\nplease contact your system administrator.", {
                    "timeout": _tmval,
                    "cb_disp": function() {
                        _tmval -= 1;
                        //console.log("time..." + _tmval);
                        if ($('.error #countdown').css("display") == "none") {
                            $('.error #countdown').fadeIn(1000);
                        }
                        $('.error #countdown #message').text(`The Device ID is ${HotelTV.devinfo.serial_number}.\r\n\r\nSystem will be reboot in ${_tmval} second...`);
                    },
                    "cb_eoe": function() {
                        setTimeout(HotelTV.hcap.Reboot(), 500);
                    }
                });
        }
        // state[theme_root] 정의
        // For Reference:
        //      조선 : HJS00001
        //      인스파이어 : HIN00001
        //      임페리얼 : HIM00001
        HotelTV.state['theme_root'] = HotelTV.hotelinfo.siteCode;

        try {
            HotelTV.guestinfo = await HotelTV.api.GetGuestInfo();
        } catch (_error) {
            let _tmval = 50;
            HotelTV.ui_utils.ShowErrMsg(true,
                "system.error.get-guestinfo",
                "SYSTEM ERROR",
                "Fail to get guest information.\r\nplease contact your system administrator.", {
                    "timeout": _tmval,
                    "cb_disp": function() {
                        _tmval -= 1;
                        //console.log("time..." + _tmval);
                        if ($('.error #countdown').css("display") == "none") {
                            $('.error #countdown').fadeIn(1000);
                        }
                        $('.error #countdown #message').text(`The Device ID is ${HotelTV.devinfo.serial_number}.\r\n\r\nSystem will be reboot in ${_tmval} second...`);
                    },
                    "cb_eoe": function() {
                        setTimeout(HotelTV.hcap.Reboot(), 500);
                    }
                });
        }

        try {
            HotelTV.opening = await HotelTV.api.GetOpeningCtz();
        } catch (_error) {
            let _tmval = 50;
            HotelTV.ui_utils.ShowErrMsg(true,
                "system.error.get-openingctzinfo",
                "SYSTEM ERROR",
                "Fail to get opening contents information.\r\nplease contact your system administrator.", {
                    "timeout": _tmval,
                    "cb_disp": function() {
                        _tmval -= 1;
                        //console.log("time..." + _tmval);
                        if ($('.error #countdown').css("display") == "none") {
                            $('.error #countdown').fadeIn(1000);
                        }
                        $('.error #countdown #message').text(`The Device ID is ${HotelTV.devinfo.serial_number}.\r\n\r\nSystem will be reboot in ${_tmval} second...`);
                    },
                    "cb_eoe": function() {
                        setTimeout(HotelTV.hcap.Reboot(), 500);
                    }
                });
        }

        try {
            HotelTV.weather = await HotelTV.api.GetWeather();
        } catch (_error) {
            console.error("Display Error page for get Weather info");
        }

        try {
            HotelTV.flight = await HotelTV.api.GetFlight();
        } catch (_error) {
            console.error("Display Error page for get flight info");
        }

        try {
            HotelTV.widget = await HotelTV.api.GetWidgetCtz();
        } catch (_error) {
            //console.log("Display Error page for get widget info");
            HotelTV.ui_utils.ShowErrMsg(true,
                "system.error.get-widget",
                "SYSTEM ERROR",
                "Fail to get tv widget contents information.\r\nplease contact your system administrator.", {
                    "timeout": _tmval,
                    "cb_disp": function() {
                        _tmval -= 1;
                        //console.log("time..." + _tmval);
                        if ($('.error #countdown').css("display") == "none") {
                            $('.error #countdown').fadeIn(1000);
                        }
                        $('.error #countdown #message').text(`The Device ID is ${HotelTV.devinfo.serial_number}.\r\n\r\nSystem will be reboot in ${_tmval} second...`);
                    },
                    "cb_eoe": function() {
                        setTimeout(HotelTV.hcap.Reboot(), 500);
                    }
                });
        }

        try {
            HotelTV.tvguide = await HotelTV.api.GetProgramCtz();
        } catch (_error) {
            //console.log("Display Error page for get tvguide info");
            HotelTV.ui_utils.ShowErrMsg(true,
                "system.error.get-tvguideinfo",
                "SYSTEM ERROR",
                "Fail to get tv program contents information.\r\nplease contact your system administrator.", {
                    "timeout": _tmval,
                    "cb_disp": function() {
                        _tmval -= 1;
                        //console.log("time..." + _tmval);
                        if ($('.error #countdown').css("display") == "none") {
                            $('.error #countdown').fadeIn(1000);
                        }
                        $('.error #countdown #message').text(`The Device ID is ${HotelTV.devinfo.serial_number}.\r\n\r\nSystem will be reboot in ${_tmval} second...`);
                    },
                    "cb_eoe": function() {
                        setTimeout(HotelTV.hcap.Reboot(), 500);
                    }
                });
        }

        try {
            HotelTV.news = await HotelTV.api.GetNews();
        } catch (_error) {
            console.error("Display Error page for get news info");
        }

        try {
            HotelTV.message = await HotelTV.api.GetMessage();
        } catch (_error) {
            console.error("Display Error page for get news info");
        }

        try {
            HotelTV.translation = await HotelTV.api.GetTranslation();
        } catch (_error) {
            console.error("Display Error page for get translation info");
        }


        //Save to Session
        sessionStorage.setItem("devinfo", JSON.stringify(HotelTV.devinfo));
        sessionStorage.setItem("svrinfo", JSON.stringify(HotelTV.svrinfo));
        sessionStorage.setItem("settings", JSON.stringify(HotelTV.settings));
        sessionStorage.setItem("state", JSON.stringify(HotelTV.state));
        sessionStorage.setItem("hotelinfo", JSON.stringify(HotelTV.hotelinfo));
        sessionStorage.setItem("guestinfo", JSON.stringify(HotelTV.guestinfo));
        sessionStorage.setItem("opening", JSON.stringify(HotelTV.opening));
        sessionStorage.setItem("flight", JSON.stringify(HotelTV.flight));
        sessionStorage.setItem("weather", JSON.stringify(HotelTV.weather));
        sessionStorage.setItem("widget", JSON.stringify(HotelTV.widget));
        sessionStorage.setItem("tvguide", JSON.stringify(HotelTV.tvguide));
        sessionStorage.setItem("news", JSON.stringify(HotelTV.news));
        sessionStorage.setItem("message", JSON.stringify(HotelTV.message));
        sessionStorage.setItem("translation", JSON.stringify(HotelTV.translation));

        //Now Switch Over Welcome page
        if (HotelTV.opening != null) {
            $(".startup").fadeOut(1000, function() {
                window.location.replace('./wellcome.html');
            });
        } else {
            if (HotelTV.state['registration'].license == 'hotel-full') {
                setTimeout(function() {
                    window.location.replace('./app_hoteltv_full.html');
                }, 1000);
            }
        }
    } else {
        console.error("Display Error page for invalid license type.");
    }
    console.log("Initialization:: Done");
    HotelTV.ui_utils.SetBusy(false);

    SpatialNavigation.init();
};

HotelTV.LoadWelCome = async function() {
    //Turn Off HCAP api log
    extDisableHcapConsoleLog = true;

    HotelTV.devinfo = await JSON.parse(sessionStorage.getItem("devinfo"));
    HotelTV.svrinfo = await JSON.parse(sessionStorage.getItem("svrinfo"));
    //HotelTV.state = await JSON.parse(sessionStorage.getItem("state"));
    //STEP#03:API Module INIT
    await HotelTV.api.Init(HotelTV.svrinfo.ipaddr, HotelTV.svrinfo.port, HotelTV.devinfo.model_name.substring(2, HotelTV.devinfo.model_name.length - 1), HotelTV.devinfo.serial_number);
    HotelTV.settings = await JSON.parse(sessionStorage.getItem("settings"));
    HotelTV.guestinfo = await JSON.parse(sessionStorage.getItem("guestinfo"));
    HotelTV.hotelinfo = await JSON.parse(sessionStorage.getItem("hotelinfo"));
    HotelTV.opening = await JSON.parse(sessionStorage.getItem("opening"));
    HotelTV.widget = await JSON.parse(sessionStorage.getItem("widget"));
    HotelTV.tvguide = await JSON.parse(sessionStorage.getItem("tvguide"));
    try {
        HotelTV.services = await HotelTV.api.GetServiceInfo();
        sessionStorage.setItem("services", JSON.stringify(HotelTV.services));
    } catch (_error) {
        console.error("Display Error page for get service info");
    }
    //HotelTV.translation = await JSON.parse(sessionStorage.getItem("translation"));
    try {
        HotelTV.translation = await HotelTV.api.GetTranslation();
    } catch (_error) {
        console.error("Display Error page for get translation info");
    }

    //Set checkined guest language
    HotelTV.state.lang = HotelTV.guestinfo.language;

    let _res = HotelTV.devinfo.display_resolution.split("x");
    HotelTV.ui_welcome.Init(_res[0], _res[1]);

    //await HotelTV.hcap.ShowDevInfo();
    HotelTV.ui_welcome.Show();


    //STEP#06 Register Service web worker
    if (window.SharedWorker) {
        const myWorker = new SharedWorker("./lib/hoteltv.service.js");

        myWorker.port.postMessage({
            'cmd': "start_service",
            "param": {
                "token": HotelTV.state.token,
                "dev_family": HotelTV.devinfo.model_name.substring(2, HotelTV.devinfo.model_name.length - 1),
                "dev_snum": HotelTV.devinfo.serial_number,
                "svrinfo": HotelTV.svrinfo,
            },
        });


        myWorker.port.onmessage = function(e) {
            let recvMsg = e.data;
            //console.log(`Recv Msg[${recvMsg.event}]::> ${recvMsg.ret} ::> ${recvMsg.data}`);
            //console.log(`Recv Msg[${recvMsg.event}]::> ${recvMsg.ret}`);
            if (recvMsg.event == "update_report") {
                HotelTV.hcap.GetUptime();
                HotelTV.hcap.GetDeviceUsage().then(_usage => {
                    //console.log(`USAGE::> CPU[${_usage.cpu}%]`);
                    HotelTV.api.ReportBrief(HotelTV.devinfo, HotelTV.guestinfo, _usage);
                });
            }
        }
    } else {
        console.error('Your browser doesn\'t support web workers.')
    }

    //STEP#07 MQTT Service
    if (HotelTV.services) {
        if (HotelTV.services.mqtt) {
            let _mqttSvcInfo = HotelTV.services.mqtt;

            if (_mqttSvcInfo.protocol == "ws") {
                HotelTV.services.client = mqtt.connect(
                    //'ws://' + HotelTV.svrinfo.ipaddr + ':9001',
                    'ws://' + _mqttSvcInfo.host + ':' + _mqttSvcInfo.port, {
                        clean: true, // retain session
                        connectTimeout: 4000, // Timeout period
                        username: _mqttSvcInfo.username,
                        password: _mqttSvcInfo.password,
                        clientId: 'mqtt_sid_' + HotelTV.devinfo.serial_number.substring(0, 12)
                    }
                );

                HotelTV.services.client.on('connect', function() {
                    HotelTV.services.client.subscribe(_mqttSvcInfo.topic, function(err) {
                        if (err) {
                            console.error(`Fail to subscribe::TOPIC[${_mqttSvcInfo.topic}]`);
                        } else {
                            console.log(`Success to subscribe::TOPIC[${_mqttSvcInfo.topic}]`);
                        }
                    });
                })

                HotelTV.services.client.on('message', function(topic, message) {
                    let szMsg = message.toString();
                    HotelTV.ui_welcome.MqttEvent(szMsg);
                    //MQTT메시지 종료 하려면 아래 end호출
                    //HotelTV.services.client.end()
                })

                HotelTV.services.client.on('error', function(error) {
                    // message is Buffer
                    console.error(error.toString());
                    //HotelTV.services.client.end()
                })
            }
        }
    }
}

HotelTV.UnloadWelCome = async function() {
    sessionStorage.setItem("state", JSON.stringify(HotelTV.state));
    HotelTV.ui_welcome.Close();

    //MQTT Disconnect
    if( HotelTV.services.client ){
        HotelTV.services.client.end();
    }

    if (HotelTV.state['registration'].license == 'hotel-full') {
        setTimeout(function() {
            window.location.replace('./app_hoteltv_full.html');
        }, 1000);
    }
}


HotelTV.LoadAppFull = async function() {
    //Turn Off HCAP api log
    extDisableHcapConsoleLog = true;

    HotelTV.ui_utils.SetBusy(true);

    //STEP#01: Load session info
    HotelTV.devinfo = await JSON.parse(sessionStorage.getItem("devinfo"));
    HotelTV.svrinfo = await JSON.parse(sessionStorage.getItem("svrinfo"));
    HotelTV.services = await JSON.parse(sessionStorage.getItem("services"));
    //HotelTV.state = await JSON.parse(sessionStorage.getItem("state"));

    //STEP#02: Init HotelTV API
    await HotelTV.api.Init(HotelTV.svrinfo.ipaddr, HotelTV.svrinfo.port, HotelTV.devinfo.model_name.substring(2, HotelTV.devinfo.model_name.length - 1), HotelTV.devinfo.serial_number);
    HotelTV.settings = await JSON.parse(sessionStorage.getItem("settings"));
    HotelTV.guestinfo = await JSON.parse(sessionStorage.getItem("guestinfo"));
    HotelTV.hotelinfo = await JSON.parse(sessionStorage.getItem("hotelinfo"));
    HotelTV.weather = await JSON.parse(sessionStorage.getItem("weather"));
    HotelTV.opening = await JSON.parse(sessionStorage.getItem("opening"));
    HotelTV.widget = await JSON.parse(sessionStorage.getItem("widget"));
    HotelTV.tvguide = await JSON.parse(sessionStorage.getItem("tvguide"));
    HotelTV.flight = await JSON.parse(sessionStorage.getItem("flight"));
    HotelTV.news = await JSON.parse(sessionStorage.getItem("news"));
    HotelTV.message = await JSON.parse(sessionStorage.getItem("message"));

    try {
        HotelTV.epg = await HotelTV.api.GetEpg();
    } catch (_error) {
        console.error("Display Error page for get epg info");
    }

    try {
        HotelTV.carts.amenity = await HotelTV.api.GetAmenityCarts(null);
    } catch (_error) {
        console.error("Display Error page for get amenity carts info");
    }

    HotelTV.carts.roomservice = await HotelTV.api.GetRoomserviceCarts();
    try {
    } catch (_error) {
        console.error("Display Error page for get roomservicec carts info");
    }


    try {
        HotelTV.orders.amenity = await HotelTV.api.GetAmenityOrders(null);
    } catch (_error) {
        console.error("Display Error page for get amenity order info");
    }

    try {
        HotelTV.orders.roomservice = await HotelTV.api.GetRoomserviceOrders(null);
    } catch (_error) {
        console.error("Display Error page for get roomservice order info");
    }


    try {
        HotelTV.translation = await HotelTV.api.GetTranslation();
    } catch (_error) {
        console.error("Display Error page for get translation info");
    }
    //HotelTV.translation = await JSON.parse(sessionStorage.getItem("translation"));


    //STEP#03: INIT HCAP for HotelTV FullAPP
    let tmrAppAuth = setInterval(async function() {
        let _foundNetflix = false;
        let _hcapAppInfo = await HotelTV.hcap.PreAppGetInfo(false);
        HotelTV.state['hcap_app'] = _hcapAppInfo.applist;
        for (_i = 0; _i < HotelTV.state['hcap_app'].length; _i++) {
            if (HotelTV.state['hcap_app'][_i].title == "Netflix") {
                console.log("Found out netflix among of pre hcap app-list.")
                clearInterval(tmrAppAuth);
            }
        }

        if (_foundNetflix == false) {
            try {
                let siAppToken = null;
                let siAppName = null;
                // siApp Token Authentication
                let _progam = HotelTV.tvguide.program;
                for (let _i = 1; _i <= _progam.length; _i++) {
                    if (_progam[_i].type == "application" && _progam[_i].service == "netflix") {
                        siAppToken = await HotelTV.api.DownloadData(_progam[_i].license.file.download);
                        siAppName = _progam[_i].service;
                        //siAppToken = _progam[_i].service;

                        if (siAppName && siAppToken) {
                            HotelTV.hcap.siAppAuth(siAppName, siAppToken, false);
                        }
                    }
                }
            } catch (_error) {
                console.error("Display Error page for get siApp Auth");
            }
        }
    }, 5000);


    //STEP#05: Set Display size
    let _res = HotelTV.devinfo.display_resolution.split("x");
    HotelTV.ui_appfull.Init(_res[0], _res[1]);

    //STEP#06; Show UI
    //await HotelTV.hcap.ShowDevInfo();
    HotelTV.ui_appfull.Show();

    //STEP#06 Register Service web worker
    if (window.SharedWorker) {
        const myWorker = new SharedWorker("./lib/hoteltv.service.js");

        myWorker.port.postMessage({
            'cmd': "start_service",
            "param": {
                "token": HotelTV.state.token,
                "dev_family": HotelTV.devinfo.model_name.substring(2, HotelTV.devinfo.model_name.length - 1),
                "dev_snum": HotelTV.devinfo.serial_number,
                "svrinfo": HotelTV.svrinfo,
            },
        });



        myWorker.port.onmessage = function(e) {
            let recvMsg = e.data;
            //console.log(`Recv Msg[${recvMsg.event}]::> ${recvMsg.ret} ::> ${recvMsg.data}`);
            //console.log(`Recv Msg[${recvMsg.event}]::> ${recvMsg.ret}`);
            if (recvMsg.event == "update_epg") {
                if (recvMsg.ret === "OK") {
                    HotelTV.epg = recvMsg.data;
                    HotelTV.ui_appfull.UpdateEpg();
                }
            } else if (recvMsg.event == "update_flight") {
                if (recvMsg.ret === "OK") {
                    HotelTV.flight =recvMsg.data;
                }
            } else if (recvMsg.event == "update_weather") {
                if (recvMsg.ret === "OK") {
                    HotelTV.weather = recvMsg.data;
                }
            } else if (recvMsg.event == "update_wiget") {
                if (recvMsg.ret === "OK") {
                    HotelTV.widget = recvMsg.data;
                }
            } else if (recvMsg.event == "update_report") {
                HotelTV.hcap.GetUptime();
                HotelTV.hcap.GetDeviceUsage().then(_usage => {
                    //console.log(`USAGE::> CPU[${_usage.cpu}%]`);
                    HotelTV.api.ReportBrief(HotelTV.devinfo, HotelTV.guestinfo, _usage);
                });
            }

            // BGServiceEvent function for post processing
            HotelTV.ui_appfull.BGServiceEvent(recvMsg.event);
        }
    } else {
        console.error('Your browser doesn\'t support web workers.')
    }

    //STEP#07 MQTT Service
    if (HotelTV.services) {
        if (HotelTV.services.mqtt) {
            let _mqttSvcInfo = HotelTV.services.mqtt;

            if (_mqttSvcInfo.protocol == "ws") {
                HotelTV.services.client = mqtt.connect(
                    //'ws://' + HotelTV.svrinfo.ipaddr + ':9001',
                    'ws://' + _mqttSvcInfo.host + ':' + _mqttSvcInfo.port, {
                        clean: true, // retain session
                        connectTimeout: 4000, // Timeout period
                        username: _mqttSvcInfo.username,
                        password: _mqttSvcInfo.password,
                        clientId: 'mqtt_sid_' + HotelTV.devinfo.serial_number.substring(0, 12)
                    }
                );

                HotelTV.services.client.on('connect', function() {
                    HotelTV.services.client.subscribe(_mqttSvcInfo.topic, function(err) {
                        if (err) {
                            console.error(`Fail to subscribe::TOPIC[${_mqttSvcInfo.topic}]`);
                        } else {
                            console.log(`Success to subscribe::TOPIC[${_mqttSvcInfo.topic}]`);
                        }
                    });
                })

                HotelTV.services.client.on('message', function(topic, message) {
                    let szMsg = message.toString();
                    HotelTV.ui_appfull.MqttEvent(szMsg);
                    //MQTT메시지 종료 하려면 아래 end호출
                    //HotelTV.services.client.end()
                })

                HotelTV.services.client.on('error', function(error) {
                    // message is Buffer
                    console.error(error.toString());
                    //HotelTV.services.client.end()
                })
            }
        }
    }


    //
    //HotelTV.hcap.Test();
}

HotelTV.UnloadAppFull = async function() {
    //MQTT Disconnect
    if( HotelTV.services.client ){
        HotelTV.services.client.end();
    }
}


HotelTV.Deinit = function() {
    console.log("Start De-Initialization:: ");
    //HotelTV.service.Deinit();
}