/**
 * Created by liutiantian on 15-2-2.
 */

function IQQIEventHandler() {
    if(this.constructor.initialized == undefined) {
        this.constructor.prototype.gainFocus = function() {
            throw new Error("subclass must override gainFocus Method.");
        };

        this.constructor.prototype.releaseFocus = function() {
            throw new Error("subclass must override releaseFocus Method.");
        };

        this.constructor.prototype.onMainPageStateChange = function(state) {
            throw new Error("subclass must override onMainPageStateChange Method. show state: " + IQQIMainPage.stateToString(state));
        };
    }
}

function IQQIViewGroup(html) {
    ltt.api.js.ui.ViewGroup.call(this, html);

    if(this.constructor.initialized == undefined) {
        this.constructor.prototype.classmaker = host.tools.classmaker;

        IQQIEventHandler.call(this);
    }
}

function IQQIMainPage(lan, mode, value, position, min, max, maxLength, viewType, workType, inputName) {
    this.type = "IQQIMainPage";
    this.input = new IQQIInputPanel(html_input_panel, value, position, min, max, maxLength, viewType, workType);
    this.imagineUl = new IQQIImagineUl("iqqi_imagine_area", html_iqqi_imagine_ul, "iqqi_imagine_content_item", "iqqi_imagine_content_item_content", "iqqi_imagine_content_item_content_first", "iqqi_imagine_content_item_divider", null);
    this.buttonPanel = new IQQIButtonPanel("iqqi_button_panel", html_iqqi_button_panel, lan, mode);
    this.controlPanel = new IQQIFourColorControlPanel(html_control_panel);
    this.curFocus = this.buttonPanel;
    //var lanCode = (iqqi_new_array.indexOf(lan) > -1);
    //if (lanCode) {
        this.inputTitle = new IQQIInputName("iqqi_input_name", html_iqqi_input_name, lan, inputName);
    //}

    IQQIViewGroup.call(this, {
        "tag": "div",
        "classes": "iqqi_main_page",
        "id": "iqqi_main_page",
        "state": "normal",
        "flags": iqqi_constances.c_default|iqqi_constances.c_browser_webkit,
        "children": [
            {
                "tag": "div",
                "classes": "iqqi_input_panel",
                "id": "iqqi_input_panel",
                "state": "normal",
                "flags": iqqi_constances.c_default|iqqi_constances.c_password
            },
            {
                "tag": "div",
                "classes": "iqqi_app_area",
                "id": "iqqi_app_area",
                "state": "normal",
                "flags": iqqi_constances.c_default|iqqi_constances.c_password,
                "children": [
                    {
                        "tag": "div",
                        "classes": "iqqi_image_area",
                        "id": "iqqi_imagine_area",
                        "state": "normal",
                        "flags": iqqi_constances.c_default_btn|iqqi_constances.c_browser_webkit|iqqi_constances.c_password|iqqi_constances.c_rtl
                    },
                    {
                        "tag": "div",
                        "classes": "iqqi_button_panel",
                        "id": "iqqi_button_panel",
                        "state": "normal",
                        "flags": iqqi_constances.c_default|iqqi_constances.c_rtl
                    },
                    {
                        "tag": "div",
                        "classes": "iqqi_control_area",
                        "id": "iqqi_control_area",
                        "state": "normal",
                        "flags": iqqi_constances.c_default|iqqi_constances.c_rtl
                    }
                ]
            },
            {
                "tag": "div",
                "classes": "iqqi_input_name",
                "id": "iqqi_input_name",
                "state": "normal",
                "flags": iqqi_constances.c_default | iqqi_constances.c_password
            }
        ]
    });

    if(typeof IQQIMainPage.initialized == "undefined") {
        IQQIMainPage.STATE_FRESH = 0;
        IQQIMainPage.STATE_SHOWING = 1;
        IQQIMainPage.STATE_BACK = 2;
        IQQIMainPage.STATE_EXIT = 3;

        IQQIMainPage.stateToString = function(state) {
            if(state != undefined) {
                if(state == IQQIMainPage.STATE_FRESH) {
                    return "STATE_FRESH";
                }
                else if(state == IQQIMainPage.STATE_SHOWING) {
                    return "STATE_SHOWING";
                }
                else if(state == IQQIMainPage.STATE_BACK) {
                    return "STATE_BACK";
                }
                else if(state == IQQIMainPage.STATE_EXIT) {
                    return "STATE_EXIT";
                }
            }
        };

        IQQIMainPage.prototype.onNodeCreated = function(node) {
            if(node.id == this.html.id) {
                if(!host.tools.isRunningOnOpera()) {
                    node.onselectstart = function() {
                        return false;
                    };
                }
            }

            if(host.tools.isRunningOnOpera()) {
                if(node.textContent) {
                    node.unselectable = "on";
                }
            }
        };
        //hide image erea by curMode
        IQQIMainPage.prototype.befShow = function() {
            //this.deleteNode(this.html.children[1].children[0].id, !(host.iqqi.input.html.children[0]["type"] == "text"));
            this.deleteNode(this.html.children[1].children[0].id, !(host.config.curMode != Tools.MODE_PASSWORD));
        };

        IQQIMainPage.prototype.aftShow = function(node) {
            host.logger.i("iqqi", "IQQIMainPage.prototype.aftShow.DI1210", "id: " + (node && node.id));
            if(node == undefined || node.id == this.html.id) {
                this.pageState(IQQIMainPage.STATE_SHOWING);
                host.logger.i("iqqi", "IQQIMainPage.prototype.aftShow.DI1210", "views: " + (this.views && Object.keys(this.views).length > 0));
                if(this.views && Object.keys(this.views).length > 0) {
                    for(var vi = 0; vi < this.views.length; ++vi) {
                        host.logger.i("iqqi", "IQQIMainPage.prototype.aftShow.DI1210", "id: " + this.views[vi].view.html.id + "; attached: " + this.views[vi].attached);
                        if(this.views[vi].attached) {
                            this.views[vi].view.aftShow();
                        }
                    }
                }
            }
        };

        IQQIMainPage.prototype.gainFocus = function() {

        };

        IQQIMainPage.prototype.releaseFocus = function() {

        };

        IQQIMainPage.prototype.onMainPageStateChange = function(state) {
            if(this.views && Object.keys(this.views).length > 0) {
                for(var vi = 0; vi < this.views.length; ++vi) {
                    if(state == IQQIMainPage.STATE_BACK || state == IQQIMainPage.STATE_EXIT) {
                        this.views[vi].attached = false;
                    }
                    this.views[vi].view.onMainPageStateChange(state);
                }
            }
        };

        IQQIMainPage.prototype.onKeyDown = function(event) {
            host.logger.i("iqqi", "IQQIMainPage.prototype.onKeyDown", "curFocus type is:" + this.curFocus.type);
            if(this.curFocus && host.keyevent.validKeyEvent(this.curFocus.type, host.keyevent.STATE_DOWN, event.which)) {
                if(this.curFocus.onKeyDown(event)) {
                    return true;
                }
                else {
                    host.logger.i("iqqi", "IQQIMainPage.prototype.onKeyDown", "this.curFocus.onKeyDown return is NULL");
                    switch(event.which) {
                        case host.keyevent.VK_UP:
                            return onKeyUpDown(this);
                        case host.keyevent.VK_DOWN:
                            return onKeyDownDown(this);
                        case host.keyevent.VK_ESC:
                            return onKeyBackDown(this);
                    }
                }
            }
            else {
                host.logger.i("iqqi", "IQQIMainPage.prototype.onKeyDown", "curFocus is undefined or invalidkey");
                switch(event.which) {
                    case host.keyevent.VK_DOWN:
                        return onKeyDownDown(this);
                    case host.keyevent.VK_UP:
                        return onKeyUpDown(this);
                    case host.keyevent.VK_BACK:
                        return onKeyBackDown(this, event.keyFrom, 1);
                    case host.keyevent.VK_ESC:
                        return onKeyBackDown(this, event.keyFrom, 0);
                    case host.keyevent.VK_ENTER:
                        return onKeyEnterDown(this);
                    case host.keyevent.VK_RED:
                        return this.controlPanel.onKeyDown(event);
                    case host.keyevent.VK_GREEN:
                        return this.controlPanel.onKeyDown(event);
                    case host.keyevent.VK_YELLOW:
                        return this.controlPanel.onKeyDown(event);
                    case host.keyevent.VK_BLUE:
                        return this.controlPanel.onKeyDown(event);
                }
            }
            if(this.curFocus == host.iqqi.lanSwitch) {
                return true;
            }
            return false;
        };

        IQQIMainPage.prototype.switchFocus = function(newFocus, release, gain) {
            if(this.curFocus == newFocus) {
                return;
            }
            (release == undefined || release) && (this.curFocus && this.curFocus.releaseFocus());
            this.lastFocus = this.curFocus;
            this.curFocus = newFocus;
            (gain == undefined || gain) && (this.curFocus && this.curFocus.gainFocus());

        };

        IQQIMainPage.prototype.pageState = function(state) {
            if(state != undefined) {
                if(this.state != state) {
                    this.onMainPageStateChange(state);
                }
                this.state = state;
            }
            else {
                return this.state;
            }
        };

        /**
         * response to back on remote control.
         * @param self
         * @returns {boolean}
         */
        function onKeyBackDown(self, from, isback){
            DBG_ERROR("onKeyBackDown..111...."+from);
            var keyFrom = from;
            if(keyFrom == null){
                keyFrom = "Remote";
            }
            //self.hide();
            if(keyFrom !="Remote" && isback){
                self.buttonPanel. responseToBackButton(self.buttonPanel);
                return true;
            }
            else{
                self.input.onBack();
                host.logger.i("iqqi", "IQQIMainPage.prototype.onKeyBackDown", "must return back from callback");
                if (!!self.charPanel) {
                    self.charPanel.hide();
                }
                self.hide();
                return true;
            }

        }

        function onKeyUpDown(self) {
            if(self.curFocus == self.buttonPanel) {
                if(self.imagineUl.working) {
                    self.switchFocus(self.imagineUl);
                }
                else {
                    self.switchFocus(self.input);
                }
            }
            else if(self.curFocus == self.imagineUl) {
                self.switchFocus(self.input);
            }
            // we shield up key's default action, because we has already customized the down action.
            return true;
        }

        function onKeyDownDown(self) {
            if(self.curFocus == self.input) {
                if(self.imagineUl.working) {
                    self.switchFocus(self.imagineUl);
                }
                else {
                    self.switchFocus(self.buttonPanel);
                }
            }
            if(self.curFocus == self.imagineUl) {
                self.switchFocus(self.buttonPanel);
            }
            return true;
        }

        function onKeyEnterDown(self) {
            if(self.curFocus == self.input) {
                self.input.onExit();
                host.logger.i("iqqi", "IQQIMainPage.prototype.onKeyEnterDown", "must return back from callback");
                self.hide();
                if (!!self.charPanel) {
                    self.charPanel.hide();
                }
                return true;
            }
            return false;
        }
    }
    IQQIMainPage.initialized = true;

    this.lanSwitch = new IQQILanSwitchDialog(host.tools.getLanguageList(), "iqqi_lan_switch_item", "iqqi_lan_switch_item_selector", "iqqi_lan_switch_item_label", function(lan) {
        this.curFocus = this.buttonPanel;
        if(!!lan) {
            host.logger.i("iqqi", "IQQIMainPage", "show code: " + lan.code + "; curLang: " + host.config.curLang);
            if(lan.code == host.config.curLang) {
                //this.buttonPanel.setLanAndMode(lan.code, Tools.MODE_LANGUAGE);
                this.buttonPanel.setLanAndMode(lan.code, host.config.curMode);
                this.charPanel.setLanAndMode(lan.code, host.config.curMode);
                return;
            }
            if(!!host.iqqi.buttonPanel.currentImagineRoot) {
                host.iqqi.input.insertValue(host.iqqi.buttonPanel.currentImagineRoot);
                host.iqqi.buttonPanel.currentImagineRoot = "";
                host.iqqi.buttonPanel.lastDisplay = [];
                host.iqqi.imagineUl.hideUl();
            }
            this.buttonPanel.shiftMode = false;
            this.buttonPanel.capsMode = false;

            var oldRtl = host.tools.assertLanguageRtl(host.config.curLang);
            var newRtl = host.tools.assertLanguageRtl(lan.code);
            host.logger.i("iqqi", "IQQIMainPage", "show oldRtl: " + oldRtl + "; newRtl: " + newRtl);
            //this.buttonPanel.setLanAndMode(lan.code, Tools.MODE_LANGUAGE);
            this.buttonPanel.setLanAndMode(lan.code, host.config.curMode);
            if (typeof IQQICharPanel.initialized != "undefined") {
                IQQICharPanel.initialized = false;
            }
            this.input.onNewLanguageSetted(oldRtl != newRtl);
            this.imagineUl.onNewLanguageSetted(oldRtl != newRtl);
            this.controlPanel.onNewLanguageSetted(oldRtl != newRtl);
            this.inputTitle.onNewLanguageSetted(oldRtl != newRtl);
            //if(host.config.workType != "password") {
                window.localStorage["iqqiLanguage"] = host.config.curLang;
            //}

        }

    }.bind(this));

    this.addView(this.input, this.input.html.id);
    this.addView(this.imagineUl, this.imagineUl.html.id);
    this.addView(this.buttonPanel, this.buttonPanel.html.id);
    this.addView(this.controlPanel, this.controlPanel.html.id);
    this.pageState(IQQIMainPage.STATE_FRESH);
}

function IQQIView(html) {
    ltt.api.js.ui.View.call(this, html);

    if(this.constructor.initialized == undefined) {
        this.constructor.prototype.classmaker = host.tools.classmaker;

        this.constructor.prototype.stringGet = function(key) {
            return strings[key][host.config.curColorLanguage];
        };

        IQQIEventHandler.call(this);
    }
}

function IQQIInputName(id, html, lan, txt) {
    IQQIView.call(this, id);
    this.type = "IQQIInputName";
    this.html = html;
    this.html.classes = "iqqi_input_name_text";

    if(IQQIInputName.initialized == undefined) {
        IQQIInputName.prototype.onNewLanguageSetted = function(rewrite) {
            var enter = document.getElementById("iqqi_input_name");
            txt = host.config.IQQIInputName;
            if(!!enter) {
                if (!!txt) {
                    enter.innerHTML = txt;
                } else {
                    enter.innerHTML = "Please Input: ";
                }
            }
            /*if (!!rewrite) {
                enter.innerHTML = rewrite;
            }*/
        };
    }

}

function IQQIButtonPanel(id, html, lan, mode) {
    IQQIView.call(this, id);
    this.type = "IQQIButtonPanel";
    this.html = html;

    this.focusRow = 0;
    this.focusCol = 0;

    this.shiftMode = false;
    this.capsMode = false;

    this.currentImagineRoot = "";
    this.imeType = host.tv ? imejs.iqqi.ENGLISH : -1;
    this.getType = host.tv ? host.native.TYPE_CANDIDATE_ALL : 0;
    this.lastDisplay = [];

    if(typeof IQQIButtonPanel.initialized == "undefined") {
        IQQIButtonPanel.prototype.onNodeCreated = function(node) {
                //if(IQQIButtonPanel.prototype.onNodeCreated.initialized == undefined) {
            if(true) {
                function validLineKey(node) {
                    if(validLineKey.initialized == undefined) {
                        validLineKey.validater = new RegExp("^.+LineKey_\\d+$", "gm");
                        validLineKey.cache = new ltt.api.js.util.Cache("panel_id", 128);
                        validLineKey.initialized = true;
                    }

                    if(!validLineKey.cache.containsKey(node.id)) {
                        validLineKey.cache.cache(node.id, validLineKey.validater.test(node.id));
                    }
                    return validLineKey.cache.get(node.id);
                }

                function findPosition(node) {
                    if(findPosition.initialized == undefined) {
                        findPosition.cache = new ltt.api.js.util.Cache("line_key_position", 128);
                        findPosition.initialized = true;
                    }

                    if(!findPosition.cache.containsKey(node.id)) {
                        findPosition.cache.cache(node.id, {"row": host.config.rows.indexOf(node.id.split("_")[0]), "col": parseInt(node.id.split("_")[1])});
                    }

                    return findPosition.cache.get(node.id);
                }

                function onPanelEnter() {
                    if (host.iqqi.curFocus != host.iqqi.charPanel) {
                        host.logger.i("iqqi", "IQQIButtonPanel.prototype.onNodeCreated.onPanelEnter.DI1210", "this.id: " + this.id);
                        host.iqqi.lastFocus = host.iqqi.curFocus;
                        host.iqqi.curFocus = host.iqqi.buttonPanel;
                    }
                }

                function onPanelLeave() {
                    host.logger.i("iqqi", "IQQIButtonPanel.prototype.onNodeCreated.onPanelLeave.DI1210", "this.id: " + this.id);
                }

                function onLineKeyEnter() {
                    if (host.iqqi.curFocus != host.iqqi.charPanel) {
                        host.logger.i("iqqi", "IQQIButtonPanel.prototype.onNodeCreated.onLineKeyEnter.DI1210", "this.id: " + this.id);
                        setFocus(host.iqqi.buttonPanel, findPosition(node).row, findPosition(node).col);
                    }
                }

                function onLineKeyLeave() {
                    if (host.iqqi.curFocus != host.iqqi.charPanel) {
                        host.logger.i("iqqi", "IQQIButtonPanel.prototype.onNodeCreated.onLineKeyLeave.DI1210", "this.id: " + this.id);
                        setFocus(host.iqqi.buttonPanel, -1, -1);
                    }
                }

                function onLineKeyClick() {
                    if (host.iqqi.curFocus != host.iqqi.charPanel) {
                        host.logger.i("iqqi", "IQQIButtonPanel.prototype.onNodeCreated.onLineKeyClick.DI1210", "this.id: " + this.id);
                        host.iqqi.buttonPanel.onKeyDown({"which": host.keyevent.VK_ENTER});
                    }
                }

                IQQIButtonPanel.prototype.onNodeCreated.initialized = true;
            }

            if(node.id == this.html.id) {
                node.onmouseenter = onPanelEnter;
                node.onmouseleave = onPanelLeave;
            }
            else if(validLineKey(node)) {
                node.onmouseenter = onLineKeyEnter;
                node.onmouseleave = onLineKeyLeave;
            }

            if(validLineKey(node)) {
                node.onclick = onLineKeyClick;
            }

            if(host.tools.isRunningOnOpera()) {
                if(node.textContent) {
                    node.unselectable = "on";
                }
            }
        };

        IQQIButtonPanel.prototype.onMainPageStateChange = function(state) {
            if(state == IQQIMainPage.STATE_BACK || state == IQQIMainPage.STATE_EXIT) {
                setFocus(this, -1, -1);
            }
        };

        IQQIButtonPanel.prototype.setLanAndMode = function(lan, mode) {
            host.logger.i("iqqi", "IQQIButtonPanel.setLanAndMode", "show lan: " + lan + "; mode: " + mode);
            host.config.curLang = lan;
            host.config.curMode = mode;
            if(!host.config.data[lan]) {
                host.config.curLang = host.config.curLangArray[0];
            }
            adaptTTFForLan(host.config.curLang);
            host.config.curImeType = host.tv ? host.config.ImeDict[host.config.curLang] : -1;
            host.config.curImeFirst = ("CHI" == host.config.curLang || "ZHO" == host.config.curLang) == false;

            this.csses = this.getCsses();
            this.display = this.getDisplay();
            this.content = this.getContent();

            for(var row = 0; row < 6; row++) {
                this.html.children[row].classes = this.csses.lines[row];
                for(var col = 0; col < 15; col++) {
                    if(!!this.csses) {
                        var css = this.csses.buttons[host.config.rows[row]] && this.csses.buttons[host.config.rows[row]][col];
                        if(!!css) {
                            this.html.children[row].children[col].classes = this.csses.buttons[host.config.rows[row]][col];
                        }
                    }

                    var type = this.display[host.config.rows[row]] && this.display[host.config.rows[row]][col];
                    this.html.children[row].children[col].state = "gone";
                    if(!!type) {
                        this.html.children[row].children[col].state = "normal";
                    }

                    var value = this.content[host.config.rows[row]] && this.content[host.config.rows[row]][col];
                    delete this.html.children[row].children[col].content;
                    if(!!value) {
                        this.html.children[row].children[col].content = value;
                    }
                }
            }

            this.rewrite();

            switch(mode) {
                case Tools.MODE_LANGUAGE:
                    setFocus(this, 0, 0);
                    if (!!this.shiftMode) {
                        shiftToShiftIQQI(host.config.curLang);
                    }
                    if (!!this.capsMode) {
                        shiftToCapsIQQI(host.config.curLang);
                    }
                    break;
                case Tools.MODE_NUM1:
                    setFocus(this, 0, 3);
                    break;
                case Tools.MODE_NUM2:
                    setFocus(this, 0, 0);
                    break;
                case Tools.MODE_PASSWORD:
                    setFocus(this, 0, 0);
                    if (!!this.shiftMode) {
                        shiftToShiftIQQI(host.config.curLang);
                    }
                    if (!!this.capsMode) {
                        shiftToCapsIQQI(host.config.curLang);
                    }
                    break;
            }
        };

        IQQIButtonPanel.prototype.onKeyDown = function(event) {
            switch(event.which) {
                case host.keyevent.VK_DOWN:
                    if (event.keyFrom != "Keyboard") {
                        return onKeyDownDown(this);
                    }
                    return true;
                case host.keyevent.VK_UP:
                    if (event.keyFrom != "Keyboard") {
                        return onKeyUpDown(this);
                    }
                    return true;
                case host.keyevent.VK_RIGHT:
                    if (event.keyFrom != "Keyboard") {
                        if(GLOBAL.RTL)  {
                            return onKeyLeftDown(this);
                        }
                        return onKeyRightDown(this);
                    }

                case host.keyevent.VK_LEFT:
                    if (event.keyFrom != "Keyboard") {
                        if(GLOBAL.RTL)  {
                            return onKeyRightDown(this);
                        }
                        return onKeyLeftDown(this);
                    }

                case host.keyevent.VK_ENTER:
                    //if( this.focusRow < 0) return false;
                    dispatchEnterDown(this, this.focusRow, this.focusCol);
                    return true;
            }
        };

        IQQIButtonPanel.prototype.getDisplay = function() {
            switch(host.config.curMode) {
                case Tools.MODE_LANGUAGE:
                    /*if(host.config.curLang == "MYA") {
                        return (host.config.data[host.config.curLang][host.config.myaPageNum] || host.config.data[host.config.curLang]).display;
                    }*/
                    if(this.shiftMode || this.capsMode) {
                        return host.config.data[host.config.curLang].upper.display || host.config.data[host.config.curLang].display;
                    }
                    return host.config.data[host.config.curLang].display;
                case Tools.MODE_NUM1:
                    if("password" == host.config.workType) {
                        return host.config.data["NUM1"].display;
                    }
                    if(host.config.data["NUM1"][host.config.curLang]) {
                        return host.config.data["NUM1"][host.config.curLang].display || host.config.data["NUM1"].display;
                    }
                    return host.config.data["NUM1"].display;
                case Tools.MODE_NUM2:
                    if("password" == host.config.workType) {
                        return host.config.data["NUM2"].display;
                    }
                    if(!!host.config.data["NUM2"][host.config.curLang]) {
                        return host.config.data["NUM2"][host.config.curLang].display || host.config.data["NUM2"].display;
                    }
                    return host.config.data["NUM2"].display;
                case Tools.MODE_PASSWORD:
                    if(this.shiftMode || this.capsMode) {
                        return host.config.data[host.config.curLang].upper.display || host.config.data[host.config.curLang].display;
			//return host.config.data["ENG"].upper.display || host.config.data["ENG"].display;
                    }
                    return host.config.data[host.config.curLang].display;
		    //return host.config.data["ENG"].display;
            }
        };

        IQQIButtonPanel.prototype.getCsses = function() {
            var inner = {};
            switch(host.config.curMode) {
                case Tools.MODE_LANGUAGE:
                    /*if(host.config.curLang == "MYA") {
                        if(host.config.data[host.config.curLang][host.config.myaPageNum] && host.config.data[host.config.curLang][host.config.myaPageNum].csses) {
                            inner.csses = host.config.data[host.config.curLang][host.config.myaPageNum].csses;
                            break;
                        }
                        inner.csses = host.config.data[host.config.curLang].csses;
                        break;
                    }*/
                    if(this.shiftMode || this.capsMode) {
                        if(!!host.config.data[host.config.curLang].upper.csses) {
                            inner.csses = host.config.data[host.config.curLang].upper.csses || host.config.data[host.config.curLang].csses;
                            break;
                        }
                    }
                    inner.csses = host.config.data[host.config.curLang].csses;
                    break;
                case Tools.MODE_NUM1:
                    if("password" == host.config.workType) {
                        inner.csses = host.config.data["NUM1"].csses;
                        break;
                    }
                    if(host.config.data["NUM1"][host.config.curLang]) {
                        inner.csses = host.config.data["NUM1"][host.config.curLang].csses || host.config.data["NUM1"].csses;
                        break;
                    }
                    inner.csses = host.config.data["NUM1"].csses;
                    break;
                case Tools.MODE_NUM2:
                    if("password" == host.config.workType) {
                        inner.csses = host.config.data["NUM2"].csses;
                        break;
                    }
                    if(host.config.data["NUM2"][host.config.curLang]) {
                        inner.csses = host.config.data["NUM2"][host.config.curLang].csses || host.config.data["NUM2"].csses;
                        break;
                    }
                    inner.csses = host.config.data["NUM2"].csses;
                    break;
                case Tools.MODE_PASSWORD:
                    if(this.shiftMode || this.capsMode) {
                        inner.csses = host.config.data[host.config.curLang].upper.csses || host.config.data[host.config.curLang].csses;
			//inner.csses = host.config.data["ENG"].upper.csses || host.config.data["ENG"].csses;
                        break;
                    }
                    inner.csses = host.config.data[host.config.curLang].csses;
		    //inner.csses = host.config.data["ENG"].csses;
                    break;
            }
            switch(host.screen) {
                case "720P":
                    return inner.csses["720P"] || inner.csses["1080P"];
                case "1080P":
                    return inner.csses["1080P"] || inner.csses["720P"];
            }
        };

        IQQIButtonPanel.prototype.getContent = function() {
            switch(host.config.curMode) {
                case Tools.MODE_LANGUAGE:
                   /* if(host.config.curLang == "MYA") {
                        return (host.config.data[host.config.curLang][host.config.myaPageNum] || host.config.data[host.config.curLang]).content;
                        break;
                    }*/
                    if(this.shiftMode || this.capsMode) {
                        return host.config.data[host.config.curLang].upper.content;
                    }
                    return host.config.data[host.config.curLang].content;
                case Tools.MODE_NUM1:
                    if("password" == host.config.workType) {
                        return host.config.data["NUM1"].content;
                    }
                    if(host.config.data["NUM1"][host.config.curLang]) {
                        return host.config.data["NUM1"][host.config.curLang].content || host.config.data["NUM1"].content;
                    }
                    return host.config.data["NUM1"].content;
                case Tools.MODE_NUM2:
                    if("password" == host.config.workType) {
                        return host.config.data["NUM2"].content;
                    }
                    if(host.config.data["NUM2"][host.config.curLang]) {
                        return host.config.data["NUM2"][host.config.curLang].content || host.config.data["NUM2"].content;
                    }
                    return host.config.data["NUM2"].content;
                case Tools.MODE_PASSWORD:
                    /*if(host.config.curLang == "MYA") {
                        return (host.config.data[host.config.curLang][host.config.myaPageNum] || host.config.data[host.config.curLang]).content;
                        break;
                    }*/
                    if(this.shiftMode || this.capsMode) {
                        return host.config.data[host.config.curLang].upper.content;
                    }
		    return host.config.data[host.config.curLang].content;
                    //return host.config.data["ENG"].content;
            }
        };

        IQQIButtonPanel.prototype.releaseFocus = function() {
            setFocus(this, -1, -1);
        };

        IQQIButtonPanel.prototype.gainFocus = function() {
            host.logger.i("iqqi", "IQQIButtonPanel.prototype.gainFocus.DI1210", "lastFocusRow: " + this.lastFocusRow + "; lastFocusCol: " + this.lastFocusCol);
            if(!!host.iqqi.imagineUl && host.iqqi.imagineUl.working) {
                setFocus(this, 0, 0);
            }
            else if(host.iqqi.lastFocus == host.iqqi.lanSwitch || host.iqqi.lastFocus == host.iqqi.charPanel) {
                setFocus(this, this.lastFocusRow, this.lastFocusCol);
            }
            else {
                var row = 5;
                for(var col = 14; col >= 0; col--) {
                    var dom = document.getElementById(this.html.children[row].children[col].id);
                    if(!!dom) {
                        if(/.*gone$/gm.test(dom.className)) {
                            continue;
                        }
                        setFocus(this, row, col);
                        return;
                    }
                }
            }
        };

        IQQIButtonPanel.prototype.rewriteDataOnly = function() {
            this.content = this.getContent();
            for(var row = 0; row < 6; row++) {
                for(var col = 0; col < 15; col++) {
                    if(!!this.content[host.config.rows[row]] && this.content[host.config.rows[row]].length > col) {
                        host.logger.i("iqqi", "IQQIButtonPanel.rewriteDataOnly", "show id: " + this.html.children[row].children[col].id + "; new content: " + this.content[host.config.rows[row]][col]);
                        var dom = document.getElementById(this.html.children[row].children[col].id);
                        dom.innerHTML = this.content[host.config.rows[row]][col] || "";
                    }
                }
            }
        };

        IQQIButtonPanel.prototype.dispatchMessage = function(message) {
            switch(message.what) {
                case host.constants.MSG_REMOTE_NUMBER_KEY_EVENT:
                    onRemoteNumberKey(this, message.which);
                    break;
            }
        };

        IQQIButtonPanel.prototype.decideShiftCaps = function() {
            if(host.config.curMode == Tools.MODE_NUM1 || host.config.curMode == Tools.MODE_NUM2) {
                return undefined;
            }

            if(host.tools.assertLanguageShift(host.config.curLang)) {
                if(this.capsMode) {
                    shiftToCapsIQQI();
                    return "caps";
                }
                else if(this.shiftMode) {
                    shiftToShiftIQQI();
                    return "shift";
                }
                else {
                    return "normal";
                }
            }

            return undefined;
        };

        function onKeyDownDown(self) {
            var inner = {};
            inner.from = document.getElementById(self.html.children[self.focusRow].children[self.focusCol].id);
            if(!!inner.from) {
                inner.rect = inner.from.getBoundingClientRect();
                inner.found = false;
                inner.row = self.focusRow;
                while(inner.found == false) {
                    inner.row = (inner.row + 1) % 6;
                    inner.col = self.focusCol;
                    if(inner.col == 0) {
                        inner.target = document.getElementById(self.html.children[inner.row].children[inner.col].id);
                        if(!!inner.target) {
                            host.logger.i("iqqi", "IQQIButtonPanel.onKeyDownDown", "show match: " + (/[^\s]+?gone/g.test(inner.target.className)) + "; and className: " + inner.target.className);
                            if(/[^\s]+?gone/g.test(inner.target.className)) {
                                continue;
                            }
                            inner.found = true;
                            break;
                        }
                    }
                    else {
                        for(inner.col = 0; inner.col < 15; inner.col++) {
                            host.logger.i("iqqi", "IQQIButtonPanel.onKeyDownDown", "show row: " + inner.row + "; col: " + inner.col);
                            inner.target = document.getElementById(self.html.children[inner.row].children[inner.col].id);
                            if(!!inner.target) {
                                host.logger.i("iqqi", "IQQIButtonPanel.onKeyDownDown", "show match: " + (/[^\s]+?gone/g.test(inner.target.className)) + "; and className: " + inner.target.className);
                                if(/[^\s]+?gone/g.test(inner.target.className)) {
                                    break;
                                }
                                inner.trect = inner.target.getBoundingClientRect();
                                if(inner.rect.left >= (inner.trect.left - 40) && inner.rect.left <= inner.trect.right) {
                                    host.logger.i("iqqi", "IQQIButtonPanel.onKeyDownDown", "show target row: " + inner.row + "; col: " + inner.col);
                                    inner.found = true;
                                    break;
                                }
                            }
                        }
                    }
                }
                if(inner.found) {
                    setFocus(self, inner.row, inner.col);
                }
            }
            return true;
        }

        function onKeyUpDown(self) {
            if(self.focusRow == 0) {
                return false;
            }
            var inner = {};
            inner.from = document.getElementById(self.html.children[self.focusRow].children[self.focusCol].id);
            if(!!inner.from) {
                inner.rect = inner.from.getBoundingClientRect();
                inner.row = self.focusRow;
                inner.found = false;
                while(inner.found == false) {
                    if(inner.row == 0) {
                        return false;
                    }
                    inner.row--;
                    inner.col = self.focusCol;
                    if(inner.col == 0) {
                        inner.target = document.getElementById(self.html.children[inner.row].children[inner.col].id);
                        if(!!inner.target) {
                            host.logger.i("iqqi", "IQQIButtonPanel.onKeyUpDown", "show match: " + (/[^\s]+?gone/g.test(inner.target.className)) + "; and className: " + inner.target.className);
                            if(/[^\s]+?gone/g.test(inner.target.className)) {
                                continue;
                            }
                            inner.found = true;
                            break;
                        }
                    }
                    else {
                        for(inner.col = 0; inner.col < 15; inner.col++) {
                            host.logger.i("iqqi", "IQQIButtonPanel.onKeyDownDown", "show row: " + inner.row + "; col: " + inner.col);
                            inner.target = document.getElementById(self.html.children[inner.row].children[inner.col].id);
                            if(!!inner.target) {
                                host.logger.i("iqqi", "IQQIButtonPanel.onKeyDownDown", "show match: " + (/[^\s]+?gone/g.test(inner.target.className)) + "; and className: " + inner.target.className);
                                if(/[^\s]+?gone/g.test(inner.target.className)) {
                                    break;
                                }
                                inner.trect = inner.target.getBoundingClientRect();
                                if(inner.rect.left >= inner.trect.left && inner.rect.left <= inner.trect.right) {
                                    host.logger.i("iqqi", "IQQIButtonPanel.onKeyDownDown", "show target row: " + inner.row + "; col: " + inner.col);
                                    inner.found = true;
                                    break;
                                }
                            }
                        }
                    }
                }
                if(inner.found) {
                    setFocus(self, inner.row, inner.col);
                }
            }
            return true;
        }

        function onKeyRightDown(self) {
            var col = (self.focusCol + 1) % 15;
            var element = document.getElementById(self.html.children[self.focusRow].children[col].id);
            if(!element) {
                return true;
            }
            if(/[^ ]+?gone/g.test(element.className)) {
                col = 0;
            }
            setFocus(self, self.focusRow, col);
            return true;
        }

        function onKeyLeftDown(self) {
            var col = self.focusCol - 1;
            if(col < 0) {
                col = 14;
            }
            for(;col >= 0; col--) {
                var element = document.getElementById(self.html.children[self.focusRow].children[col].id);
                if(!element) {
                    return true;
                }
                if(/[^ ]+?gone/g.test(element.className) == false) {
                    break;
                }
            }
            setFocus(self, self.focusRow, col);
            return true;
        }

        function setFocus(self, row, col) {
            if(self.focusRow + 1 > 0 && self.focusCol + 1 > 0) {
                self.html.children[self.focusRow].children[self.focusCol].state = "normal";
                var oldFocus = document.getElementById(self.html.children[self.focusRow].children[self.focusCol].id);
                if(!!oldFocus) {
                    oldFocus.className = host.tools.classmaker.call(self, self.html.children[self.focusRow].children[self.focusCol]);
                }

                self.lastFocusRow = self.focusRow > -1 && self.focusRow;
                self.lastFocusCol = self.focusCol > -1 && self.focusCol;
            }

            self.focusRow = row;
            self.focusCol = col;
            if(row == -1 || col == -1) {
                return;
            }
            self.html.children[self.focusRow].children[self.focusCol].state = "focus";
            var newFocus = document.getElementById(self.html.children[self.focusRow].children[self.focusCol].id);
            if(!!newFocus) {
                newFocus.className = host.tools.classmaker.call(self, self.html.children[self.focusRow].children[self.focusCol]);
            }

            if (!!oldFocus && !!newFocus) {
                var shiftIQQIArray = ["rus_shift_new12_shift_presto_1080P_focus", "rus_shift_new12_shift_presto_1080P_normal", "rus_shift_new12_caps_presto_1080P_focus", "rus_shift_new12_caps_presto_1080P_normal", "rus_shift_new12_normal_presto_1080P_focus", "rus_shift_new12_normal_presto_1080P_normal", "eng_shift_new_shift_presto_1080P_focus", "eng_shift_new_shift_presto_1080P_normal", "eng_shift_new_caps_presto_1080P_focus", "eng_shift_new_caps_presto_1080P_normal", "eng_shift_new_normal_presto_1080P_focus", "eng_shift_new_normal_presto_1080P_normal"];
                //var shiftIQQICapsArray = ["rus_shift_new12_caps_presto_1080P_focus", "rus_shift_new12_caps_presto_1080P_normal"];

                if (shiftIQQIArray.indexOf(oldFocus.className) > -1 || shiftIQQIArray.indexOf(newFocus.className) > -1) {
                    if (!!self.shiftMode && !self.capsMode) {

                        shiftToShiftIQQI(host.config.curLang);

                    }
                    if (!!self.capsMode && !self.shiftMode) {
                        shiftToCapsIQQI(host.config.curLang);

                    }

                }

                /*if (shiftIQQICapsArray.indexOf(oldFocus.className) > -1 || shiftIQQICapsArray.indexOf(newFocus.className) > -1) {
                    if (!!self.capsMode) {
                        $(".rus_shift_new12_normal_presto_1080P_normal").addClass("rus_shift_new12_shift_presto_1080P_normal");
                        $(".rus_shift_new12_normal_presto_1080P_normal").removeClass("rus_shift_new12_normal_presto_1080P_normal");
                        $(".rus_shift_new12_normal_presto_1080P_focus").addClass("rus_shift_new12_shift_presto_1080P_focus");
                        $(".rus_shift_new12_normal_presto_1080P_focus").removeClass("rus_shift_new12_normal_presto_1080P_focus");
                    }
                }*/
            }
        }

        /**
         * dispatch enter event in button panel
         * @param self
         * @param {Number} row
         * @param {Number} col
         */
        function dispatchEnterDown(self, row, col) {
            host.logger.i("iqqi", "IQQIButtonPanel.dispatchEnterDown", "show row: " + row + "; col: " + col);
            //if(row < 0) return;
            switch(self.display[host.config.rows[row]][col]) {
                case host.iqqi.input.IQQI_RESPONSE_TYPE_WORD:
                    responseToWordButton(self, row, col);
                    break;
                case host.iqqi.input.IQQI_RESPONSE_TYPE_SOUND_LEVEL:
                    responseToUncertainChar(self, row, col);
                    break;
                case host.iqqi.input.IQQI_RESPONSE_TYPE_NUM:
                    responseToNumButton(self, row, col);
                    break;
                case host.iqqi.input.IQQI_RESPONSE_TYPE_SYMBOL:
                    responseToPuncButton(self, row, col);
                    break;
                case host.iqqi.input.IQQI_RESPONSE_TYPE_WHITESPACE:
                    responseToWhiteButton(self);
                    break;
                case host.iqqi.input.IQQI_RESPONSE_TYPE_BACKSPACE:
                    self.responseToBackButton(self);
                    break;
                case host.iqqi.input.IQQI_RESPONSE_TYPE_SHIFT:
                    responseToShiftButton(self);
                    break;
                case host.iqqi.input.IQQI_RESPONSE_TYPE_MYA_SCROLL:
                    responseToMyaScrollButton(self, row, col);
                    break;
                case host.iqqi.input.IQQI_RESPONSE_TYPE_ENTER:
                    if(responseToEnterButton(self)) {
                        return;
                    }
                    break;
                case host.iqqi.input.IQQI_RESPONSE_TYPE_NUMSWITCH:
                    responseToNumSwitchButton(self, row, col);
                    return;
                case host.iqqi.input.IQQI_RESPONSE_TYPE_LANSWITCH:
                    responseToLanSwitchButton(self, row, col);
                    return;
                case host.iqqi.input.IQQI_RESPONSE_TYPE_ESC:
                    responseToEscButton(self);
                    return;
                case host.iqqi.input.IQQI_RESPONSE_TYPE_SYMBOL_SHIFT:
                    responseToCharSwitchButton(self, row, col);
                    //todo shift down
                    return;

            }
            if(self.display[host.config.rows[row]][col] == host.iqqi.input.IQQI_RESPONSE_TYPE_SHIFT) {
                return;
            }
            if(self.shiftMode) {
                self.shiftMode = false;
                var changeIQQIShiftFlagNormal = false;
                var changeIQQIShiftFlagFocus = false;
                changeIQQIShiftFunc(changeIQQIShiftFlagNormal, changeIQQIShiftFlagFocus, self.shiftMode, self.capsMode, host.config.curLang);
                self.rewriteDataOnly();
                self.setState(self.html.children[3].children[0].id, "normal");
            }
        }

        /**
         * response to word button
         * @param {IQQIButtonPanel} self
         * @param {Number} row
         * @param {Number} col
         */
        function responseToWordButton(self, row, col) {
            self.currentImagineRoot += self.content[host.config.rows[row]][col];
            try {
                if(host.tv) {                
                    if("password" == host.config.workType) {
                    //if(host.config.curMode == Tools.MODE_PASSWORD) {
                        host.iqqi.input.insertValue(self.currentImagineRoot);
                        self.currentImagineRoot = "";
                        self.lastDisplay = [];
                    }
                    else {
                        if(self.currentImagineRoot.length >= 19) {
                            host.iqqi.input.insertValue(self.currentImagineRoot);
                            self.currentImagineRoot = "";
                            self.lastDisplay = [];
                            host.iqqi.imagineUl.hideUl();
                            return;
                        }
                        host.iqqi.imagineUl.currentImagineCount = host.native.IQQINativeGetCandidateCount(self.currentImagineRoot, host.config.curImeType, host.config.curImeFirst, self.getType);
                        host.logger.i("iqqi", "IQQIButtonPanel.responseToWordButton", "show count: " + host.iqqi.imagineUl.currentImagineCount);
                        if(host.iqqi.imagineUl.currentImagineCount == 0 || host.iqqi.imagineUl.currentImagineCount == -1) {
                            host.iqqi.imagineUl.setImagineData([self.currentImagineRoot], 0);
                            self.lastDisplay.push(self.display[host.config.rows[row]][col]);
                            host.iqqi.imagineUl.showUl();
                            return;
                        }
                        host.iqqi.imagineUl.setImagineData(host.native.IQQINativeGetCandidates(self.currentImagineRoot, host.config.curImeType, 0, 40 < host.iqqi.imagineUl.currentImagineCount ? 40 : host.iqqi.imagineUl.currentImagineCount, host.config.curImeFirst, self.getType), 0);
                        self.lastDisplay.push(self.display[host.config.rows[row]][col]);
                        host.iqqi.imagineUl.showUl();
                    }
                    return;
                }
            }
            catch(ex) {
                host.logger.e("iqqi", "IQQIButtonPanel.responseToWordButton", "show error: " + ex, ex);
                return;
            }
            if(host.config.curMode == Tools.MODE_PASSWORD) {
                host.iqqi.input.insertValue(self.currentImagineRoot);
                self.currentImagineRoot = "";
                self.lastDisplay = [];
                return;
            }
            host.iqqi.imagineUl.showUl();
            if(self.currentImagineRoot == "test") {
                host.iqqi.imagineUl.setImagineData(iqqi_imagine_test_data, 0);
                self.lastDisplay.push(self.display[host.config.rows[row]][col]);
                return;
            }
            host.iqqi.imagineUl.setImagineData([self.currentImagineRoot], 0);
            host.logger.i("iqqi", "IQQIButtonPanel.responseToWordButton", "show currentImagineRoot: " + self.currentImagineRoot);
            self.lastDisplay.push(self.display[host.config.rows[row]][col]);
        }

        /**
         * this method was designed for chinese sound level, can not guarantee any other character's response is anything close to right.
         * @param {IQQIButtonPanel} self
         * @param {Number} row
         * @param {Number} col
         */
        function responseToUncertainChar(self, row, col) {
            if(!!self.currentImagineRoot) {
                var newRoot = self.currentImagineRoot + self.content[host.config.rows[row]][col];
                if(newRoot >= 19) {
                    host.iqqi.input.insertValue(newRoot);
                    self.currentImagineRoot = "";
                    self.lastDisplay = [];
                    host.iqqi.imagineUl.hideUl();
                    return;
                }
                var newCount = host.native.IQQINativeGetCandidateCount(newRoot, host.config.curImeType, host.config.curImeFirst, self.getType);
                if(0 >= newCount) {
                    host.logger.i("iqqi", "IQQIButtonPanel.responseToUncertainChar", "detect new count is 0,  abandon the uncertain input, show it: " + self.content[host.config.rows[row]][col] + "; row: " + row + "; col: " + col);
                    return;
                }

                var new_first_40_str = host.native.IQQINativeGetCandidates(newRoot, host.config.curImeType, 0, 40 < host.iqqi.imagineUl.currentImagineCount ? 40 : host.iqqi.imagineUl.currentImagineCount, host.config.curImeFirst, self.getType).join("");
                var old_count = host.native.IQQINativeGetCandidateCount(self.currentImagineRoot, host.config.curImeType, host.config.curImeFirst, self.getType);
                var old_first_40_str = host.native.IQQINativeGetCandidates(self.currentImagineRoot, host.config.curImeType, 0, 40 < host.iqqi.imagineUl.currentImagineCount ? 40 : host.iqqi.imagineUl.currentImagineCount, host.config.curImeFirst, self.getType).join("");

                if(old_count == newCount && old_first_40_str == new_first_40_str) {
                    host.logger.i("iqqi", "IQQIButtonPanel.responseToUncertainChar", "count and first 40 is exactly same, ignore this uncertain input: " + self.content[host.config.rows[row]][col] + "; row: " + row + "; col: " + col);
                    return;
                }

                self.currentImagineRoot += self.content[host.config.rows[row]][col];
                host.iqqi.imagineUl.currentImagineCount = host.native.IQQINativeGetCandidateCount(self.currentImagineRoot, host.config.curImeType, host.config.curImeFirst, self.getType);
                if(host.iqqi.imagineUl.currentImagineCount == 0 || host.iqqi.imagineUl.currentImagineCount == -1) {
                    host.iqqi.imagineUl.setImagineData([self.currentImagineRoot], 0);
                    self.lastDisplay.push(self.display[host.config.rows[row]][col]);
                    host.iqqi.imagineUl.showUl();
                    return;
                }
                host.iqqi.imagineUl.setImagineData(host.native.IQQINativeGetCandidates(self.currentImagineRoot, host.config.curImeType, 0, 40 < host.iqqi.imagineUl.currentImagineCount ? 40 : host.iqqi.imagineUl.currentImagineCount, host.config.curImeFirst, self.getType), 0);
                self.lastDisplay.push(self.display[host.config.rows[row]][col]);
                host.iqqi.imagineUl.showUl();
                return;
            }
            host.iqqi.input.insertValue(self.content[host.config.rows[row]][col]);
            self.lastDisplay = [];
        }
        /**
         * response to num button
         * @param {IQQIButtonPanel} self
         * @param {Number} row
         * @param {Number} col
         */
        function responseToNumButton(self, row, col) {
            var value = self.content[host.config.rows[row]][col];
            if(!!self.currentImagineRoot) {
                value = self.currentImagineRoot + value;
                self.currentImagineRoot = "";
                host.iqqi.imagineUl.hideUl();
            }
            host.iqqi.input.insertValue(value);
            self.lastDisplay = [];
        }

        /**
         * response to punc button
         * @param {IQQIButtonPanel} self
         * @param {Number} row
         * @param {Number} col
         */
        function responseToPuncButton(self, row, col) {
            var value = self.content[host.config.rows[row]][col];
            if(!!self.currentImagineRoot) {
                value = self.currentImagineRoot + value;
                self.currentImagineRoot = "";
                host.iqqi.imagineUl.hideUl();
            }
            host.iqqi.input.insertValue(value);
            self.lastDisplay = [];
        }

        function responseToWhiteButton(self) {
            var value = " ";
            if(!!self.currentImagineRoot) {
                value = self.currentImagineRoot + value;
                self.currentImagineRoot = "";
                host.iqqi.imagineUl.hideUl();
            }
            host.iqqi.input.insertValue(value);
            self.lastDisplay = [];
        }


        /**
         * response to shift button.
         * @param self
         */
        function responseToShiftButton(self) {
            if(self.capsMode) {
                self.capsMode = false;
            }
            else if(self.shiftMode == false) {
                self.shiftMode = true;
            }
            else {
                self.shiftMode = false;
                self.capsMode = true;
                self.setState(self.html.children[3].children[0].id, self.html.children[3].children[0].state);
                var changeIQQIShiftFlagNormal = false;
                var changeIQQIShiftFlagFocus = false;
                changeIQQIShiftFunc(changeIQQIShiftFlagNormal, changeIQQIShiftFlagFocus, self.shiftMode, self.capsMode, host.config.curLang);
                return;
            }

            if(host.config.curLang  == "THA" || host.config.curLang  == "FRA" || host.config.curLang == "SPA" || host.config.curLang == "ARA") {
                self.setLanAndMode(host.config.curLang, host.config.curMode);
                setFocus(self, 3, 0);
                return;
            }

            self.rewriteDataOnly();

            var changeIQQIShiftFlagNormal = false;
            var changeIQQIShiftFlagFocus = false;
            changeIQQIShiftFunc(changeIQQIShiftFlagNormal, changeIQQIShiftFlagFocus, self.shiftMode, self.capsMode, host.config.curLang);

            self.setState(self.html.children[3].children[0].id, self.html.children[3].children[0].state);
        }

        /**
         * response to mya scroll button. only enabled in mya language.
         * @param {IQQIButtonPanel} self
         * @param {Number} row
         * @param {Number} col
         */
        function responseToMyaScrollButton(self, row, col) {
            switch(self.content[host.config.rows[row]][col]) {
                case "က":
                    delete host.config.myaPageNum;
                    break;
                case "ခ":
                    host.config.myaPageNum = "second";
                    break;
                case "ဂ":
                    host.config.myaPageNum = "third";
                    break;
                case "၁၂":
                    host.config.myaPageNum = "fourth";
                    break;
            }
            self.setLanAndMode(host.config.curLang, host.config.curMode);
        }

        /**
         * response to enter button.
         * @param {IQQIButtonPanel} self
         */
        function responseToEnterButton(self) {
            if(!!self.currentImagineRoot) {
                host.iqqi.input.insertValue(self.currentImagineRoot);
                if(!!host.tv && !!host.config.curImeFirst) {
                    host.native.IQQINativeLearnWord(host.config.curImeType, self.currentImagineRoot, self.currentImagineRoot);
                }
                self.currentImagineRoot = "";
                host.iqqi.imagineUl.hideUl();
                return false;
            }
            host.iqqi.input.onExit();
            host.iqqi.hide();
            if(!!host.iqqi.charPanel) {
                host.iqqi.charPanel.hide();
            }
            return true;
        }

        /**
         * response to num switch button
         * @param {IQQIButtonPanel} self
         * @param {Number} row
         * @param {Number} col
         */
        function responseToNumSwitchButton(self, row, col) {
            if("123" == self.html.children[row].children[col].content) {
                self.setLanAndMode(host.config.curLang, Tools.MODE_NUM1);
            }
            else if("1/2" == self.html.children[row].children[col].content) {
                self.setLanAndMode(host.config.curLang, Tools.MODE_NUM2);
            }
            else if("2/2" == self.html.children[row].children[col].content) {
                self.setLanAndMode(host.config.curLang, Tools.MODE_NUM1);
            }
        }

        /**
         * response to lan switch button
         * @param {IQQIButtonPanel} self
         * @param {Number} row
         * @param {Number} col
         */
        function responseToLanSwitchButton(self, row, col) {
            host.logger.i("iqqi", "IQQIButtonPanel.responseToLanSwitchButton", "show row: " + row + "; col: " + col);
            if("ABC" == self.html.children[row].children[col].content) {
                if("password" == host.config.workType) {
                //if(host.config.curMode == Tools.MODE_PASSWORD) {
                    self.setLanAndMode(host.config.curLang, Tools.MODE_PASSWORD);
		    //self.setLanAndMode("ENG", Tools.MODE_PASSWORD);
                    return;
                }
                self.setLanAndMode(host.config.curLang, Tools.MODE_LANGUAGE);
            }
            else {
                if("password" == host.config.workType) {
                //if(host.config.curMode == Tools.MODE_PASSWORD) {
                   // return;
                }
                host.iqqi.switchFocus(host.iqqi.lanSwitch);
                host.iqqi.lanSwitch.setLans(host.tools.getLanguageList());
                host.iqqi.lanSwitch.show();
            }
        }

        /**
         * response to lan switch button
         * @param {IQQIButtonPanel} self
         * @param {Number} row
         * @param {Number} col
         */
        function responseToCharSwitchButton(self, row, col) {
            host.logger.i("iqqi", "IQQIButtonPanel.responseToCharSwitchButton", "show row: " + row + "; col: " + col);
            if("ABC" == self.html.children[row].children[col].content) {
                if("password" == host.config.workType) {
                    //if(host.config.curMode == Tools.MODE_PASSWORD) {
                    self.setLanAndMode(host.config.curLang, Tools.MODE_PASSWORD);
                    //self.setLanAndMode("ENG", Tools.MODE_PASSWORD);
                    return;
                }
                self.setLanAndMode(host.config.curLang, Tools.MODE_LANGUAGE);
            }
            else {
                if("password" == host.config.workType) {
                    //if(host.config.curMode == Tools.MODE_PASSWORD) {
                    // return;
                }
                if (typeof IQQICharPanel.initialized == "undefined" || IQQICharPanel.initialized == false) {
                    host.iqqi.charPanel = new IQQICharPanel("iqqi_char_panel", html_iqqi_char_panel, host.config.curLang, host.config.curMode);
                }
                host.iqqi.switchFocus(host.iqqi.charPanel);
                host.iqqi.charPanel.show();
                host.iqqi.charPanel.rewriteDataOnly();
            }
        }

        /**
         * response to esc button
         * @param {IQQIButtonPanel} self
         */
        function responseToEscButton(self) {
            self.currentImagineRoot = "";
            host.iqqi.input.onExit();
            if (!!host.iqqi.charPanel) {
                host.iqqi.charPanel.hide()
            }
            host.iqqi.hide();
        }

        /**
         * response to back button
         * @param {IQQIButtonPanel} self
         */
        IQQIButtonPanel.prototype.responseToBackButton = function(self) {
        //function responseToBackButton(self) {
            if(!!self.currentImagineRoot) {
                self.currentImagineRoot = self.currentImagineRoot.slice(0, -1);
                if(!!self.currentImagineRoot) {
                    if(host.tv) {
                        self.lastDisplay.pop();
                        host.iqqi.imagineUl.currentImagineCount = host.native.IQQINativeGetCandidateCount(self.currentImagineRoot, host.config.curImeType, host.config.curImeFirst, self.getType);
                        host.iqqi.imagineUl.setImagineData(host.native.IQQINativeGetCandidates(self.currentImagineRoot, host.imeType, 0, 40, true, self.getType), 0);
                        if(host.iqqi.imagineUl.currentImagineCount == 0 || host.iqqi.imagineUl.currentImagineCount == -1) {
                            host.iqqi.imagineUl.setImagineData([self.currentImagineRoot], 0);
                            return;
                        }
                        host.iqqi.imagineUl.setImagineData(host.native.IQQINativeGetCandidates(self.currentImagineRoot, host.config.curImeType, 0, 40 < host.iqqi.imagineUl.currentImagineCount ? 40 : host.iqqi.imagineUl.currentImagineCount, host.config.curImeFirst, self.getType), 0);
                        return;
                    }
                    if(self.currentImagineRoot == "test") {
                        host.iqqi.imagineUl.setImagineData(iqqi_imagine_test_data, 0);
                        self.lastDisplay.pop();
                        return;
                    }
                    host.iqqi.imagineUl.setImagineData([self.currentImagineRoot], 0);
                    self.lastDisplay.pop();
                    return;
                }
                host.iqqi.imagineUl.hideUl();
                return;
            }
            host.iqqi.input.executeBackSpace();
        }

        function responseToUnknownButton(self, char) {
            if(char == null || char == "" || char.charCodeAt(0) == 8){  //For: backspace输入口字符bug
                DBG_ERROR("invalid character ");
                return;
            }
            var value = char;
            if(!!self.currentImagineRoot) {
                value = self.currentImagineRoot + char;
                self.currentImagineRoot = "";
                host.iqqi.imagineUl.hideUl();
            }
            if(value != null && value != ""){
                host.iqqi.input.insertValue(value);
            }
            self.lastDisplay = [];
        }

        function adaptTTFForLan(lan) {
            switch(lan) {
                case "MYA":
                    adaptTTFForLan.fontFamily = "my_Myanmar_Font";
                    break;
                case "HIN":
                    adaptTTFForLan.fontFamily = "my_Hindi_Font";
                    break;
                case "THA":
                    adaptTTFForLan.fontFamily = "my_Thai_Font";
                    break;
                //case "FAS":
                //    IQQIConfig.fontFamily = "my_Persian_Font";
                //    break;
                //case "ARA":
                //    IQQIConfig.fontFamily = "my_Arabic_Font";
                //    break;
                //case "CHI":
                //    IQQIConfig.fontFamily = "my_zh_CN_Font";
                //    break;
                //case "ZHO":
                //    IQQIConfig.fontFamily = "my_zh_TW_Font";
                //    break;
                default:
                    adaptTTFForLan.fontFamily = "myFirstFont";
                    break;
            }
            if(adaptTTFForLan.fontFamily == document.body.style.fontFamily) {
                host.logger.i("iqqi", "IQQIConfig.IQQIConfigAdaptTTFForLan", "same font-family, nothing to be done.");
                return;
            }
            document.body.style.fontFamily = adaptTTFForLan.fontFamily;
        }

        function assertRowAndColOfChar(self, char) {
            for(var key in self.content) {
                if(self.content.hasOwnProperty(key)) {
                    for(var i = 0; i < self.content[key]; ++i) {
                        if(self.content[key][i] == char) {
                            return {"row" :host.config.rows.indexOf(key), "col": i};
                        }
                    }
                }
            }
            return {"row": -1, "col": -1};
        }

        function onRemoteNumberKey(self, which) {
            if(host.config.curLang == "NUM1" || host.config.curLang == "NUM2") {
                onRemoteNumberKey.number = host.config.data.ENG.numbers[which - 48];
                onRemoteNumberKey.position = assertRowAndColOfChar(self, onRemoteNumberKey.number);
            }
            else if(host.config.curMode == Tools.MODE_PASSWORD || host.config.curMode == Tools.MODE_NUMBER_PASSWORD || host.config.curMode == Tools.MODE_NUM1 || host.config.curMode == Tools.MODE_NUM2) {
                onRemoteNumberKey.number = String.fromCharCode(which);
                onRemoteNumberKey.position = assertRowAndColOfChar(self, onRemoteNumberKey.number);
            }
            else {
                //var numbers = host.config.data[host.config.curLang].numbers || host.config.data.ENG.numbers;
                onRemoteNumberKey.number = String.fromCharCode(which);
                onRemoteNumberKey.position = assertRowAndColOfChar(self, onRemoteNumberKey.number);
            }
            if(onRemoteNumberKey.position.row == -1 || onRemoteNumberKey.position.col == -1) {
                responseToUnknownButton(self, onRemoteNumberKey.number);
                return;
            }
            responseToNumButton(self, onRemoteNumberKey.position.row, onRemoteNumberKey.position.col);
        }
    }
    IQQIButtonPanel.initialized = true;

    this.setLanAndMode(lan, mode);
}

function IQQICharPanel(id, html, lan, mode) {
    IQQIView.call(this, id);
    this.type = "IQQICharPanel";
    this.html = html;

    switch (host.config.curLang) {
        case "FRA":
            this.html.classes = "iqqi_char_panel_fra";
            this.charRowNum = 2;
            this.charColNum = 6;
            break;
        case "HRV":
            this.html.classes = "iqqi_char_panel_hrv";
            this.charRowNum = 1;
            this.charColNum = 5;
            break;
        case "SLK":
            this.html.classes = "iqqi_char_panel_slk";
            this.charRowNum = 2;
            this.charColNum = 4;
            break;
        case "LIT":
            this.html.classes = "iqqi_char_panel_lit";
            this.charRowNum = 2;
            this.charColNum = 5;
            break;
        case "CES":
            this.html.classes = "iqqi_char_panel_ces";
            this.charRowNum = 2;
            this.charColNum = 5;
            break;
    }

    this.focusRow = 0;
    this.focusCol = 0;

    this.currentImagineRoot = "";
    this.imeType = host.tv ? imejs.iqqi.ENGLISH : -1;
    this.getType = host.tv ? host.native.TYPE_CANDIDATE_ALL : 0;
    this.lastDisplay = [];

    if(typeof IQQICharPanel.initialized == "undefined" || IQQICharPanel.initialized == false) {
        IQQICharPanel.prototype.onNodeCreated = function(node) {
            //if(IQQICharPanel.prototype.onNodeCreated.initialized == undefined) {
            if(true) {
                function validLineKey(node) {
                    if(validLineKey.initialized == undefined) {
                        validLineKey.validater = new RegExp("^.+LineChar_\\d+$", "gm");
                        validLineKey.cache = new ltt.api.js.util.Cache("panel_id", 128);
                        validLineKey.initialized = true;
                    }

                    if(!validLineKey.cache.containsKey(node.id)) {
                        validLineKey.cache.cache(node.id, validLineKey.validater.test(node.id));
                    }
                    return validLineKey.cache.get(node.id);
                }

                function findPosition(node) {
                    if(findPosition.initialized == undefined) {
                        findPosition.cache = new ltt.api.js.util.Cache("line_key_position", 128);
                        findPosition.initialized = true;
                    }

                    if(!findPosition.cache.containsKey(node.id)) {
                        findPosition.cache.cache(node.id, {"row": host.config.charRows.indexOf(node.id.split("_")[0]), "col": parseInt(node.id.split("_")[1])});
                    }

                    return findPosition.cache.get(node.id);
                }

                function onPanelEnter() {
                    host.logger.i("iqqi", "IQQICharPanel.prototype.onNodeCreated.onPanelEnter.DI1210", "this.id: " + this.id);
                    host.iqqi.lastFocus = host.iqqi.curFocus;
                    host.iqqi.curFocus = host.iqqi.charPanel;
                }

                function onPanelLeave() {
                    host.logger.i("iqqi", "IQQICharPanel.prototype.onNodeCreated.onPanelLeave.DI1210", "this.id: " + this.id);
                }

                function onLineKeyEnter() {
                    host.logger.i("iqqi", "IQQICharPanel.prototype.onNodeCreated.onLineKeyEnter.DI1210", "this.id: " + this.id);
                    setFocus(host.iqqi.charPanel, findPosition(node).row, findPosition(node).col);
                }

                function onLineKeyLeave() {
                    host.logger.i("iqqi", "IQQICharPanel.prototype.onNodeCreated.onLineKeyLeave.DI1210", "this.id: " + this.id);
                    setFocus(host.iqqi.charPanel, -1, -1);
                }

                function onLineKeyClick() {
                    host.logger.i("iqqi", "IQQICharPanel.prototype.onNodeCreated.onLineKeyClick.DI1210", "this.id: " + this.id);
                    host.iqqi.charPanel.onKeyDown({"which": host.keyevent.VK_ENTER});
                }

                IQQICharPanel.prototype.onNodeCreated.initialized = true;
            }

            if(node.id == this.html.id) {
                node.onmouseenter = onPanelEnter;
                node.onmouseleave = onPanelLeave;
            }
            else if(validLineKey(node)) {
                node.onmouseenter = onLineKeyEnter;
                node.onmouseleave = onLineKeyLeave;
            }

            if(validLineKey(node)) {
                node.onclick = onLineKeyClick;
            }

            if(host.tools.isRunningOnOpera()) {
                if(node.textContent) {
                    node.unselectable = "on";
                }
            }
        };

        IQQICharPanel.prototype.onMainPageStateChange = function(state) {
            if(state == IQQIMainPage.STATE_BACK || state == IQQIMainPage.STATE_EXIT) {
                setFocus(this, -1, -1);
            }
        };

        IQQICharPanel.prototype.setLanAndMode = function(lan, mode) {
            host.logger.i("iqqi", "IQQICharPanel.setLanAndMode", "show lan: " + lan + "; mode: " + mode);
            host.config.curLang = lan;
            host.config.curMode = mode;
            if(!host.config.data[lan]) {
                host.config.curLang = host.config.curLangArray[0];
            }
            adaptTTFForLan(host.config.curLang);
            host.config.curImeType = host.tv ? host.config.ImeDict[host.config.curLang] : -1;
            host.config.curImeFirst = ("CHI" == host.config.curLang || "ZHO" == host.config.curLang) == false;


            this.csses = this.getCsses();
            this.display = this.getDisplay();
            this.content = this.getContent();

            for(var row = 0; row < 4; row++) {
                if (row < this.charRowNum) {
                    this.html.children[row].classes = this.csses.lines[row];
                }
                for(var col = 0; col < 10; col++) {
                    if (row < this.charRowNum && col < this.charColNum) {
                        if(!!this.csses) {
                            var css = this.csses.buttons[host.config.charRows[row]] && this.csses.buttons[host.config.charRows[row]][col];
                            if(!!css) {
                                this.html.children[row].children[col].classes = this.csses.buttons[host.config.charRows[row]][col];
                            }
                        }

                        var type = this.display[host.config.charRows[row]] && this.display[host.config.charRows[row]][col];
                        this.html.children[row].children[col].state = "gone";
                        if(!!type) {
                            this.html.children[row].children[col].state = "normal";
                        }

                        var value = this.content[host.config.charRows[row]] && this.content[host.config.charRows[row]][col];
                        delete this.html.children[row].children[col].content;
                        if(!!value) {
                            this.html.children[row].children[col].content = value;
                        }
                    } else {
                        this.html.children[row].children[col].state = "gone";
                        delete this.html.children[row].children[col].content;
                    }
                }
            }

            this.rewrite();
            setFocus(this, 0, 0);
        };

        IQQICharPanel.prototype.onKeyDown = function(event) {
            switch(event.which) {
                case host.keyevent.VK_DOWN:
                    if (event.keyFrom != "Keyboard") {
                        return onKeyDownDown(this);
                    }
                    return true;
                case host.keyevent.VK_UP:
                    if (event.keyFrom != "Keyboard") {
                        return onKeyUpDown(this);
                    }
                    return true;
                case host.keyevent.VK_RIGHT:
                    if (event.keyFrom != "Keyboard") {
                        if(GLOBAL.RTL)  {
                            return onKeyLeftDown(this);
                        }
                        return onKeyRightDown(this);
                    }

                case host.keyevent.VK_LEFT:
                    if (event.keyFrom != "Keyboard") {
                        if(GLOBAL.RTL)  {
                            return onKeyRightDown(this);
                        }
                        return onKeyLeftDown(this);
                    }

                case host.keyevent.VK_BACK:
                    if (event.keyFrom != "Keyboard") {
                        return onKeyBackDown(this);
                    }
                    return true;
                case host.keyevent.VK_ENTER:
                    //if( this.focusRow < 0) return false;
                    dispatchEnterDown(this, this.focusRow, this.focusCol);
                    return true;
            }
        };

        IQQICharPanel.prototype.getDisplay = function() {
            switch(host.config.curMode) {
                case Tools.MODE_LANGUAGE:
                    /*if(host.config.curLang == "MYA") {
                        return (host.config.data[host.config.curLang][host.config.myaPageNum] || host.config.data[host.config.curLang]).char.display;
                    }*/
                    if(host.iqqi.buttonPanel.shiftMode || host.iqqi.buttonPanel.capsMode) {
                        return host.config.data[host.config.curLang].char.upper.display || host.config.data[host.config.curLang].char.display;
                    }
                    return host.config.data[host.config.curLang].char.display;
                case Tools.MODE_PASSWORD:
                    if(host.iqqi.buttonPanel.shiftMode || host.iqqi.buttonPanel.capsMode) {
                        return host.config.data[host.config.curLang].char.upper.display || host.config.data[host.config.curLang].char.display;
                        //return host.config.data["ENG"].upper.display || host.config.data["ENG"].display;
                    }
                    return host.config.data[host.config.curLang].char.display;
                //return host.config.data["ENG"].display;
            }
        };

        IQQICharPanel.prototype.getCsses = function() {
            var inner = {};
            switch(host.config.curMode) {
                case Tools.MODE_LANGUAGE:
                    /*if(host.config.curLang == "MYA") {
                        if(host.config.data[host.config.curLang][host.config.myaPageNum] && host.config.data[host.config.curLang][host.config.myaPageNum].char.csses) {
                            inner.csses = host.config.data[host.config.curLang][host.config.myaPageNum].char.csses;
                            break;
                        }
                        inner.csses = host.config.data[host.config.curLang].char.csses;
                        break;
                    }*/
                    if(host.iqqi.buttonPanel.shiftMode || host.iqqi.buttonPanel.capsMode) {
                        if(!!host.config.data[host.config.curLang].char.upper.csses) {
                            inner.csses = host.config.data[host.config.curLang].char.upper.csses || host.config.data[host.config.curLang].char.csses;
                            break;
                        }
                    }
                    inner.csses = host.config.data[host.config.curLang].char.csses;
                    break;
                case Tools.MODE_PASSWORD:
                    if(host.iqqi.buttonPanel.shiftMode || host.iqqi.buttonPanel.capsMode) {
                        inner.csses = host.config.data[host.config.curLang].char.upper.csses || host.config.data[host.config.curLang].char.csses;
                        //inner.csses = host.config.data["ENG"].upper.csses || host.config.data["ENG"].csses;
                        break;
                    }
                    inner.csses = host.config.data[host.config.curLang].char.csses;
                    //inner.csses = host.config.data["ENG"].csses;
                    break;
            }
            switch(host.screen) {
                case "720P":
                    return inner.csses["720P"] || inner.csses["1080P"];
                case "1080P":
                    return inner.csses["1080P"] || inner.csses["720P"];
            }
        };

        IQQICharPanel.prototype.getContent = function() {
            switch(host.config.curMode) {
                case Tools.MODE_LANGUAGE:
                    /*if(host.config.curLang == "MYA") {
                        return (host.config.data[host.config.curLang][host.config.myaPageNum] || host.config.data[host.config.curLang]).char.content;
                        break;
                    }*/
                    if(host.iqqi.buttonPanel.shiftMode || host.iqqi.buttonPanel.capsMode) {
                        return host.config.data[host.config.curLang].char.upper.content;
                    }
                    return host.config.data[host.config.curLang].char.content;
                case Tools.MODE_PASSWORD:
                    /*if(host.config.curLang == "MYA") {
                        return (host.config.data[host.config.curLang][host.config.myaPageNum] || host.config.data[host.config.curLang]).char.content;
                        break;
                    }*/
                    if(host.iqqi.buttonPanel.shiftMode || host.iqqi.buttonPanel.capsMode) {
                        return host.config.data[host.config.curLang].char.upper.content;
                    }
                    return host.config.data[host.config.curLang].char.content;
                //return host.config.data["ENG"].content;
            }
        };

        IQQICharPanel.prototype.releaseFocus = function() {
            setFocus(this, -1, -1);
        };

        IQQICharPanel.prototype.gainFocus = function() {
            host.logger.i("iqqi", "IQQICharPanel.prototype.gainFocus.DI1210", "lastFocusRow: " + this.lastFocusRow + "; lastFocusCol: " + this.lastFocusCol);
            if(host.iqqi.lastFocus == host.iqqi.buttonPanel) {
                setFocus(this, this.lastFocusRow, this.lastFocusCol);
            } else {
                setFocus(self, 0, 0)
            }
        };

        IQQICharPanel.prototype.rewriteDataOnly = function() {
            this.content = this.getContent();
            for(var row = 0; row < this.charRowNum; row++) {
                for(var col = 0; col < this.charColNum; col++) {
                    if(!!this.content[host.config.charRows[row]] && this.content[host.config.charRows[row]].length > col) {
                        host.logger.i("iqqi", "IQQICharPanel.rewriteDataOnly", "show id: " + this.html.children[row].children[col].id + "; new ccharontent: " + this.content[host.config.charRows[row]][col]);
                        var dom = document.getElementById(this.html.children[row].children[col].id);
                        dom.innerHTML = this.content[host.config.charRows[row]][col] || "";
                    }
                }
            }
        };

        IQQICharPanel.prototype.dispatchMessage = function(message) {
            switch(message.what) {
                case host.constants.MSG_REMOTE_NUMBER_KEY_EVENT:
                    onRemoteNumberKey(this, message.which);
                    break;
            }
        };

        IQQICharPanel.prototype.decideShiftCaps = function() {
            if(host.config.curMode == Tools.MODE_NUM1 || host.config.curMode == Tools.MODE_NUM2) {
                return undefined;
            }

            if(host.tools.assertLanguageShift(host.config.curLang)) {
                if(host.iqqi.buttonPanel.capsMode) {
                    return "caps";
                }
                else if(host.iqqi.buttonPanel.shiftMode) {
                    return "shift";
                }
                else {
                    return "normal";
                }
            }

            return undefined;
        };

        function onKeyDownDown(self) {
            var inner = {};
            inner.from = document.getElementById(self.html.children[self.focusRow].children[self.focusCol].id);
            if(!!inner.from) {
                inner.rect = inner.from.getBoundingClientRect();
                inner.found = false;
                inner.row = self.focusRow;
                while(inner.found == false) {
                    inner.row = (inner.row + 1) % self.charRowNum;
                    inner.col = self.focusCol;
                    if(inner.col == 0) {
                        inner.target = document.getElementById(self.html.children[inner.row].children[inner.col].id);
                        if(!!inner.target) {
                            host.logger.i("iqqi", "IQQICharPanel.onKeyDownDown", "show match: " + (/[^\s]+?gone/g.test(inner.target.className)) + "; and className: " + inner.target.className);
                            if(/[^\s]+?gone/g.test(inner.target.className)) {
                                continue;
                            }
                            inner.found = true;
                            break;
                        }
                    }
                    else {
                        for(inner.col = 0; inner.col < self.charColNum; inner.col++) {
                            host.logger.i("iqqi", "IQQICharPanel.onKeyDownDown", "show row: " + inner.row + "; col: " + inner.col);
                            inner.target = document.getElementById(self.html.children[inner.row].children[inner.col].id);
                            if(!!inner.target) {
                                host.logger.i("iqqi", "IQQICharPanel.onKeyDownDown", "show match: " + (/[^\s]+?gone/g.test(inner.target.className)) + "; and className: " + inner.target.className);
                                if(/[^\s]+?gone/g.test(inner.target.className)) {
                                    break;
                                }
                                inner.trect = inner.target.getBoundingClientRect();
                                if(inner.rect.left >= (inner.trect.left - 40) && inner.rect.left <= inner.trect.right) {
                                    host.logger.i("iqqi", "IQQICharPanel.onKeyDownDown", "show target row: " + inner.row + "; col: " + inner.col);
                                    inner.found = true;
                                    break;
                                }
                            }
                        }
                    }
                }
                if(inner.found) {
                    setFocus(self, inner.row, inner.col);
                }
            }
            return true;
        }

        function onKeyUpDown(self) {
            if(self.focusRow == 0) {
                return false;
            }
            var inner = {};
            inner.from = document.getElementById(self.html.children[self.focusRow].children[self.focusCol].id);
            if(!!inner.from) {
                inner.rect = inner.from.getBoundingClientRect();
                inner.row = self.focusRow;
                inner.found = false;
                while(inner.found == false) {
                    if(inner.row == 0) {
                        return false;
                    }
                    inner.row--;
                    inner.col = self.focusCol;
                    if(inner.col == 0) {
                        inner.target = document.getElementById(self.html.children[inner.row].children[inner.col].id);
                        if(!!inner.target) {
                            host.logger.i("iqqi", "IQQICharPanel.onKeyUpDown", "show match: " + (/[^\s]+?gone/g.test(inner.target.className)) + "; and className: " + inner.target.className);
                            if(/[^\s]+?gone/g.test(inner.target.className)) {
                                continue;
                            }
                            inner.found = true;
                            break;
                        }
                    }
                    else {
                        for(inner.col = 0; inner.col < self.charColNum; inner.col++) {
                            host.logger.i("iqqi", "IQQICharPanel.onKeyDownDown", "show row: " + inner.row + "; col: " + inner.col);
                            inner.target = document.getElementById(self.html.children[inner.row].children[inner.col].id);
                            if(!!inner.target) {
                                host.logger.i("iqqi", "IQQICharPanel.onKeyDownDown", "show match: " + (/[^\s]+?gone/g.test(inner.target.className)) + "; and className: " + inner.target.className);
                                if(/[^\s]+?gone/g.test(inner.target.className)) {
                                    break;
                                }
                                inner.trect = inner.target.getBoundingClientRect();
                                if(inner.rect.left >= inner.trect.left && inner.rect.left <= inner.trect.right) {
                                    host.logger.i("iqqi", "IQQICharPanel.onKeyDownDown", "show target row: " + inner.row + "; col: " + inner.col);
                                    inner.found = true;
                                    break;
                                }
                            }
                        }
                    }
                }
                if(inner.found) {
                    setFocus(self, inner.row, inner.col);
                }
            }
            return true;
        }

        function onKeyRightDown(self) {
            var col = (self.focusCol + 1) % self.charColNum;
            var element = document.getElementById(self.html.children[self.focusRow].children[col].id);
            if(!element) {
                return true;
            }
            if(/[^ ]+?gone/g.test(element.className)) {
                col = 0;
            }
            setFocus(self, self.focusRow, col);
            return true;
        }

        function onKeyLeftDown(self) {
            var col = self.focusCol - 1;
            if(col < 0) {
                col = self.charColNum - 1;
            }
            for(;col >= 0; col--) {
                var element = document.getElementById(self.html.children[self.focusRow].children[col].id);
                if(!element) {
                    return true;
                }
                if(/[^ ]+?gone/g.test(element.className) == false) {
                    break;
                }
            }
            setFocus(self, self.focusRow, col);
            return true;
        }

        function setFocus(self, row, col) {
            if(self.focusRow + 1 > 0 && self.focusCol + 1 > 0) {
                self.html.children[self.focusRow].children[self.focusCol].state = "normal";
                var oldFocus = document.getElementById(self.html.children[self.focusRow].children[self.focusCol].id);
                if(!!oldFocus) {
                    oldFocus.className = host.tools.classmaker.call(self, self.html.children[self.focusRow].children[self.focusCol]);
                }

                self.lastFocusRow = self.focusRow > -1 && self.focusRow;
                self.lastFocusCol = self.focusCol > -1 && self.focusCol;
            }

            self.focusRow = row;
            self.focusCol = col;
            if(row == -1 || col == -1) {
                return;
            }
            self.html.children[self.focusRow].children[self.focusCol].state = "focus";
            var newFocus = document.getElementById(self.html.children[self.focusRow].children[self.focusCol].id);
            if(!!newFocus) {
                newFocus.className = host.tools.classmaker.call(self, self.html.children[self.focusRow].children[self.focusCol]);
            }
        }

        /**
         * dispatch enter event in char panel
         * @param self
         * @param {Number} row
         * @param {Number} col
         */
        function dispatchEnterDown(self, row, col) {
            host.logger.i("iqqi", "IQQICharPanel.dispatchEnterDown", "show row: " + row + "; col: " + col);
            if(row < 0 || col < 0) return;
            responseToWordChar(self, row, col);
            if(self.display[host.config.charRows[row]][col] == host.iqqi.input.IQQI_RESPONSE_TYPE_SHIFT) {
                return;
            }
            if(!host.iqqi.buttonPanel.capsMode) {
                self.rewriteDataOnly();
            }
        }

        function onKeyBackDown(self) {
            self.hide();
            if (!!self.charPanel) {
                self.charPanel.hide();
            }
            self.hide();
            host.iqqi.switchFocus(host.iqqi.buttonPanel);
            return true;
        }

        /**
         * response to word char
         * @param {IQQICharPanel} self
         * @param {Number} row
         * @param {Number} col
         */
        function responseToWordChar(self, row, col) {
            host.iqqi.buttonPanel.currentImagineRoot += self.content[host.config.charRows[row]][col];
            try {
                if(host.tv) {
                    if("password" == host.config.workType) {
                        //if(host.config.curMode == Tools.MODE_PASSWORD) {
                        host.iqqi.input.insertValue(host.iqqi.buttonPanel.currentImagineRoot);
                        host.iqqi.buttonPanel.currentImagineRoot = "";
                        self.lastDisplay = [];
                    }
                    else {
                        if(host.iqqi.buttonPanel.currentImagineRoot.length >= 19) {
                            host.iqqi.input.insertValue(host.iqqi.buttonPanel.currentImagineRoot);
                            host.iqqi.buttonPanel.currentImagineRoot = "";
                            self.lastDisplay = [];
                            host.iqqi.imagineUl.hideUl();
                            return;
                        }
                        host.iqqi.imagineUl.currentImagineCount = host.native.IQQINativeGetCandidateCount(host.iqqi.buttonPanel.currentImagineRoot, host.config.curImeType, host.config.curImeFirst, self.getType);
                        host.logger.i("iqqi", "IQQICharPanel.responseToWordChar", "show count: " + host.iqqi.imagineUl.currentImagineCount);
                        if(host.iqqi.imagineUl.currentImagineCount == 0 || host.iqqi.imagineUl.currentImagineCount == -1) {
                            host.iqqi.imagineUl.setImagineData([host.iqqi.buttonPanel.currentImagineRoot], 0);
                            self.lastDisplay.push(self.display[host.config.rows[row]][col]);
                            host.iqqi.imagineUl.showUl();
                            return;
                        }
                        host.iqqi.imagineUl.setImagineData(host.native.IQQINativeGetCandidates(host.iqqi.buttonPanel.currentImagineRoot, host.config.curImeType, 0, 40 < host.iqqi.imagineUl.currentImagineCount ? 40 : host.iqqi.imagineUl.currentImagineCount, host.config.curImeFirst, self.getType), 0);
                        self.lastDisplay.push(self.display[host.config.rows[row]][col]);
                        host.iqqi.imagineUl.showUl();
                    }
                    return;
                }
            }
            catch(ex) {
                host.logger.e("iqqi", "IQQICharPanel.responseToWordChar", "show error: " + ex, ex);
                return;
            }
            if(host.config.curMode == Tools.MODE_PASSWORD) {
                host.iqqi.input.insertValue(host.iqqi.buttonPanel.currentImagineRoot);
                host.iqqi.buttonPanel.currentImagineRoot = "";
                self.lastDisplay = [];
                return;
            }
            host.iqqi.imagineUl.showUl();
            if(self.currentImagineRoot == "test") {
                host.iqqi.imagineUl.setImagineData(iqqi_imagine_test_data, 0);
                self.lastDisplay.push(self.display[host.config.charRows[row]][col]);
                return;
            }
            host.iqqi.imagineUl.setImagineData([host.iqqi.buttonPanel.currentImagineRoot], 0);
            host.logger.i("iqqi", "IQQICharPanel.responseToWordChar", "show currentImagineRoot: " + host.iqqi.buttonPanel.currentImagineRoot);
            self.lastDisplay.push(self.display[host.config.charRows[row]][col]);
        }

        /**
         * response to num char
         * @param {IQQICharPanel} self
         * @param {Number} row
         * @param {Number} col
         */
        function responseToNumChar(self, row, col) {
            var value = self.content[host.config.rows[row]][col];
            if(!!self.currentImagineRoot) {
                value = self.currentImagineRoot + value;
                self.currentImagineRoot = "";
                host.iqqi.imagineUl.hideUl();
            }
            host.iqqi.input.insertValue(value);
            self.lastDisplay = [];
        }

        function responseToUnknownChar(self, char) {
            var value = char;
            if(!!self.currentImagineRoot) {
                value = self.currentImagineRoot + char;
                self.currentImagineRoot = "";
                host.iqqi.imagineUl.hideUl();
            }
            host.iqqi.input.insertValue(value);
            self.lastDisplay = [];
        }

        function adaptTTFForLan(lan) {
            switch(lan) {
                case "MYA":
                    adaptTTFForLan.fontFamily = "my_Myanmar_Font";
                    break;
                case "HIN":
                    adaptTTFForLan.fontFamily = "my_Hindi_Font";
                    break;
                case "THA":
                    adaptTTFForLan.fontFamily = "my_Thai_Font";
                    break;
                //case "FAS":
                //    IQQIConfig.fontFamily = "my_Persian_Font";
                //    break;
                //case "ARA":
                //    IQQIConfig.fontFamily = "my_Arabic_Font";
                //    break;
                //case "CHI":
                //    IQQIConfig.fontFamily = "my_zh_CN_Font";
                //    break;
                //case "ZHO":
                //    IQQIConfig.fontFamily = "my_zh_TW_Font";
                //    break;
                default:
                    adaptTTFForLan.fontFamily = "myFirstFont";
                    break;
            }
            if(adaptTTFForLan.fontFamily == document.body.style.fontFamily) {
                host.logger.i("iqqi", "IQQIConfig.IQQIConfigAdaptTTFForLan", "same font-family, nothing to be done.");
                return;
            }
            document.body.style.fontFamily = adaptTTFForLan.fontFamily;
        }

        function assertRowAndColOfChar(self, char) {
            for(var key in self.content) {
                if(self.content.hasOwnProperty(key)) {
                    for(var i = 0; i < self.content[key]; ++i) {
                        if(self.content[key][i] == char) {
                            return {"row" :host.config.rows.indexOf(key), "col": i};
                        }
                    }
                }
            }
            return {"row": -1, "col": -1};
        }

        function onRemoteNumberKey(self, which) {
            if(host.config.curLang == "NUM1" || host.config.curLang == "NUM2") {
                onRemoteNumberKey.number = host.config.data.ENG.numbers[which - 48];
                onRemoteNumberKey.position = assertRowAndColOfChar(self, onRemoteNumberKey.number);
            }
            else if(host.config.curMode == Tools.MODE_PASSWORD || host.config.curMode == Tools.MODE_NUMBER_PASSWORD || host.config.curMode == Tools.MODE_NUM1 || host.config.curMode == Tools.MODE_NUM2) {
                onRemoteNumberKey.number = host.config.data.ENG.numbers[which - 48];
                onRemoteNumberKey.position = assertRowAndColOfChar(self, onRemoteNumberKey.number);
            }
            else {
                //var numbers = host.config.data[host.config.curLang].numbers || host.config.data.ENG.numbers;
                onRemoteNumberKey.number = String.fromCharCode(which);
                onRemoteNumberKey.position = assertRowAndColOfChar(self, onRemoteNumberKey.number);
            }
            if(onRemoteNumberKey.position.row == -1 || onRemoteNumberKey.position.col == -1) {
                responseToUnknownChar(self, onRemoteNumberKey.number);
                return;
            }
            responseToNumChar(self, onRemoteNumberKey.position.row, onRemoteNumberKey.position.col);
        }
    }
    IQQICharPanel.initialized = true;

    this.setLanAndMode(lan, mode);
}

function IQQIImagineUl(id, html, item, content, first, divider, data) {
    IQQIView.call(this, html);
    this.type = "IQQIImagineUl";
    this.begin = 0;
    this.end = 0;
    this.working = false;
    this.focusIndex = -1;

    this.item = item;
    this.content = content;
    this.first = first;
    this.divider = divider;

    this.oneLength = host.screen == "720P" ? 1230 : 1850;
    this.twoLength = host.screen == "720P" ? 1180 : 1780;
    this.threeLength = host.screen == "720P" ? 1130 : 1710;

    this.Ferry = [];

    if(typeof IQQIImagineUl.initialized == "undefined") {
        IQQIImagineUl.prototype.onNodeCreated = function(node) {
            if(IQQIImagineUl.prototype.onNodeCreated.initialized == undefined) {
                function onImagineEnter() {
                    host.logger.i("iqqi", "IQQIImagineUl.prototype.onNodeCreated.onImagineEnter.DI1210", "this.id: " + this.id);
                    if(host.iqqi.imagineUl.working) {
                        host.iqqi.switchFocus(host.iqqi.imagineUl, true, false);
                    }
                }

                function onImagineLeave() {
                    host.logger.i("iqqi", "IQQIImagineUl.prototype.onNodeCreated.onImagineLeave.DI1210", "this.id: " + this.id);
                }

                function onArrowEnter() {
                    host.logger.i("iqqi", "IQQIImagineUl.prototype.onNodeCreated.onArrowEnter.DI1210", "this.id: " + this.id);
                }

                function onArrowLeave() {
                    host.logger.i("iqqi", "IQQIImagineUl.prototype.onNodeCreated.onArrowLeave.DI1210", "this.id: " + this.id);
                }

                function onArrowClick() {
                    host.logger.i("iqqi", "IQQIImagineUl.prototype.onNodeCreated.onArrowClick.DI1210", "this.id: " + this.id);

                    if(onArrowClick.initialized == undefined) {
                        function onStartArrowClick() {
                            if(host.iqqi.imagineUl.begin == 0) {
                                return;
                            }
                            host.iqqi.imagineUl.setImagineData(host.iqqi.imagineUl.data, host.iqqi.imagineUl.Ferry.pop());
                        }

                        function onEndArrowClick() {
                            if(ltt.api.js.json.fetchData(window, "imejs.iqqi")) {
                                if(host.iqqi.imagineUl.focusIndex + host.iqqi.imagineUl.begin + 20 + 1 >= host.iqqi.imagineUl.data.length) {
                                    if(host.iqqi.imagineUl.data.length <= host.iqqi.imagineUl.currentImagineCount - 20) {
                                        var results_i = host.native.IQQINativeGetCandidates(host.iqqi.buttonPanel.currentImagineRoot, host.config.curImeType, host.iqqi.imagineUl.data.length, 20, false, host.iqqi.buttonPanel.getType);
                                        for(var i = 0; i < results_i.length; ++i) {
                                            host.iqqi.imagineUl.data.push(results_i[i]);
                                        }
                                    }
                                    else if(host.iqqi.imagineUl.data.length <= host.iqqi.imagineUl.currentImagineCount) {
                                        var results_j = host.native.IQQINativeGetCandidates(host.iqqi.buttonPanel.currentImagineRoot, host.config.curImeType, host.iqqi.imagineUl.data.length, host.iqqi.imagineUl.currentImagineCount - host.iqqi.imagineUl.data.length, false, host.iqqi.buttonPanel.getType);
                                        for(var j = 0; j < results_j.length; ++j) {
                                            host.iqqi.imagineUl.data.push(results_j[j]);
                                        }
                                    }
                                }
                            }

                            host.iqqi.imagineUl.Ferry.push(host.iqqi.imagineUl.begin);
                            host.iqqi.imagineUl.setImagineData(host.iqqi.imagineUl.data, host.iqqi.imagineUl.end);
                        }

                        onArrowClick.initialized = true;
                    }

                    if(host.iqqi.imagineUl.html.children[0].id == this.id) {
                        if(host.tools.assertLanguageRtl(host.config.curLang)) {
                            onEndArrowClick();
                        }
                        else {
                            onStartArrowClick();
                        }
                    }
                    else if(host.iqqi.imagineUl.html.children[2].id == this.id) {
                        if(host.tools.assertLanguageRtl(host.config.curLang)) {
                            onStartArrowClick();
                        }
                        else {
                            onEndArrowClick();
                        }
                    }
                }

                function onItemEnter() {
                    host.logger.i("iqqi", "IQQIImagineUl.prototype.onNodeCreated.onItemEnter.DI1210", "this.id: " + this.id);
                    focusItem(host.iqqi.imagineUl, parseInt(this.id.slice(this.id.lastIndexOf("_") + 1)) - host.iqqi.imagineUl.begin);
                }

                function onItemLeave() {
                    host.logger.i("iqqi", "IQQIImagineUl.prototype.onNodeCreated.onItemLeave.DI1210", "this.id: " + this.id);
                    focusItem(host.iqqi.imagineUl, -1);
                }

                function onItemClick() {
                    host.logger.i("iqqi", "IQQIImagineUl.prototype.onNodeCreated.onItemClick.DI1210", "this.id: " + this.id);
                    host.iqqi.imagineUl.onKeyDown({"which": host.keyevent.VK_ENTER});
                }

                IQQIImagineUl.prototype.onNodeCreated.initialized = true;
            }

            if(node.id == this.html.id) {
                node.onmouseenter = onImagineEnter;
                node.onmouseleave = onImagineLeave;
            }
            else if(node.id == this.html.children[0].id || node.id == this.html.children[2].id) {
                node.onmouseenter = onArrowEnter;
                node.onmouseleave = onArrowLeave;
                node.onclick = onArrowClick;
            }
            else if(/^iqqi_imagine_content_item_\d+$/gm.test(node.id)) {
                node.onmouseenter = onItemEnter;
                node.onmouseleave = onItemLeave;
                node.onclick = onItemClick;
            }

            if(node.textContent) {
                if(host.tools.isRunningOnOpera()) {
                    node.unselectable = "on";
                }
            }
        };

        IQQIImagineUl.prototype.onMainPageStateChange = function(state) {
            if(state == IQQIMainPage.STATE_BACK || state == IQQIMainPage.STATE_EXIT) {
                this.hideUl();
            }
        };

        /**
         * set imagine data of imagine ul.
         * @param {Array} data
         * @param {Number} begin
         */
        IQQIImagineUl.prototype.setImagineData = function(data, begin) {
            this.data = data || [];
            this.html.children[1].children = [];
            this.begin = (begin != undefined && begin) || 0;
            if(this.begin == 0) {
                this.Ferry = [];
            }
            if(!(this.data && this.data.length)) {
                this.hideUl();
                return;
            }
            var ul = document.getElementById(this.html.children[1].id);
            if(!!ul) {
                ul.innerHTML = "";
                if(this.begin > 0) {
                    showLeftArrow(this);
                }
                else {
                    hideLeftArrow(this);         //此处，重点，联想区样式
                }
                adaptArrowStatus(this);
                var elementTotalWidth = 0;
                //var languageCode = window.localStorage["iqqiLanguage"] || this.curLang || host.config.curLangArray[0];
                //var lancode = languageCode;
                //var newlangflag = (iqqi_new_array.indexOf(lancode) > -1);
                if(1) {           //根据不同语言布局，联想区显示单词个数不同
                    for(var i = begin; i < this.data.length; i++) {
                        var newLi = createSingleLi(this, this.data[i], i);
                        ul.appendChild(newLi);
                        var big = elementTotalWidth > (this.begin > 0 ? 1072 : 1004);//按这个大小计算显示个数
                        elementTotalWidth += newLi.scrollWidth;
                        last: if(elementTotalWidth > (this.begin > 0 ? 1140 : 1072)) {//按这个大小计算显示个数
                            if(i == this.data.length - 1 && elementTotalWidth > this.oneLength == false) {
                                host.logger.i("iqqi", "ImagineUl.setImagineData", "show big: " + big + "; begin: " + this.begin + "; one: " + (elementTotalWidth > this.oneLength));
                                break last;
                            }
                            showRightArrow(this);
                            adaptArrowStatus(this);
                            this.end = i;
                            this.html.children[1].children[i - this.begin].state = "normal";
                            host.logger.i("iqqi", "IQQIImagineUl.prototype.setImagineData", "DI1210, show ooop");
                            newLi.className = host.tools.classmaker.call(this, this.html.children[1].children[i - this.begin]);
                            if(this.focusIndex == i - this.begin) {
                                this.html.children[1].children[i - this.begin].children[0].state = "focus";
                            }
                            else {
                                this.html.children[1].children[i - this.begin].children[0].state = "normal";
                            }
                            newLi.firstChild.className = host.tools.classmaker.call(this, this.html.children[1].children[i - this.begin].children[0]);
                            this.html.children[1].children[i - this.begin].children[1].state = "hidden";
                            newLi.lastChild.className = host.tools.classmaker.call(this, this.html.children[1].children[i - this.begin].children[1]);
                            if(big) {
                                this.end = i - 1;
                            }
                            return;
                        }
                        this.html.children[1].children[i - this.begin].state = "normal";

                        newLi.className = host.tools.classmaker.call(this, this.html.children[1].children[i - this.begin]);



                        if(this.focusIndex == i - this.begin) {
                            this.html.children[1].children[i - this.begin].children[0].state = "focus";
                        }
                        else {
                            this.html.children[1].children[i - this.begin].children[0].state = "normal";
                        }
                        newLi.firstChild.className = host.tools.classmaker.call(this, this.html.children[1].children[i - this.begin].children[0]);
                        this.html.children[1].children[i - this.begin].children[1].state = "normal";
                        newLi.lastChild.className = host.tools.classmaker.call(this, this.html.children[1].children[i - this.begin].children[1]);
                        this.end = i;

                    }
                } else {
                    for(var i = begin; i < this.data.length; i++) {
                        var newLi = createSingleLi(this, this.data[i], i);
                        ul.appendChild(newLi);
                        var big = elementTotalWidth > (this.begin > 0 ? this.twoLength : this.oneLength);//按这个大小计算显示个数
                        elementTotalWidth += newLi.scrollWidth;
                        last: if(elementTotalWidth > (this.begin > 0 ? this.threeLength : this.twoLength)) {//按这个大小计算显示个数
                            if(i == this.data.length - 1 && elementTotalWidth > this.oneLength == false) {
                                host.logger.i("iqqi", "ImagineUl.setImagineData", "show big: " + big + "; begin: " + this.begin + "; one: " + (elementTotalWidth > this.oneLength));
                                break last;
                            }
                            showRightArrow(this);
                            adaptArrowStatus(this);
                            this.end = i;
                            this.html.children[1].children[i - this.begin].state = "normal";
                            host.logger.i("iqqi", "IQQIImagineUl.prototype.setImagineData", "DI1210, show ooop");
                            newLi.className = host.tools.classmaker.call(this, this.html.children[1].children[i - this.begin]);
                            if(this.focusIndex == i - this.begin) {
                                this.html.children[1].children[i - this.begin].children[0].state = "focus";
                            }
                            else {
                                this.html.children[1].children[i - this.begin].children[0].state = "normal";
                            }
                            newLi.firstChild.className = host.tools.classmaker.call(this, this.html.children[1].children[i - this.begin].children[0]);
                            this.html.children[1].children[i - this.begin].children[1].state = "hidden";
                            newLi.lastChild.className = host.tools.classmaker.call(this, this.html.children[1].children[i - this.begin].children[1]);
                            if(big) {
                                this.end = i - 1;
                            }
                            return;
                        }
                        this.html.children[1].children[i - this.begin].state = "normal";

                        newLi.className = host.tools.classmaker.call(this, this.html.children[1].children[i - this.begin]);



                        if(this.focusIndex == i - this.begin) {
                            this.html.children[1].children[i - this.begin].children[0].state = "focus";
                        }
                        else {
                            this.html.children[1].children[i - this.begin].children[0].state = "normal";
                        }
                        newLi.firstChild.className = host.tools.classmaker.call(this, this.html.children[1].children[i - this.begin].children[0]);
                        this.html.children[1].children[i - this.begin].children[1].state = "normal";
                        newLi.lastChild.className = host.tools.classmaker.call(this, this.html.children[1].children[i - this.begin].children[1]);
                        this.end = i;

                    }
                }
                host.logger.i("iqqi", "IQQIImagineUl.setImagineData", "show next: " + ul.lastChild.lastChild.id);
                this.setState(ul.lastChild.lastChild.id, "hidden");
                hideRightArrow(this);
                adaptArrowStatus(this);
            }
        };

        IQQIImagineUl.prototype.showUl = function() {
            if(this.working) {
                return;
            }
            this.working = true;
            this.html.children[1].state = "none_normal";
            var ul = document.getElementById(this.html.children[1].id);
            if(!!ul) {
                ul.className = host.tools.classmaker.call(this, this.html.children[1]);
            }
            adaptArrowStatus(this);
        };

        IQQIImagineUl.prototype.hideUl = function() {
            this.html.children[1].state = "hidden";

            hideLeftArrow(this);
            hideRightArrow(this);
            var ul = document.getElementById(this.html.children[1].id);
            if(!!ul) {
                ul.innerHTML = "";
                ul.className = host.tools.classmaker.call(this, this.html.children[1]);
            }
            delete this.data;
            delete this.html.children[1].children;
            this.begin = 0;
            this.end = 0;
            this.focusIndex = -1;
            this.working = false;
            this.Ferry = [];
        };

        /**
         * hideUlLight intends to hide ul by chane its own and sub item's css so that dom will not be changed when execute hide.
         * method never tested.
         */
        IQQIImagineUl.prototype.hideUlLight = function() {
            this.html.children[1].state = "hidden";

            hideLeftArrow(this);
            hideRightArrow(this);
            var ul = document.getElementById(this.html.children[1].id);
            if(!!ul) {
                ul.className = host.tools.classmaker.call(this, this.html.children[1]);
                for(var i = 0; i < this.html.children[1].children.length; i++) {
                    this.html.children[1].children[i].state = "hidden";
                    var li = document.getElementById(this.html.children[1].children[i].id);
                    if(!!li) {
                        li.className = host.tools.classmaker.call(this, this.html.children[1].children[i]);
                        this.html.children[1].children[i].children[1].state = "hidden";
                        var divider = document.getElementById(this.html.children[1].children[i].children[1].id);
                        if(!!divider) {
                            divider.className = host.tools.classmaker.call(this, this.html.children[1].children[i].children[1]);
                        }
                    }
                }
            }
            delete this.data;
            delete this.html.children[1].children;
            this.begin = 0;
            this.end = 0;
            this.focusIndex = -1;
            this.working = false;
            this.Ferry = [];
        };

        IQQIImagineUl.prototype.gainFocus = function() {
            if(this.begin > 0) {
                this.setImagineData(this.data, 0);
            }
            focusItem(this, 0);
        };

        IQQIImagineUl.prototype.releaseFocus = function() {
            focusItem(this, -1);
        };

        IQQIImagineUl.prototype.onKeyDown = function(event) {    //联想区按键处理，enter right left
            host.logger.i("iqqi", "IQQIImagineUl.onKeyDown", "show event: " + event.which);
            switch(event.which) {
                case host.keyevent.VK_LEFT:
                    //if(host.tools.assertLanguageRtl(host.config.curLang)) {
		    if((GLOBAL.RTL && host.tools.assertLanguageRtl(host.config.curLang))||
		      (!GLOBAL.RTL && !host.tools.assertLanguageRtl(host.config.curLang)))  {
                        onKeyLeftDown(this);
                        break;
                    }
		    onKeyRightDown(this);
                    
                    break;
                case host.keyevent.VK_RIGHT:
                    //if(host.tools.assertLanguageRtl(host.config.curLang)) {
		    if((GLOBAL.RTL && host.tools.assertLanguageRtl(host.config.curLang))||
		      (!GLOBAL.RTL && !host.tools.assertLanguageRtl(host.config.curLang)))  {
                        onKeyRightDown(this);
                        break;
                    }
		    onKeyLeftDown(this);
                    
                    break;
                case host.keyevent.VK_ENTER:
                    onKeyEnterDown(this);
                    break;
                default:
                    return false;
            }
            return true;
        };

        IQQIImagineUl.prototype.onNewLanguageSetted = function(rewrite) {
            if(rewrite) {
                this.rewrite();
            }
        };

        /**
         * create single li.
         * @param self
         * @param {string} value
         * @param {Number} position
         * @returns {HTMLElement}
         */
        function createSingleLi(self, value, position) {   //创建联想列表
            var html = {
                "tag": "li",
                "classes": self.item,
                "id": "",
                "state": "hidden",
                "flags": iqqi_constances.c_default|iqqi_constances.c_browser_webkit|iqqi_constances.c_browser_exclude_hidden,
                "children": [
                    {
                        "tag": "div",
                        "classes": self.content,
                        "id": "",
                        "state": "normal"
                    },
                    {
                        "tag": "div",
                        "classes": self.divider,
                        "id": "",
                        "state": "hidden"
                    }
                ]
            };

            var li = document.createElement("li");
            host.logger.i("iqqi", "IQQIImagineUl.createSingleLi", "show [li data]: " + value + "; and position: " + position);
            li.id = self.item + "_" + position;
            html.id = li.id;
            li.className = host.tools.classmaker.call(self, html);

            var content = document.createElement("div");
            content.id = self.content + "_" + position;
            html.children[0].id = content.id;
            if(position == 0 && host.config.curImeFirst) {
                html.children[0].classes = self.first;
                content.className = host.tools.classmaker.call(self, html.children[0]);
            }
            else {
                html.children[0].classes = self.content;
                content.className = host.tools.classmaker.call(self, html.children[0]);
            }
            html.children[0].content = value;
            content.innerHTML = value;
            li.appendChild(content);

            var divider = document.createElement("div");
            divider.id = self.divider + "_" + position;
            divider.className = host.tools.classmaker.call(self, html.children[1]);
            html.children[1].id = divider.id;
            li.appendChild(divider);

            self.onNodeCreated(li, html);

            if(typeof self.html.children[1].children == "undefined") {
                self.html.children[1].children = [];
            }
            self.html.children[1].children.push(html);
            host.logger.i("iqqi", "IQQIImagineUl.createSingleLi", "show target li id: " + self.html.children[1].children[0].id + "; and classes: " + self.html.children[1].children[0].classes);

            return li;
        }

        function adaptArrowStatus(self) {
            if(self.html.children[0].state == "normal" && self.html.children[2].state == "normal") {
                self.html.children[1].state = "two_normal";
            }
            else if(self.html.children[0].state == "normal" || self.html.children[2].state == "normal") {
                self.html.children[1].state = "one_normal";
            }
            else {
                self.html.children[1].state = "none_normal";
            }
            var ul = document.getElementById(self.html.children[1].id);
            if(!!ul) {
                ul.className = host.tools.classmaker.call(self, self.html.children[1]);
            }
        }

        function showLeftArrow(self) {
            self.html.children[0].state = "normal";
            var leftArrow = document.getElementById(self.html.children[0].id);
            if(!!leftArrow) {
                leftArrow.className = host.tools.classmaker.call(self, self.html.children[0]);
            }
        }

        function hideLeftArrow(self) {
            self.html.children[0].state = "gone";
            var leftArrow = document.getElementById(self.html.children[0].id);
            if(!!leftArrow) {
                leftArrow.className = host.tools.classmaker.call(self, self.html.children[0]);
            }
        }

        function showRightArrow(self) {
            self.html.children[2].state = "normal";
            var leftArrow = document.getElementById(self.html.children[2].id);
            if(!!leftArrow) {
                leftArrow.className = host.tools.classmaker.call(self, self.html.children[2]);
            }
        }

        function hideRightArrow(self) {
            self.html.children[2].state = "gone";
            var leftArrow = document.getElementById(self.html.children[2].id);
            if(!!leftArrow) {
                leftArrow.className = host.tools.classmaker.call(self, self.html.children[2]);
            }
        }

        function focusItem(self, focusIndex) {
            host.logger.i("iqqi", "ImagineUl.focusItem", "show focus index: " + focusIndex);
            if(self.focusIndex + 1 > 0) {
                if(!!self.html.children[1].children[self.focusIndex]) {
                    self.html.children[1].children[self.focusIndex].children[0].state = "normal";
                    var oldFocus = document.getElementById(self.html.children[1].children[self.focusIndex].children[0].id);
                    if(!!oldFocus) {
                        oldFocus.className = host.tools.classmaker.call(self, self.html.children[1].children[self.focusIndex].children[0]);
                    }
                }
            }

            self.focusIndex = focusIndex;
            if(self.focusIndex == -1) {
                return;
            }
            self.html.children[1].children[self.focusIndex].children[0].state = "focus";
            var newFocus = document.getElementById(self.html.children[1].children[self.focusIndex].children[0].id);
            host.logger.i("iqqi", "ImagineUl.focusItem", "show !!newFocus: " + (!!newFocus) + "; and id: " + self.html.children[1].children[self.focusIndex].children[0].id);
            if(!!newFocus) {
                newFocus.className = host.tools.classmaker.call(self, self.html.children[1].children[self.focusIndex].children[0]);
            }
        }

        /**
         * response to key left down.
         * @param {IQQIImagineUl} self
         */
        function onKeyLeftDown(self) {
            if(self.focusIndex > 0) {
                focusItem(self, self.focusIndex - 1);
                return;
            }
            if(self.begin == 0) {
                return;
            }
            self.setImagineData(self.data, self.Ferry.pop());
            focusItem(self, self.end - self.begin - 1);
        }

        /**
         * response to key right down.
         * @param {IQQIImagineUl} self
         */
        function onKeyRightDown(self) {
            if(self.focusIndex + self.begin + 20 + 1 >= self.data.length) {
                try {
                    detectAndLoadMore(self);
                }
                catch(ex) {
                    host.logger.e("iqqi", "IQQIImagineUl.onKeyRightDown", "show error when detectAndLoadMore: " + ex, ex);
                }
            }
            if(self.begin + self.focusIndex < self.end - 1) {
                focusItem(self, self.focusIndex + 1);
                return;
            }
            host.logger.i("iqqi", "IQQIImagineUl.onKeyRightDown", "show end: " + self.end + "; and self.data.length: " + self.data.length);
            if(self.end == self.data.length - 1) {
                if(self.focusIndex == self.end - self.begin) {
                    return;
                }
                focusItem(self, self.focusIndex + 1);
                return;
            }
            self.Ferry.push(self.begin);
            self.setImagineData(self.data, self.end);
            focusItem(self, 0);
        }

        function onKeyEnterDown(self) {
            host.iqqi.input.insertValue(self.data[self.begin + self.focusIndex]);
            if(!!host.tv) {
                host.native.IQQINativeLearnWord(host.config.curImeType, host.iqqi.buttonPanel.currentImagineRoot, self.data[self.begin + self.focusIndex]);
            }
            host.iqqi.buttonPanel.currentImagineRoot = "";
            host.iqqi.buttonPanel.lastDisplay = [];
            self.hideUl();
        }

        function detectAndLoadMore(self) {
            host.logger.i("iqqi", "IQQIImagineUl.detectAndLoadMore", "show length: " + self.data.length + "; count: " + self.currentImagineCount);
            if(self.data.length <= self.currentImagineCount - 20) {
                var results_i = host.native.IQQINativeGetCandidates(host.iqqi.buttonPanel.currentImagineRoot, host.config.curImeType, self.data.length, 20, false, host.iqqi.buttonPanel.getType);
                for(var i = 0; i < results_i.length; ++i) {
                    self.data.push(results_i[i]);
                }
            }
            else if(self.data.length < self.currentImagineCount) {
                var results_j = host.native.IQQINativeGetCandidates(host.iqqi.buttonPanel.currentImagineRoot, host.config.curImeType, self.data.length, self.currentImagineCount - self.data.length, false, host.iqqi.buttonPanel.getType);
                for(var j = 0; j < results_j.length; ++j) {
                    self.data.push(results_j[j]);
                }
            }
        }
    }
    IQQIImagineUl.initialized = true;

    this.setImagineData(data, 0);
}

function IQQIInputPanel(html, value, position, min, max, maxLength, viewType, workType) {
    IQQIView.call(this, html);
    this.IQQI_RESPONSE_TYPE_UNDEFINED = 0;
    this.IQQI_RESPONSE_TYPE_NUM = 1;
    this.IQQI_RESPONSE_TYPE_WORD = 2;
    this.IQQI_RESPONSE_TYPE_SHIFT = 3;
    this.IQQI_RESPONSE_TYPE_SYMBOL = 4;
    this.IQQI_RESPONSE_TYPE_ESC = 5;
    this.IQQI_RESPONSE_TYPE_LANSWITCH = 6;
    this.IQQI_RESPONSE_TYPE_NUMSWITCH = 7;
    this.IQQI_RESPONSE_TYPE_WHITESPACE = 8;
    this.IQQI_RESPONSE_TYPE_BACKSPACE = 9;
    this.IQQI_RESPONSE_TYPE_ENTER = 10;
    this.IQQI_RESPONSE_TYPE_SOUND_LEVEL = 11;
    this.IQQI_RESPONSE_TYPE_IQQI_SETTINGS = 12;
    this.IQQI_RESPONSE_TYPE_MYA_SCROLL = 13;
    this.IQQI_RESPONSE_TYPE_SYMBOL_SHIFT = 14;

    if(typeof IQQIInputPanel.initialized == "undefined") {
        IQQIInputPanel.prototype.onNodeCreated = function(node) {
            if(IQQIInputPanel.prototype.onNodeCreated.initialized == undefined) {
                function onInputEnter() {
                    host.iqqi.switchFocus(host.iqqi.input);
                }

                function onInputLeave() {
                    host.iqqi.switchFocus();
                }

                IQQIInputPanel.prototype.onNodeCreated.initialized = true;
            }

            if(node.id == this.html.children[0].id) {
                node.onmouseenter = onInputEnter;
                node.onmouseleave = onInputLeave;

                node.type = this.html.children[0].type;

                if(host.tools.isRunningOnOpera()) {
                    node.unselectable = "on";
                }
            }
        };

        IQQIInputPanel.prototype.aftShow = function(node) {
            host.logger.i("iqqi", "IQQIInputPanel.prototype.aftShow.DI1210", "node.id: " + (node && node.id) + "; this.value: " + this.value + "; this.lastRecordPosition: " + this.lastRecordPosition);
            if(node == undefined || node.id == this.html.id) {
                this.setValue(this.value, this.lastRecordPosition);
            }
        };

        IQQIInputPanel.prototype.onMainPageStateChange = function(state) {
            if(state == IQQIMainPage.STATE_BACK || state == IQQIMainPage.STATE_EXIT) {
                delete this.value;
                delete this.lastRecordPosition;
            }
        };

        /**
         * set limit of the input within this panel.
         * @param {string} value
         * @param {Number} position
         * @param {Number} min
         * @param {Number} max
         * @param {Number} maxLength
         * @param {string} viewType
         * @param {string} workType
         */
        IQQIInputPanel.prototype.setAttribute = function(value, position, min, max, maxLength, viewType, workType) {
            host.logger.i("iqqi", "IQQIInputPanel.setAttribute", "show id: " + this.html.children[0].id + "; value: " + value + "; position: " + position + "; min: " + min + "; max: " + max + ";  maxLength: " + maxLength + "; viewType:" + viewType + "; workType: " + workType);
            this.viewType = viewType;
            this.workType = workType;
            this.html.children[0]["type"] = "text";
            if(!!viewType) {
                this.html.children[0]["type"] = viewType;
            }

            if(!!this.html.children[0]["maxlength"]) {
                delete this.html.children[0]["maxlength"];
            }
            if(maxLength != undefined) {
                this.maxLength = maxLength;
                this.html.children[0]["maxlength"] = this.maxLength;
            }
            this.html.children[0]["value"] = "";
            this.oldValue = "";
            this.value = "";
            this.lastRecordPosition = 0;
            if(!!value) {
                this.html.children[0]["value"] = value;
                this.oldValue = value;
                this.value = value;
                this.lastRecordPosition = value.length;
            }
        };

        IQQIInputPanel.prototype.setCallBack = function(callback) {
            host.logger.i("iqqi", "IQQIInputPanel.prototype.setCallBack", "callback: " + callback);
            if(callback) {
                this.callback = callback;
            }
        };

        /**
         * request focus for input element.
         * in most browser, this does not need.
         */
        IQQIInputPanel.prototype.requestFocus = function() {
            var dom = document.getElementById(this.html.children[0].id);
            if(!!dom) {
                this.setCaretPosition(dom.value.length);
            }
        };

        /**
         * do nothing, this is defined for all our view must implement this method, even do nothing.
         */
        IQQIInputPanel.prototype.gainFocus = function() {
            this.html.children[0].state = "focus";
            var input = document.getElementById(this.html.children[0].id);
            if(!!input) {
                input.className = host.tools.classmaker.call(this, this.html.children[0]);
            }
        };

        /**
         * do nothing, this is defined for all our view must implement this method, even do nothing.
         */
        IQQIInputPanel.prototype.releaseFocus = function() {
            this.html.children[0].state = "normal";
            var input = document.getElementById(this.html.children[0].id);
            if(!!input) {
                input.className = host.tools.classmaker.call(this, this.html.children[0]);
            }
        };

        IQQIInputPanel.prototype.isValidInput = function(id) {
            var currentValue = $('#'+this.id).val();
            if(currentValue.length >= this.maxLength) {
                return false;
            }
            if(this.workType == "number" || this.workType == "numberpassword") {
                return this.isNumberValue(id);
            }
            return true;
        };

        IQQIInputPanel.prototype.shouldStopImagine = function(imagineRoot) {
            if(!!this.maxLength) {
                var input = document.getElementById(this.html.children[0].id);
                var originValue = input.value;
                if(originValue.length + imagineRoot.length > this.maxLength) {
                    this.insertValue(imagineRoot);
                    return true;
                }
            }
            return false;
        };

        IQQIInputPanel.prototype.getCaretPosition = function() {
            var ctrl =document.getElementById(this.html.children[0].id);
            var caretPos = 0;
            if (!!document.selection) {
                ctrl.focus();
                var Sel = document.selection.createRange();
                Sel.moveStart('character', -ctrl.value.length);
                caretPos = Sel.text.length;
            }
            else if (!!ctrl.selectionStart || ctrl.selectionStart == '0') {
                caretPos = ctrl.selectionStart;
            }
            return (caretPos);
        };

        IQQIInputPanel.prototype.setCaretPosition = function(pos) {
            var ctrl =document.getElementById(this.html.children[0].id);
            if(host.tools.isRunningOnTv()) {
                ctrl.focus();
            }
            if(ctrl.setSelectionRange) {
                try {
                    ctrl.setSelectionRange(pos, pos);
                }
                catch(ex) {
                    host.logger.e("iqqi", "IQQIInputPanel.setCaretPosition", "show error: " + ex, ex);
                }
            }
            else if(ctrl.createTextRange) {
                var range = ctrl.createTextRange();
                range.collapse(false);
                range.moveEnd('character', pos);
                range.moveStart('character', pos);
                range.select();
            }
            if(host.tools.isRunningOnTv()) {
                ctrl.focus();
            }
        };

        IQQIInputPanel.prototype.setValue = function(value, position) {
            this.value = value;
            var input = document.getElementById(this.html.children[0].id);
            input && (input.value = (value || ""));
            this.lastRecordPosition = position != undefined && position;
            position != undefined && this.setCaretPosition(position);
        };

        IQQIInputPanel.prototype.executeBackSpace = function() {
            var curCaretPosition = this.getCaretPosition();
            if(curCaretPosition == 0) {
                return;
            }

            var input = document.getElementById(this.html.children[0].id);
            var originValue = input.value;
            if(originValue.length == curCaretPosition) {
                originValue = originValue.slice(0, -1);
            }
            else {
                var pre = originValue.slice(0, curCaretPosition - 1);
                var tail = originValue.slice(curCaretPosition);
                originValue = pre + tail;
            }
            this.setValue(originValue, curCaretPosition - 1);
        };

        /**
         * insert value to browser.
         * @param {string} value
         */
        IQQIInputPanel.prototype.insertValue = function(value) {
            host.logger.i("iqqi", "IQQIInputPanel.insertValue", "show value: " + value);
            var input = document.getElementById(this.html.children[0].id);
            var originValue = input.value;
            if(!!this.maxLength) {
                if(value.length + originValue.length > this.maxLength) {
                    value = value.slice(0, this.maxLength - originValue.length);
                }
            }
            var caretMove = value.length;
            var curCaretPosition = this.getCaretPosition();
            if(originValue.length == curCaretPosition) {
                value = originValue + value;
            }
            else {
                var pre = originValue.slice(0, curCaretPosition);
                var tail = originValue.slice(curCaretPosition);
                value = pre + value + tail;
            }

            if(!!this.max) {
                if(this.workType == "number" && !!this.max && value > this.max) {
                    host.logger.i("iqqi", "IQQIInputPanel.insertValue", "value is bigger than max, shield this input, show value: " + value + "; max: " + this.max);
                    return;
                }
            }

            this.setValue(value, curCaretPosition + caretMove);
        };

        IQQIInputPanel.prototype.onExit = function() {
            if(host.tv) {
                var input = document.getElementById(this.html.children[0].id);
                if(!!input){
                    host.logger.i("iqqi", "IQQIInputPanel.onExit", "show value: " + input.value);
                    //this.html.children[0]["value"] = "";
                    try {
                        if(!!window.Hisense && !!Hisense.VirtualKeyBoard) {
                            Hisense.VirtualKeyBoard.Commit(input.value || "");
                        }
                        else if(!!window.opera_omi) {
                            opera_omi.sendPlatformMessage("commit-ime;" + (input.value || "") + ";false");
                        }
                    }
                    catch(ex) {
                        host.logger.e("iqqi", "IQQIInputPanel.onExit", "show error when call el commit: " + ex, ex);
                    }
                }
            }
            if(this.callback) {
                var input = document.getElementById(this.html.children[0].id);
                if(input) {
                    if(this.callback) {
                        this.callback.call({"value": input.value, "position": this.getCaretPosition(this.html.children[0].id)});
                    }
                }
            }
	    this.html.children[0]["value"] = "";
            host.iqqi.pageState(IQQIMainPage.STATE_EXIT);
            clearTimeout(iqqi_imagine_timer);
        };

        IQQIInputPanel.prototype.onBack = function() {
            if(host.tv) {
                //this.html.children[0]["value"] = "";
                try {
                    if(!!window.Hisense && !!Hisense.VirtualKeyBoard) {
                        Hisense.VirtualKeyBoard.Commit(this.oldValue);
                    }
                    else if(!!window.opera_omi) {
                        opera_omi.sendPlatformMessage("commit-ime;" + this.oldValue + ";false");
                    }
                }
                catch(ex) {
                    host.logger.e("iqqi", "IQQIInputPanel.onBack", "show error when call el commit: " + ex, ex);
                }
            }
            if(this.callback) {
                var input = document.getElementById(this.html.children[0].id);
                if(input) {
                    if(this.callback) {
                        this.callback.call({"value": this.html.children[0]["value"], "position": this.getCaretPosition(this.html.children[0].id)});						
                    }
                }
            }
	    this.html.children[0]["value"] = "";
            host.iqqi.pageState(IQQIMainPage.STATE_BACK);
            clearTimeout(iqqi_imagine_timer);
        };

        IQQIInputPanel.prototype.onNewLanguageSetted = function(rewrite) {
            host.logger.i("iqqi", "IQQIInputPanel.prototype.onNewLanguageSetted.DI1210", "rewrite: " + rewrite);
            if(rewrite) {
                this.rewrite();
            }
        };
    }
    IQQIInputPanel.initialized = true;

    this.setAttribute(value, position, min, max, maxLength, viewType, workType);
}

function IQQILanSwitchDialog(lans, item, selector, label, callback) {
    IQQIView.call(this, {
        "tag": "div",
        "classes": "iqqi_lan_switch_page",
        "id": "iqqi_lan_switch_page",
        "state": "normal",
        "flags": iqqi_constances.c_default|iqqi_constances.c_browser_webkit,
        "children": [
            {
                "tag": "div",
                "classes": "iqqi_lan_switch_dialog",
                "id": "iqqi_lan_switch_dialog",
                "state": "normal",
                "flags": iqqi_constances.c_default|iqqi_constances.c_rtl,
                "children": [
                    {
                        "tag": "div",
                        "classes": "lan_switch_title",
                        "id": "lan_switch_title",
                        "state": "normal",
                        "flags": iqqi_constances.c_default|iqqi_constances.c_rtl,
                        "content": "@string/lan_switch_title"
                    },
                    {
                        "tag": "div",
                        "classes": "lan_switch_item_area",
                        "id": "lan_switch_item_area",
                        "state": "normal",
                        "flags": iqqi_constances.c_default|iqqi_constances.c_rtl,
                        "children": [
                            {
                                "tag": "ul",
                                "classes": "lan_switch_ul",
                                "id": "lan_switch_ul",
                                "state": "normal"
                            },
                            {
                                "tag": "div",
                                "classes": "lan_switch_scroll_bar",
                                "id": "lan_switch_scroll_bar",
                                "state": "normal",
                                "flags": iqqi_constances.c_default|iqqi_constances.c_rtl
                            }
                        ]
                    }
                ]
            }
        ]
    });
    this.type = "IQQILanSwitchDialog";

    this.item = item;
    this.selector = selector;
    this.label = label;
    this.callback = callback;

    this.begin = 0;
    this.curFocusRow = 0;

    this.step = 110;

    var curLindex = 0;

    if(typeof IQQILanSwitchDialog.initialized == "undefined") {
        IQQILanSwitchDialog.prototype.onNodeCreated = function(node) {
            if(IQQILanSwitchDialog.prototype.onNodeCreated.initialized == undefined) {
                function onDialogEnter() {
                    host.iqqi.switchFocus(host.iqqi.lanSwitch);
                }

                function onDialogLeave() {

                }

                function onDialogClick() {
                    return false;
                }

                function onItemEnter() {
                    host.logger.i("iqqi", "IQQILanSwitchDialog.prototype.onNodeCreated.onItemEnter", "this.id: " + this.id);
                    var tmpRow = parseInt(this.id.slice(this.id.lastIndexOf("_") + 1) - host.iqqi.lanSwitch.begin);
                    if(tmpRow != host.iqqi.lanSwitch.curFocusRow) {
                        blurItem(host.iqqi.lanSwitch, host.iqqi.lanSwitch.begin + host.iqqi.lanSwitch.curFocusRow);
                        host.iqqi.lanSwitch.curFocusRow = tmpRow;
                    }
                    focusItem(host.iqqi.lanSwitch, host.iqqi.lanSwitch.begin + host.iqqi.lanSwitch.curFocusRow);
                }

                function onItemLeave() {
                    host.logger.i("iqqi", "IQQILanSwitchDialog.prototype.onNodeCreated.onItemLeave", "this.id: " + this.id);
                    blurItem(host.iqqi.lanSwitch, parseInt(this.id.slice(this.id.lastIndexOf("_") + 1)))
                }

                function onItemClick() {
                    host.iqqi.lanSwitch.onKeyDown({"which": host.keyevent.VK_ENTER});
                }

                function onListWheel(event) {
                    event.preventDefault();
                    blurItem(host.iqqi.lanSwitch, host.iqqi.lanSwitch.begin + host.iqqi.lanSwitch.curFocusRow);
                    var ul = document.getElementById(host.iqqi.lanSwitch.html.children[0].children[1].children[0].id);
                    if(!!ul) {
                        host.logger.i("iqqi", "IQQILanSwitchDialog.prototype.onNodeCreated.onMouseWheel.DI1210", "show event.wheelDelta: " + event.wheelDelta + "; begin: " + host.iqqi.lanSwitch.begin + "; length: " + host.iqqi.lanSwitch.lans.length);
                        var wheelStep = host.tv ? 40 : 120;
                        if (event.wheelDelta > 0 && host.iqqi.lanSwitch.begin > 0) {
                            var wheelUp = Math.floor(Math.abs(event.wheelDelta) / wheelStep);
                            if (host.iqqi.lanSwitch.begin - wheelUp < 0) {
                                wheelUp = host.iqqi.lanSwitch.begin;
                            }
                            host.iqqi.lanSwitch.begin -= wheelUp;
                        }
                        else if (event.wheelDelta < 0 && host.iqqi.lanSwitch.lans.length - host.iqqi.lanSwitch.begin > 5) {
                            var wheelDown = Math.floor(Math.abs(event.wheelDelta) / wheelStep);
                            if (wheelDown + host.iqqi.lanSwitch.begin + 5 > host.iqqi.lanSwitch.lans.length) {
                                wheelDown = host.iqqi.lanSwitch.lans.length - host.iqqi.lanSwitch.begin - 5;
                            }
                            host.iqqi.lanSwitch.begin += wheelDown;
                        }
                    }
                    host.logger.i("iqqi", "IQQILanSwitchDialog.prototype.onNodeCreated.onMouseWheel.DI1210", "show begin: " + host.iqqi.lanSwitch.begin + "; focusRow: " + host.iqqi.lanSwitch.curFocusRow);
                    focusItem(host.iqqi.lanSwitch, host.iqqi.lanSwitch.begin + host.iqqi.lanSwitch.curFocusRow);
                    calculateUl(host.iqqi.lanSwitch);
                    calculateScrollBar(host.iqqi.lanSwitch);
                }

                IQQILanSwitchDialog.prototype.onNodeCreated.initialized = true;
            }

            if(node.id == this.html.id) {
                if(!host.tools.isRunningOnOpera()) {
                    node.onselectstart = function() {
                        return false;
                    };
                }

                node.onmouseenter = onDialogEnter;
                node.onmouseleave = onDialogLeave;
                node.onclick = onDialogClick;
            }
            else if(/^iqqi_lan_switch_item_\d+/gm.test(node.id)) {
                node.onmouseenter = onItemEnter;
                node.onmouseleave = onItemLeave;
                node.onclick = onItemClick;
            }
            else if(host.iqqi.lanSwitch.html.children[0].children[1].children[0].id == node.id) {
                node.onmousewheel = onListWheel;
            }

            if(host.tools.isRunningOnOpera()) {
                if(node.textContent) {
                    node.unselectable = "on";
                }
            }
        };

        IQQILanSwitchDialog.prototype.gainFocus = function() {

        };

        IQQILanSwitchDialog.prototype.releaseFocus = function() {

        };

        IQQILanSwitchDialog.prototype.onMainPageStateChange = function(state) {
            if(state == IQQIMainPage.STATE_BACK || state == IQQIMainPage.STATE_EXIT) {
                delete this.begin;
                delete this.curFocusRow;
                delete this.lans;
                delete this.html.children[0].children[1].children[0].children;
            }
        };

        /**
         * set the lans to show.
         * @param {Array} lans
         */
        IQQILanSwitchDialog.prototype.setLans = function(lans) {
            if(!!lans) {
                this.lans = lans;
                if(host.screen == "720P") {
                    this.step = 60;
                }
                else {
                    this.step = 110;
                }
                this.html.children[0].children[1].children[0].children = [];
                for(var key in lans) {
                    if(lans.hasOwnProperty(key)) {
                        createSingleLi(this, lans[key], key);
                    }
                }
                calculateScrollBar(this);
            }
        };

        IQQILanSwitchDialog.prototype.aftShow = function() {
            calculateScrollBar(this);
            calculateUl(this);
        };

        IQQILanSwitchDialog.prototype.onKeyDown = function(event) {
            switch(event.which) {
                case host.keyevent.VK_DOWN:
                    return onKeyDownDown(this);
                case host.keyevent.VK_UP:
                    return onKeyUpDown(this);
                case host.keyevent.VK_ESC:
                    return onKeyEscDown(this);
                case host.keyevent.VK_ENTER:
                    return onKeyEnterDown(this);
                case host.keyevent.VK_BACK:
                    return onKeyBackDown(this);
            }
        };

        function createSingleLi(self, lan, index) {
            var html = {
                "tag": "li",
                "classes": "iqqi_lan_switch_item",
                "id": "",
                "state": "normal",
                "closed_flag": false,
                "children": [
                    {
                        "tag": "div",
                        "classes": "iqqi_lan_switch_item_selector",
                        "id": "",
                        "state": "normal",
                        "flags": iqqi_constances.c_default|iqqi_constances.c_rtl
                    },
                    {
                        "tag": "div",
                        "classes": "iqqi_lan_switch_item_name",
                        "id": "",
                        "state": "normal",
                        "flags": iqqi_constances.c_default|iqqi_constances.c_rtl
                    }
                ]
            };

            html.id = self.item + "_" + index;

            html.children[0].id = self.selector + "_" + index;

            html.children[1].id = self.label + "_" + index;
            html.children[1].content = lan.name;


            if(lan.code == host.config.curLang) {
                self.begin = parseInt(index);
                if(ltt.api.js.json.fetchData(self.lans, "length") <= 5) {
                    self.begin = 0;
                }
                else if(ltt.api.js.json.fetchData(self.lans, "length") - self.begin <= 5) {
                    self.begin = ltt.api.js.json.fetchData(self.lans, "length") - 5;
                }

                self.curFocusRow = index - self.begin;
                curLindex = index;
                html.state = "focus";
                html.children[0].state = "focus";
            }

            ltt.api.js.json.fetchData(self, "html").children[0].children[1].children[0].children.push(html);
        }

        function calculateUl(self) {
            var ul = document.getElementById(self.html.children[0].children[1].children[0].id);
            self.html.children[0].children[1].children[0]["style"] = "scrollTop: " + (self.begin * self.step) + "px;";
            if(!!ul) {
                ul.scrollTop = self.begin * self.step;
            }
        }

        function scrollUp(self) {
            var ul = document.getElementById(self.html.children[0].children[1].children[0].id);
            if(!!ul) {
                if(ul.scrollTop <= 0) {
                    ul.scrollTop = 0;
                    return;
                }
                self.html.children[0].children[1].children[0]["style"] = "scrollTop: " + (ul.scrollTop - self.step) + "px;";
                ul.scrollTop -= self.step;
            }
        }

        function scrollDown(self) {
            if(self.begin + self.curFocusRow == ltt.api.js.json.fetchData(self.lans, "length")) {
                return;
            }
            var ul = document.getElementById(self.html.children[0].children[1].children[0].id);
            if(!!ul) {
                self.html.children[0].children[1].children[0]["style"] = "scrollTop: " + (ul.scrollTop + self.step) + "px;";
                ul.scrollTop += self.step;
            }
        }

        function calculateScrollBar(self) {
            var scroll = document.getElementById(self.html.children[0].children[1].children[1].id);
            if(ltt.api.js.json.fetchData(self.lans, "length") < 6) {
                self.html.children[0].children[1].children[1].state = "hidden";
                if(!!scroll) {
                    scroll.className = self.classmaker(self.html.children[1].children[1].classes, self.html.children[1].children[1].state);
                }
                return;
            }
            var top = 20 + Math.floor((self.begin / ltt.api.js.json.fetchData(self.lans, "length")) * (host.screen == "720P" ? 280 : 540));
            var height = Math.floor((5 / ltt.api.js.json.fetchData(self.lans, "length")) * (host.screen == "720P" ? 280 : 540));
            host.logger.i("iqqi", "IQQILanSwitchDialog.calculateScrollBar", "show top: " + top + "; height: " + height);
            self.html.children[0].children[1].children[1]["style"] = "top: " + top + "px; height: " + height + "px;";
            if(!!scroll) {
                scroll.style.top = top + "px";
                scroll.style.height = height + "px";
            }
        }

        /**
         *
         * @param {IQQILanSwitchDialog} self
         * @returns {*}
         */
        function onKeyDownDown(self) {
            host.logger.i("iqqi", "IQQILanSwitchDialog.onKeyDownDown", "show row: " + self.curFocusRow + "; begin: " + self.begin + "; length: " + self.lans.length);
            if(self.begin + self.curFocusRow + 1 == self.lans.length) {
                return;
            }
            if(self.curFocusRow < 4) {
                blurItem(self, self.begin + self.curFocusRow);
                self.curFocusRow++;
                if (lans[self.begin + self.curFocusRow - 1].code == host.config.curLang) {
                    curLindex = self.begin + self.curFocusRow - 1;
                }
                focusItem(self, self.begin + self.curFocusRow);
            }
            else if(self.begin + self.curFocusRow + 1 < self.lans.length) {
                blurItem(self, self.begin + self.curFocusRow);
                self.begin++;
                if (lans[self.begin + self.curFocusRow - 1].code == host.config.curLang) {
                    curLindex = self.begin + self.curFocusRow - 1;
                }
                focusItem(self, self.begin + self.curFocusRow);
                scrollDown(self);
            }
            calculateScrollBar(self);

            return true;
        }

        function onKeyUpDown(self) {
            host.logger.i("iqqi", "IQQILanSwitchDialog.onKeyDownDown", "show row: " + self.curFocusRow + "; begin: " + self.begin + "; length: " + ltt.api.js.json.fetchData(self.lans, "length"));
            if(self.curFocusRow > 0) {
                blurItem(self, self.begin + self.curFocusRow);
                self.curFocusRow--;
                if (lans[self.begin + self.curFocusRow + 1].code == host.config.curLang) {
                    curLindex = self.begin + self.curFocusRow + 1;
                }
                focusItem(self, self.begin + self.curFocusRow);
            }
            else if(self.begin > 0) {
                blurItem(self, self.begin + self.curFocusRow);
                self.begin--;
                if (lans[self.begin + self.curFocusRow + 1].code == host.config.curLang) {
                    curLindex = self.begin + self.curFocusRow + 1;
                }
                focusItem(self, self.begin + self.curFocusRow);
                scrollUp(self);
            }
            calculateScrollBar(self);

            return true;
        }

        function onKeyEscDown(self) {
            self.hide();
            host.iqqi.switchFocus(host.iqqi.buttonPanel);
            host.iqqi.buttonPanel.currentImagineRoot = "";
            host.iqqi.input.onExit();
            host.iqqi.hide();
            if (!!host.iqqi.charPanel) {
                host.iqqi.charPanel.hide();
            }
            return true;
        }

        function onKeyEnterDown(self) {
            self.hide();
            if(!!self.callback && self.lans && !! self.lans[self.begin + self.curFocusRow]) {
                self.callback.call(self, self.lans[self.begin + self.curFocusRow]);
            }
        }

        function onKeyBackDown(self) {
            self.hide();
            host.iqqi.switchFocus(host.iqqi.buttonPanel);
            return true;
        }

        function blurItem(self, index) {
            host.logger.i("iqqi", "IQQILanSwitchDialog.blurItem.DI1210", "index: " + index);
            self.setState(self.html.children[0].children[1].children[0].children[index].id, "normal");
            self.setState(self.html.children[0].children[1].children[0].children[index].children[0].id, "normal");
        }

        function focusItem(self, index) {
            self.setState(self.html.children[0].children[1].children[0].children[index].id, "focus");
            self.setState(self.html.children[0].children[1].children[0].children[index].children[0].id, "focus");
            if (lans[index].code == host.config.curLang) {
                $(".iqqi_lan_switch_item_selector_presto_1080P_focus").css("background-image","url(./keyboard/img/ball_checked.png)");
                $(".iqqi_lan_switch_item_selector_presto_1080P_focus").css("background-repeat","no-repeat");
                $(".iqqi_lan_switch_item_selector_presto_1080P_focus").css("background-position","center");
                $(".iqqi_lan_switch_item_selector_presto_1080P_focus").css("background-size","50% 50%");
                $(".iqqi_lan_switch_item_selector_rtl_presto_1080P_focus").css("background-image","url(./keyboard/img/ball_checked.png)");
                $(".iqqi_lan_switch_item_selector_rtl_presto_1080P_focus").css("background-repeat","no-repeat");
                $(".iqqi_lan_switch_item_selector_rtl_presto_1080P_focus").css("background-position","center");
                $(".iqqi_lan_switch_item_selector_rtl_presto_1080P_focus").css("background-size","50% 50%");
                $("#iqqi_lan_switch_item_selector_" + curLindex).css("background-image","url(./keyboard/img/ball_checked.png)");
                $("#iqqi_lan_switch_item_selector" + curLindex).css("background-repeat","no-repeat");
                $("#iqqi_lan_switch_item_selector" + curLindex).css("background-position","center");
                $("#iqqi_lan_switch_item_selector" + curLindex).css("background-size","50% 50%");
            } else {
                $(".iqqi_lan_switch_item_selector_presto_1080P_focus").css("background-image","url(./keyboard/img/ball_normal.png)");
                $(".iqqi_lan_switch_item_selector_presto_1080P_focus").css("background-repeat","no-repeat");
                $(".iqqi_lan_switch_item_selector_presto_1080P_focus").css("background-position","center");
                $(".iqqi_lan_switch_item_selector_presto_1080P_focus").css("background-size","50% 50%");
                $(".iqqi_lan_switch_item_selector_rtl_presto_1080P_focus").css("background-image","url(./keyboard/img/ball_normal.png)");
                $(".iqqi_lan_switch_item_selector_rtl_presto_1080P_focus").css("background-repeat","no-repeat");
                $(".iqqi_lan_switch_item_selector_rtl_presto_1080P_focus").css("background-position","center");
                $(".iqqi_lan_switch_item_selector_rtl_presto_1080P_focus").css("background-size","50% 50%");
                $("#iqqi_lan_switch_item_selector_" + curLindex).css("background-image","url(./keyboard/img/ball_checked.png)");
                $("#iqqi_lan_switch_item_selector" + curLindex).css("background-repeat","no-repeat");
                $("#iqqi_lan_switch_item_selector" + curLindex).css("background-position","center");
                $("#iqqi_lan_switch_item_selector" + curLindex).css("background-size","50% 50%");
            }
        }

        IQQILanSwitchDialog.initialized = true;
    }

    this.setLans(lans);
}

function IQQIFourColorControlPanel(html) {
    IQQIView.call(this, html);
    this.type = "FourColorControlPanel";

    if(IQQIFourColorControlPanel.initialized == undefined) {
        IQQIFourColorControlPanel.prototype.onNodeCreated = function(node) {
            if(IQQIFourColorControlPanel.prototype.onNodeCreated.initialized == undefined) {
                function onMouseClick() {
                    if(host.iqqi.controlPanel.html.children[0].id == this.id) {
                        host.iqqi.controlPanel.onKeyDown({"which": host.keyevent.VK_BLUE});
                    }
                    else if(host.iqqi.controlPanel.html.children[1].id == this.id) {
                        host.iqqi.controlPanel.onKeyDown({"which": host.keyevent.VK_YELLOW});
                    }
                    else if(host.iqqi.controlPanel.html.children[2].id == this.id) {
                        host.iqqi.controlPanel.onKeyDown({"which": host.keyevent.VK_GREEN});
                    }
                    else if(host.iqqi.controlPanel.html.children[3].id == this.id) {
                        host.iqqi.controlPanel.onKeyDown({"which": host.keyevent.VK_RED});
                    }
                    return false;
                }

                IQQIFourColorControlPanel.prototype.onNodeCreated.initialized = true;
            }

            if(/^iqqi_control_area_[a-zA-Z]+$/gm.test(node.id)) {
                node.onclick = onMouseClick;
            }

            if(host.tools.isRunningOnOpera()) {
                if(node.textContent) {
                    node.unselectable = "on";
                }
            }
        };

        IQQIFourColorControlPanel.prototype.onMainPageStateChange = function(state) {

        };

        IQQIFourColorControlPanel.prototype.onNewLanguageSetted = function(rewrite) {
            host.logger.i("iqqi", "IQQIFourColorControlPanel.onNewLanguageSetted", "show rewrite: " + rewrite);
            if(rewrite) {
                this.rewrite();
                return;
            }
            var enter = document.getElementById("iqqi_control_area_enter_label");
            if(!!enter) {
                enter.innerHTML = strings["iqqi_control_enter"][host.config.curColorLanguage];
            }
            var deleteAll = document.getElementById("iqqi_control_area_delete_delete");
            if(!!deleteAll) {
                deleteAll.innerHTML = strings["iqqi_control_delete"][host.config.curColorLanguage];
            }
            var right = document.getElementById("iqqi_control_area_right_label");
            if(!!right) {
                right.innerHTML = strings["iqqi_control_right"][host.config.curColorLanguage];
            }
            var left = document.getElementById("iqqi_control_area_left_label");
            if(!!left) {
                left.innerHTML = strings["iqqi_control_left"][host.config.curColorLanguage];
            }
        };

        IQQIFourColorControlPanel.prototype.onKeyDown = function(event) {
            switch(event.which) {
                case host.keyevent.VK_RED:
                    return onKeyRedDown();
                case host.keyevent.VK_GREEN:
                    return onKeyGreenDown();
                case host.keyevent.VK_YELLOW:
                    return onKeyYellowDown();
                case host.keyevent.VK_BLUE:
                    return onKeyBlueDown();
            }
        };

        function onKeyRedDown() {
            if(host.iqqi.lanSwitch == host.iqqi.curFocus) {
                host.logger.i("iqqi", "IQQIFourColorControlPanel.onKeyRedDown", "current focus is lanSwitch, shield red key.");
                return true;
            }
            var caretPosition = host.iqqi.input.getCaretPosition();
            if(caretPosition > 0) {
                host.iqqi.input.setCaretPosition(caretPosition - 1);
            }
            else {
                host.iqqi.input.setCaretPosition(caretPosition);
            }
            return true;
        }

        function onKeyGreenDown() {
            if(host.iqqi.lanSwitch == host.iqqi.curFocus) {
                host.logger.i("iqqi", "IQQIFourColorControlPanel.onKeyGreenDown", "current focus is lanSwitch, shield green key.");
                return true;
            }
            var caretPosition = host.iqqi.input.getCaretPosition();
            var length = document.getElementById("iqqi_input").value.length;
            host.logger.i("IQQIFourColorControlPanel.onKeyGreenDown", "show caret: " + caretPosition + "; length: " + length);
            if(caretPosition < length) {
                host.iqqi.input.setCaretPosition(caretPosition + 1);
            }
            else {
                host.iqqi.input.setCaretPosition(caretPosition);
            }
            return true;
        }

        function onKeyYellowDown() {
            if(host.iqqi.lanSwitch == host.iqqi.curFocus) {
                host.logger.i("iqqi", "IQQIFourColorControlPanel.onKeyYellowDown", "current focus is lanSwitch, shield yellow key.");
                return true;
            }
            document.getElementById("iqqi_input").value = "";
            host.iqqi.input.setCaretPosition(0);
        }

        function onKeyBlueDown() {
            if(host.iqqi.lanSwitch == host.iqqi.curFocus) {
                host.logger.i("iqqi", "IQQIFourColorControlPanel.onKeyBlueDown", "current focus is lanSwitch, dispatch enter event to lanSwitch.");
                host.keyboard.onKeyDown({"which": host.keyevent.VK_ENTER});
                return true;
            }
            if(!!host.iqqi.buttonPanel.currentImagineRoot) {
                host.iqqi.input.insertValue(host.iqqi.buttonPanel.currentImagineRoot);
                if(!!host.tv  && !!host.config.curImeFirst) {
                    host.native.IQQINativeLearnWord(host.config.curImeType, host.iqqi.buttonPanel.currentImagineRoot, host.iqqi.buttonPanel.currentImagineRoot);
                }
                host.iqqi.buttonPanel.currentImagineRoot = "";
                host.iqqi.imagineUl.hideUl();
                return false;
            }
            host.iqqi.input.onExit();
            host.iqqi.hide();
            if (!!host.iqqi.charPanel) {
                host.iqqi.charPanel.hide();
            }
            return true;
        }
    }
    IQQIFourColorControlPanel.initialized = true;
}
