import { eqi18n } from '@easyquery/core'
//----------------------------------
//  PopupMenu widget
//----------------------------------

export function registerPopupMenu($) {

    function getScrollPos() {
        return {
            top: $(window).scrollTop(), 
            left: $(window).scrollLeft()
        };
    }

    function getElementAbsolutePos(element, parent) {
        var res = { x: 0, y: 0 }
        if (element !== null) {
            var position = $(element).offset();
            //parent = parent || document.documentElement || document.body;
            //var parPosition = $(parent).offset();

            //res = { x: position.left - parPosition.left, y: position.top - parPosition.top };
            res = { x: position.left , y: position.top };
        }
        return res;
    }

    function getWinSize() {
        var wnd = $(window);
        return { 
            width: wnd.innerWidth(), 
            height: wnd.innerHeight()
        };
    }



    var mouseTimer = null;

    MenuLevel.prototype = {
        _turnCheckboxes: function (items) {
            var itemsLength = items.length;
            var item;

            //turn checkboxes on for selected items
            for (var i = 0; i < itemsLength; i++) {
                item = items[i];
                if (item.itemCheckbox)
                    item.itemCheckbox.checked = this._isItemSelected(item);
                if (item.items) {
                    this._turnCheckboxes(item.items);
                }
            }
        },

        _isItemSelected: function (item) {
            if (item.items) {
                for (var i = 0; i < item.items.length; i++) {
                    if (this._isItemSelected(item.items[i])) {
                        return true;
                    }
                }
                return false;
            }
            else {
                return item.selected;
            }
        },

        _setItemSelected: function (item, value) {
            if (item.items) {
                for (var i = 0; i < item.items.length; i++) {
                    this._setItemSelected(item.items[i], value);
                }
            }
            else {
                item.selected = value;
            }
        },

        showAt: function (x, y, adjustTopPos, hidden) {
            if (!this.items) {
                return;
            }

            var self = this;

            this.initLevelDiv();

            //crocodile
            this._turnCheckboxes(this.items);

            this._renderItems();

            var levelStyle = this.levelDiv.style;
            if (hidden) {
                $(this.levelDiv).css("visibility", "hidden");
            }
            levelStyle.display = 'block';
        
            levelStyle.left = x + 'px';
            levelStyle.top = y + 'px';


            this.scrollDiv.style.width = "auto";
            this.scrollDiv.style.height = "auto";

            //adjusting level top position
            if (adjustTopPos) {
                y = this.adjustTopPos(y);
                levelStyle.top = y + 'px';
            }

            //setting minimal level width if it is defined
            var minItemWidth = this.parentMenu.minItemWidth;
            if (minItemWidth > 0 && this.scrollDiv.offsetWidth < minItemWidth) {
                for (var i = 0; i < this.items.length; i++) {
                    this.items[i].itemDiv.style.width = minItemWidth + "px";
                }
            }

            var maxItemWidth = this.parentMenu.maxItemWidth;

            //window.alert("max width:" + maxItemWidth + "; div width:" + this.scrollDiv.offsetWidth);
            if (maxItemWidth > 0 && this.scrollDiv.offsetWidth > maxItemWidth) {
                for (var i = 0; i < this.items.length; i++) {
                    this.items[i].itemDiv.style.width = maxItemWidth + "px";
                    this.items[i].itemDiv.style.overflowX = "hidden";
                }
            }

            var winSize = getWinSize();

            //adjustinng maximum height of the menu level if it does not fit to browser window
            var maxHeight = winSize.height - (y - getScrollPos().top) - 15;  //document.documentElement.scrollTop

            if (this.parentMenu.maxHeight > 0 && maxHeight > this.parentMenu.maxHeight) {
                maxHeight = this.parentMenu.maxHeight;
            }

            if (this.applyItem != null && this.applyItem.itemDiv != null) {
                maxHeight -= this.applyItem.itemDiv.offsetHeight + 5;
            }

            if (this.searchDiv != null) {
                maxHeight -= this.searchDiv.offsetHeight;
            }

            if (this.levelDiv.offsetHeight > maxHeight) {
                var newHeight = maxHeight;
                if (newHeight < 50) { newHeight = 50; }
                this.scrollDiv.style.height = newHeight + "px";
            }
            else {
                this.scrollDiv.style.height = "auto";
            }
            
            this.activeItem = null;
        },

        focus: function () {
            var self = this;
            window.setTimeout(function () {
                $(self.scrollDiv).focus();
                if (self.searchBox != null) {
                    if (self.parentMenu.options.searchBoxAutoFocus) {
                        self.searchBox.focus();
                    }
                    self.searchBox.value = "";
                }
            }, 100);
        },

        hide: function () {
            if (this.activeItem !== null) {
                if (this.activeItem.subLevel) {
                    this.activeItem.subLevel.hide();
                }
            }

            if (this.levelDiv) {
                var levelStyle = this.levelDiv.style;
                levelStyle.display = 'none';

                if (this.initialized) {
                    this.parentElement.removeChild(this.levelDiv);
                    this.initialized = false;
                }
            }
        },

        adjustTopPos: function (top) {
            var winSize = getWinSize();
            var res = top;
            var levelBottom = top - getScrollPos().top + this.levelDiv.offsetHeight;  //document.documentElement.scrollTop
            if (levelBottom > winSize.height - 5) {
                res -= levelBottom - winSize.height + 5;
                if (res < getScrollPos().top) {   
                    res = getScrollPos().top + 10; 
                }
            }
            return res;
        },

        initLevelDiv: function () {
            if (!this.initialized) {
                this.parentElement.appendChild(this.levelDiv);
                $(this.levelDiv).addClass("eqjs-menu-levelDiv");
                this.initialized = true;
            }
        },

        activateItem: function (menuItem) {
            if (this.activeItem != null) {
                this.deactivateItem(this.activeItem);
            }
            this.activeItem = menuItem;

            var rowElement = menuItem.itemDiv;
            $(rowElement).addClass("active");

            if (this.parentMenu.options.useDefaultStyles) {
                var itemBgColor = this.parentMenu.style.colors.bgON;
                var itemFgColor = this.parentMenu.style.colors.fgON;
                var itemOverBgColor = this.parentMenu.style.colors.bgOVER;
                var itemOverFgColor = this.parentMenu.style.colors.fgOVER || "";

                var itemClass = this.parentMenu.style.itemClass || "";
                var itemClassOver = this.parentMenu.style.itemClassOver || "";


                if (itemClassOver != "") {
                    rowElement.style.backgroundColor = "";
                    rowElement.style.color = "";
                }
                else {
                    //rowElement.className = "";
                    rowElement.style.backgroundColor = itemOverBgColor;
                    rowElement.style.color = itemOverFgColor;
                }
            }

            if (menuItem.items) {
                this.showSubLevel(menuItem);
            }

        },

        deactivateItem: function (menuItem) {
            var rowElement = menuItem.itemDiv;

            $(rowElement).removeClass("active");

            if (this.parentMenu.options.useDefaultStyles) {
                var itemBgColor = this.parentMenu.style.colors.bgON;
                var itemFgColor = this.parentMenu.style.colors.fgON;

                var itemClass = this.parentMenu.style.itemClass || "";
                if (itemClass != "") {
                    rowElement.style.backgroundColor = "";
                    rowElement.style.color = "";
                }
                else {
                    rowElement.style.backgroundColor = itemBgColor;
                    rowElement.style.color = itemFgColor;
                }
            }

            if (menuItem.subLevel) {
                menuItem.subLevel.hide();
            }
            this.activeItem = null;


        },


        _submitItems: function (items, selectedItems) {
            var itemsLength = items.length;
            for (var j = 0; j < itemsLength; j++) {
                if (items[j].items) {
                    this._submitItems(items[j].items, selectedItems);
                }
                else {
                    if (items[j].selected) {
                        selectedItems.push(items[j]);
                    }
                }
            }
        },

        submit: function (menuItem) {
            if (menuItem != null) {

                if (menuItem.items) { 

                }
                else {
                    this.parentMenu.hideMenu();
                    var selectedItems = [];
                    if (menuItem == this.applyItem) {
                        this._submitItems(this.items, selectedItems);
                    }

                    //-------- Not necessary. Remove after testing --------
                    //if (selectedItems.length == 0)
                    //    selectedItems = null;

                    this.parentMenu.submitMenu(menuItem, selectedItems);
                }
            }

        },

        showSubLevel: function (menuItem) {
            if (!menuItem.subLevel) {
                var levelId = '';
                if (this.menuId) {
                    levelId = this.menuId + "-" + menuItem.id;
                }

                menuItem.subLevel = new MenuLevel({
                    menu: this.parentMenu,
                    parent: this,
                    container: this.parentElement,
                    items: menuItem.items,
                    levelIndex: this.levelIndex + 1,
                    domWriteItemsId: this.domWriteItemsId,
                    menuId: levelId,
                    itemRenderedCallback: this.itemRenderedCallback
                });
            }

            var pos = getElementAbsolutePos(menuItem.itemDiv, this.parentElement);
            var scroll = getScrollPos();
            var winSize = getWinSize();

            //show menu to the side that have more space available
            var leftSpace = pos.x - scroll.left; 
            var rightSpace = winSize.width - leftSpace - menuItem.itemDiv.offsetWidth;
            var leftposx = pos.x;
          
            pos.x += menuItem.itemDiv.offsetParent.offsetWidth;
            pos.y += 1;
            menuItem.subLevel.showAt(pos.x, pos.y, true, true);

            menuItem.subLevel.levelDiv.style.width = '';
            menuItem.subLevel.levelDiv.style.right = '';
            if ((rightSpace >= menuItem.subLevel.levelDiv.offsetWidth) || (rightSpace >= leftSpace)) {  //show level to the right
                if (rightSpace < menuItem.subLevel.levelDiv.offsetWidth) {
                    menuItem.subLevel.levelDiv.style.right = -scroll.left + 'px'; 
                }
            }
            else { //show level to the left
                if (leftSpace < menuItem.subLevel.levelDiv.offsetWidth) {
                    menuItem.subLevel.levelDiv.style.left = scroll.left + 4 + 'px';
                }
                else {
                    menuItem.subLevel.levelDiv.style.left = '';
                }
                menuItem.subLevel.levelDiv.style.right = $(window).width() - pos.x + menuItem.itemDiv.offsetWidth - 6 + 'px';
            }

            $(menuItem.subLevel.levelDiv).css("visibility", "visible");
            menuItem.subLevel.focus();
        },

        refreshItems: function() {
            var itemsLength = this.items.length;
            for (var i = 0; i < itemsLength; i++) {
                var item = this.items[i];
                if (item.itemDiv) {
                    if (item.hidden) {
                        item.itemDiv.style.display = "none";
                    }
                    else {
                        item.itemDiv.style.display = "block";
                    }
                }

                if (item.subLevel) {
                    item.subLevel.refreshItems();
                }
            }
        },

        refreshCheckboxes: function () {
            var itemsLength = this.items.length;
            for (var i = 0; i < itemsLength; i++) {
                var item = this.items[i];
                if (item.itemCheckbox) {
                    item.itemCheckbox.checked = this._isItemSelected(item);
                }

                if (item.subLevel) {
                    item.subLevel.refreshCheckboxes();
                }
            }
        },

        renderContent: function () {
            if (!this.items) {
                return;
            }

            var self = this;
            //define internal variables used in this function
            var itemBgColor = this.parentMenu.style.colors.bgON || "white";
            var itemFgColor = this.parentMenu.style.colors.fgON || "black";
            var itemOverBgColor = this.parentMenu.style.colors.bgOVER || "LightSteelBlue";
            var itemFontFamily = this.parentMenu.style.itemStyle.fontFamily || "";
            var itemFontSize = this.parentMenu.style.itemStyle.fontSize || "14px";

            var multiselect = this.parentMenu.options.multiselect;
            var isSubQuery = this.parentMenu.options.isSubQuery;


            //add base DIV element which is also used to show the shadow
            var baseDiv = document.createElement("div");

            if (this.parentMenu.options.useDefaultStyles) {
                baseDiv.style.backgroundColor = itemBgColor;
                baseDiv.style.border = "1px solid";
                baseDiv.style.borderColor = this.parentMenu.style.colors.border;
                baseDiv.style.margin = "-2px 2px 2px -2px";
                baseDiv.style.width = "auto";
                baseDiv.style.height = "auto";
            }
            baseDiv.style.zIndex = this.parentMenu.zIndex;
            baseDiv.style.position = "absolute";
            baseDiv.style.display = "none";

            baseDiv['menuLevel'] = this;

            var _parentMenu = this.parentMenu;
            var _applyItem = this.applyItem;


            //if multiselect option is on - then we should add special "apply" item
            if (multiselect && this.levelIndex === 0) {
                var applyDiv = document.createElement("div");
                this.applyBtn = document.createElement('button');
                $(applyDiv).addClass("eqjs-menu-applyDiv");

                applyDiv['menuItem'] = _applyItem;

                if (this.parentMenu.options.useDefaultStyles) {
                    applyDiv.style.borderBottom = "1px solid";
                    applyDiv.style.padding = "5px";
                    applyDiv.style.marginBottom = "5px";

                    this.applyBtn.style.padding = "0 5px";
                    this.applyBtn.style.cursor = "pointer";
                }

                var applyTextNode = document.createTextNode(this.parentMenu.options.buttons.submit);

                this.applyBtn.appendChild(applyTextNode);

                applyDiv.appendChild(this.applyBtn);


                //cancel btn

                var cancelBtn = document.createElement('button');

                $(cancelBtn).addClass('eqjs-menu-cancel')

                if (this.parentMenu.options.useDefaultStyles) {
                    cancelBtn.style.padding = "0 5px";
                    cancelBtn.style.cursor = "pointer";
                    cancelBtn.style.marginLeft = "15px";
                }

                var cancelText = document.createTextNode(this.parentMenu.options.buttons.cancel);

                cancelBtn.appendChild(cancelText);

                applyDiv.appendChild(cancelBtn);

                baseDiv.appendChild(applyDiv);

                _applyItem.itemDiv = applyDiv;

                $(this.applyBtn).click(function () {
                    self.submit(self.applyItem);
                });

                $(cancelBtn).click(function () {
                    self.parentMenu.hideMenu();
                });
            }

            //if too many items - then we add a special "search" item
            if (self.items.length >= _parentMenu.options.showSearchBoxAfter) {
                var searchDiv = document.createElement("div");
                $(searchDiv).addClass("eqjs-menu-searchDiv");
                if (this.parentMenu.options.useDefaultStyles) {
                    searchDiv.style.borderBottom = "1px solid #666";
                    searchDiv.style.backgroundColor = itemBgColor;
                    searchDiv.style.borderColor = this.parentMenu.style.colors.border;
                    if (itemFontFamily != "") { searchDiv.style.fontFamily = itemFontFamily; }
                    searchDiv.style.fontSize = itemFontSize;
                    searchDiv.style.color = itemFgColor;
                    searchDiv.style.cursor = "pointer";
                    searchDiv.style.textAlign = "left";
                    searchDiv.style.padding = "5px";
                }

                var searchEditBox = document.createElement("input");
                searchEditBox.name = "searchBox";
                searchEditBox.id = "searchBox";
                $(searchEditBox).addClass('eqjs-menu-searchBox');
                if (isSubQuery) {
                    $(searchEditBox).addClass('ui-dialog');
                }

                self.searchBox = searchEditBox;
                self.searchDiv = searchDiv;

                searchEditBox.type = "text";
                searchEditBox.size = 16;
                if (this.parentMenu.options.useDefaultStyles) {
                    searchEditBox.style.fontFamily = "monospace";
                    searchEditBox.style.fontSize = "8pt";
                    searchEditBox.style.width = "100%";
                }
                searchDiv.appendChild(searchEditBox);
                baseDiv.appendChild(searchDiv);

                $(searchEditBox).on("input", function (this) {
                    self._renderItems($(this).val());
                });

            }

            var scrollDiv = document.createElement("div");
            $(scrollDiv).prop("tabindex", 1);
            $(scrollDiv).addClass("eqjs-menu-scrollDiv");
            scrollDiv.style.overflowX = "hidden";
            scrollDiv.style.overflowY = "auto";
            scrollDiv.style.position = "relative";
            baseDiv.appendChild(scrollDiv);
            this.levelDiv = baseDiv;
            this.scrollDiv = scrollDiv;

            if (this.menuId) {
                $(this.levelDiv).attr('id', this.menuId);
            }

            this._renderItems();

            $(scrollDiv).on("keydown", function (event) {
                switch(event.which) {
                    case 13: // enter
                        if (self.parentMenu.options.multiselect) {
                            self.parentMenu._rootLevel.applyBtn.click();
                        }
                        else {
                            if (self.activeItem) {
                                $(self.activeItem.itemDiv).click();
                            }
                        }
                        break;

                    case 32: // space
                        if (self.activeItem) {
                            $(self.activeItem.itemDiv).trigger("click", [true]);
                        }
                        break;

                    case 37: // left
                        if (self.parentLevel) {
                            self.deactivateItem(self.activeItem);
                            self.parentLevel._focusScrollDiv();
                        }
                        break;

                    case 38: // up
                        if (self.activeItem) {
                            var idx = $.inArray(self.activeItem, self.items);
                            if (idx > 0) {
                                self.activateItem(self.items[idx - 1]);
                            }
                        }
                        else {
                            self.activateItem(self.items[self.items.length - 1]);
                        }
                        break;

                    case 39: // right
                        if (self.activeItem && self.activeItem.subLevel) {
                            self.activeItem.subLevel._focusScrollDiv();
                            self.activeItem.subLevel.activateItem(self.activeItem.subLevel.items[0]);
                        }
                        break;

                    case 40: // down
                        if (self.activeItem) {
                            var idx = $.inArray(self.activeItem, self.items);
                            if (idx < self.items.length - 1) {
                                self.activateItem(self.items[idx + 1]);
                            }
                        }
                        else {
                            self.activateItem(self.items[0]);
                        }
                        break;

                    default: return; // exit this handler for other keys
                }
                event.preventDefault(); // prevent the default action (scroll / move caret)            
            })

        },

        _allSubitemsAreFiltered: function(items, filterCallback) {
            var len = items.length;
            for (var i = 0; i < len; i++) {
                if (filterCallback(items[i])) 
                    return false;
            }

            return true;
        },

        _renderItems: function(filter) {
            var self = this;

            var scrollDiv = this.scrollDiv;

            var multiselect = this.parentMenu.options.multiselect;
            var activateOnMouseOver = this.parentMenu.options.activateOnMouseOver;

            var itemFgColor = this.parentMenu.style.colors.fgON || "black";
            var itemOverBgColor = this.parentMenu.style.colors.bgOVER || "LightSteelBlue";

            var itemFontSize = this.parentMenu.style.itemStyle.fontSize || "14px";

            var itemFilterCallback = this.parentMenu._itemFilterCallback;

            $(scrollDiv).empty();

            var regex = filter ? new RegExp(filter, "i") : null;

            var i;
            var itemsLength = this.items.length;
            for (i = 0; i < itemsLength; i++) {
                var item = this.items[i];
                if (!item || !item.text) continue;
                if (itemFilterCallback) {
                    if (!itemFilterCallback(item)) continue;
                    if (item.items && self._allSubitemsAreFiltered(item.items, itemFilterCallback)) continue;
                }
                var idx = regex ? item.text.search(regex) : 0;
                if (idx < 0) continue;

                item.data = function (propName) {
                    return this[propName];
                };

                if (typeof (item.selected) == "undefined") {
                    item.selected = false;
                }
                if (item.selected && this.selectedItem == null) {
                    this.selectedItem = item;
                }
                var itemDiv = document.createElement("div");
                $(itemDiv).addClass("eqjs-menu-itemDiv");

                if (item.selected && !multiselect) {
                    $(itemDiv).addClass("eqjs-menu-selected");
                };

                if (this.domWriteItemsId && this.menuId) {
                    $(itemDiv).attr('id', 'item-' + this.menuId + '-' + item.id);
                }

                scrollDiv.appendChild(itemDiv);

                itemDiv['menuItem'] = item;
                item.itemDiv = itemDiv;
                if (this.parentMenu.options.useDefaultStyles) {
                    itemDiv.style.fontSize = itemFontSize;
                    itemDiv.style.color = itemFgColor;
                    itemDiv.style.paddingLeft = "15px";
                    itemDiv.style.paddingRight = "6px";
                    itemDiv.style.cursor = "pointer";
                }


                if (item.text == '---') {
                    itemDiv.appendChild(document.createElement('hr'));
                }
                else {
                    if (multiselect) { 
                        var cb = document.createElement("input");
                        cb.type = "checkbox";
                        cb.id = "cb" + item.id;
                        cb.checked = this._isItemSelected(item);
                        cb.defaultChecked = this._isItemSelected(item);
                        itemDiv.appendChild(cb);
                        item.itemCheckbox = cb;
                        if (this.parentMenu.options.useDefaultStyles) {
                            cb.style.margin = "4px 10px 0 0";
                            cb.style.verticalAlign = "top";
                        }
                    }
                    else {
                        if (item.selected) {
                            //var markText = document.createTextNode("\u25CF ");
                            //itemDiv.appendChild(markText);
                        }

                    }

                    var itemText = document.createTextNode(item.text);
                    itemDiv.appendChild(itemText);
                    var itemDivJq = $(itemDiv);

                    if (item.items && item.items.length > 0) {
                        itemDivJq.addClass("eqjs-menu-itemDiv-hasChildren");

                        var arrowSpan = document.createElement("span");
                        $(arrowSpan).addClass("eqjs-menu-itemDiv-arrow");
                        itemDiv.appendChild(arrowSpan);

                        var arrowText = document.createTextNode(">");
                        arrowSpan.appendChild(arrowText);

                    }




                    var itemClickHandler = function (this, event, isSpacePressed) {
                        var menuItem = this.menuItem;
                        if (multiselect) {
                            if (!menuItem.items || event.target == menuItem.itemCheckbox || isSpacePressed) {
                                var itemSelected = self._isItemSelected(menuItem);
                                self._setItemSelected(menuItem, !itemSelected);
                                menuItem.itemCheckbox.checked = !itemSelected;
                                self.parentMenu.refreshCheckboxes();
                            }
                            else {
                                self.activateItem(menuItem);
                            }
                        }
                        else {
                            self.activateItem(menuItem);
                            self.submit(menuItem);
                        }
                        //return false;
                    };

                    itemDivJq.off("click", itemClickHandler);
                    itemDivJq.on("click", itemClickHandler);


                    $(itemDiv).mouseenter(function (this) {
                        var menuItem = this.menuItem;
                        self.parentMenu.isCursorInside = true;
                        if (activateOnMouseOver) {
                            self.activateItem(menuItem);
                        }
                    });

                    $(itemDiv).mouseleave(function (this) {
                        var menuItem = this.menuItem;
                        self.parentMenu.isCursorInside = false;
                        setTimeout(function () {
                            if (!self.parentMenu.isCursorInside) {
                                if (menuItem == self.activeItem && activateOnMouseOver && !menuItem.subLevel) {
                                    self.deactivateItem(menuItem);
                                }
                            }
                        }, 200);
                    });
                }

                if (this.itemRenderedCallback) {
                    this.itemRenderedCallback(this.menuId, $(itemDiv));
                }

            }

        },

        remove: function () {
            //remove old level elements
            var itemsLength = this.items.length;
            for (var i = 0; i < itemsLength; i++) {
                var item = this.items[i];
                if (item.subLevel) {
                    item.subLevel.remove();
                }
            }

            if (this.levelDiv) {
                this.levelDiv.innerHtml = "";
                var parentNode = this.levelDiv.parentNode;
                if (parentNode != null) {
                    parentNode.removeChild(this.levelDiv);
                }
            }
            this.levelDiv = null;
        },

        update: function (newItems) {
            this.remove();

            //create new level
            this.items = newItems;
            this.activeItem = null;
            this.selectedItem = null;
            this.applyItem.itemDiv = null;
            this.initialized = false;
            this.updated++;

            this.renderContent();
        },

        findItem: function (searchedText) {
            var txt = searchedText.toLowerCase();
            var itemsLength = this.items.length;
            for (var i = 0; i < itemsLength; i++) {
                var item = this.items[i];
                if (item.text.toLowerCase().indexOf(txt) == 0) {
                    return item;
                }
            }
            return null;
        }


    };

    function MenuLevel(this, options) {
        //menu, items, levelIndex
        this.parentMenu = options.menu || null;
        this.parentLevel = options.parent || null;
        this.parentElement = options.container || document.body; //documentElement;
        this.levelIndex = options.levelIndex || 0;
        this.levelDiv = null;
        this.domWriteItemsId = options.domWriteItemsId || false;
        this.menuId = options.menuId || '';
        this.itemRenderedCallback = options.itemRenderedCallback || null;

        //we need to define special "apply" item for this level
        this.applyItem = new Object();
        this.applyItem.itemDiv = null;

        this.items = options.items || [];
        this.activeItem = null;
        this.selectedItem = null;
        this.initialized = false;

        this.updated = 0;

        this.renderContent();
    }

    var lastMenuID = 1;

    $.widget("eqjs.PopupMenu", {
        _mouseIsOverBlock: false,
        _mouseIsOverLink: false,
        _toId: null,
        _itemSelectedCallback: null,
        _menuClosedCallback: null,
        _itemFilterCallback: null,
        _rootLevel: null,

        options: {
            items: [],
            buttons: {
                submit: eqi18n.getText('ButtonApply'),
                cancel: eqi18n.getText('ButtonCancel')
            },
            itemFilterCallback : null,
            useDefaultStyles: false,
            multiselect: false,
            adjustHeight: true,
            showSearchBoxAfter: 30,
            activateOnMouseOver: true,
            container: document.body, //documentElement
            zIndex: 100000,
            domWriteItemsId: false,
            itemRenderedCallback: null
        },

        _create: function () {
            this.menuId = lastMenuID++;

            this._updateProps();

            this._rootLevel = new MenuLevel({
                menu: this,
                items: this.options.items,
                levelIndex: 0,
                container: this.options.container,
                domWriteItemsId: this.options.domWriteItemsId,
                menuId: this.options.id,
                itemRenderedCallback: this.options.itemRenderedCallback
            });
            $(this._rootLevel.levelDiv).addClass("eqjs-menu-rootLevel");
            $(this._rootLevel.levelDiv).css('z-index', this.options.zIndex);

            var self = this;

            this._menuKeyUpHandler = function (eventObj) {
                if (eventObj.which == 27) {
                    self.hideMenu();
                    eventObj.stopImmediatePropagation();
                }
            };

            this._globalMouseDownHandler = function () {
                if (!self.active) return true;
                var e = window.event || arguments[0];
                var o = e.srcElement || e.target;
                var isOutside = true;

                while (o) {
                    if (o.tagName && o.tagName.toLowerCase() == 'div') {
                        if (o.menuLevel) {
                            if (o.menuLevel.parentMenu == self) {
                                isOutside = false;
                                break;
                            }
                        }
                    }
                    o = o.parentNode || o.parentElement;
                }
                if (isOutside) {
                    self.hideMenu();
                }
                return true;
            };


            this._render();
        },


        _clearItemMenuProps: function (item) {
            //don't clear properties they belong this menu
            if (item.subLevel && item.subLevel.parentMenu == this) return;

            if (item.subLevel) {
                item.subLevel.remove();
                item.subLevel = null;
            }

            if (item.itemDiv) {
                item.itemDiv = null;
            }

            if (item.items) {
                this._clearItemsMenuProps(item.items);
            } 
        },

        _clearItemsMenuProps: function (items) {
            if (!items) return;

            for (var i = 0; i < items.length; i++) {
                this._clearItemMenuProps(items[i]);
            }
        },

        _render: function () {
            var self = this;

        },

        _updateProps: function () {
            this.style = {};
            this.style.colors = { border: "#666666", shadow: "#888888", bgON: "white", fgON: "black", bgOVER: "#B6BDD2", fgOVER: "black" };
            this.style.itemStyle = { fontSize: "14px" };

            this.minItemWidth = 0;
            this.maxItemWidth = 0;
            this.maxHeight = 0;
            this.zIndex = this.options.zIndex;

            this.commandTemplate = "";
            this.parentElement = null;
            this.args = [];
            this.active = false;
        },

        _setOption: function (key, value) {
            if (arguments.length == 2) {
                this.options[key] = value;
                return this;
            }
            else {
                return this.options[key];
            }
        },


        _setSelectedItems: function (items, selectedIds) {
            var itemsLength = items ? items.length : 0;
            var item;
            for (var i = 0; i < itemsLength; i++) {
                item = items[i];
                if (item.items) {
                    this._setSelectedItems(item.items, selectedIds);
                }
                else {
                    item.selected = $.inArray(item.id, selectedIds) >= 0;
                }
            }
        },


        showMenu: function (options) {
            var self = this;

            this._clearItemsMenuProps(this.options.items);

            self._itemSelectedCallback = options.itemSelectedCallback || null;
            self._menuClosedCallback = options.menuClosedCallback || null;
            self._itemFilterCallback = options.itemFilterCallback || null;


            if (options.items) {
                this.options.items = options.items;
                this._rootLevel.items = options.items;
            }

            if (options.onMenuItemSelected) {
                this.options.onMenuItemSelected = options.onMenuItemSelected;
            }

            var selectedIds = options.selectedIds || null;
            if (selectedIds) {
                if (typeof selectedIds === "string") {
                    selectedIds = selectedIds.split(",");
                }
            }
            else {
                selectedIds = [];
            }

            this.active = true;

            //crocodile
            this._setSelectedItems(self.options.items, selectedIds);

            var anchor = $(options.anchor || document.documentElement);

            var srcPos = getElementAbsolutePos(anchor.get(0), this.options.container);

            var anchorHeight = anchor.outerHeight(false)
            var anchorWidth = anchor.outerWidth(false);

            var pos = {
                x: srcPos.x,
                y: srcPos.y + anchorHeight + 2
            };
            var scroll = getScrollPos();
            var winSize = getWinSize();

            //show menu to the side that have more space available
            var leftSpace = pos.x + anchorWidth - scroll.left; //window.pageXOffset;
            var rightSpace = winSize.width - leftSpace + anchorWidth;
            var leftposx = pos.x;

            pos.x += 2; 
            self._rootLevel.showAt(pos.x, pos.y, true, true);

            self._rootLevel.levelDiv.style.width = '';
            self._rootLevel.levelDiv.style.right = '';
            if ((rightSpace >= self._rootLevel.levelDiv.offsetWidth) || (rightSpace >= leftSpace)) {  //show level to the right
                if (rightSpace < self._rootLevel.levelDiv.offsetWidth) {
                    self._rootLevel.levelDiv.style.right = -scroll.left + 'px';
                }
            }
            else { //show level to the left
                if (leftSpace < self._rootLevel.levelDiv.offsetWidth) {
                    self._rootLevel.levelDiv.style.left = scroll.left + 4 + 'px';
                }
                else {
                    self._rootLevel.levelDiv.style.left = '';
                }
                self._rootLevel.levelDiv.style.right = $(window).width() - pos.x - anchorWidth + 'px';
            }

            $(self._rootLevel.levelDiv).css("visibility", "visible");
            self._rootLevel.focus();

            $(document).on("keyup", this._menuKeyUpHandler);
            $(document).on('mousedown', this._globalMouseDownHandler);
        },


        hideMenu: function () {
            $(document).off('mousedown', this._globalMouseDownHandler);
            $(document).off("keyup", this._menuKeyUpHandler);
            this._rootLevel.hide();
            if (this._menuClosedCallback) {
                this._menuClosedCallback.call();
            }
        },

        submitMenu: function (menuItem, selectedItems) {

            var data = { 'widget': this, 'menuItem': menuItem, 'selectedItems': selectedItems };

            if (this._itemSelectedCallback) {
                this._itemSelectedCallback.apply(this, [null, data]);
            }
            else {
                this._trigger("onMenuItemSelected", null, data);
            }
        },

        knockMenuStyle: function (menu) {
            menu.removeAttr('style');
            var hasUlStyle = menu.find('ul').first().prop('style');

            if (hasUlStyle !== "undefined" && hasUlStyle !== false) {
                menu.find('ul').first().prop('style', '');
            }
        },

        refreshItems: function () {
            this._rootLevel.refreshItems();
        },

        refreshCheckboxes: function () {
            this._rootLevel.refreshCheckboxes();
        }

    });
}