import { eqi18n, equtils, Column, SortDirection, ExprTag } from '@easyquery/core';
export function registerColumnsPanelWidget($) {
    $.widget("eqjs.ColumnsContainer", {
        _activeColumnWidget: null,
        _globalColCounter: 0,
        _defaultMenuOptions: {
            showSearchBoxAfter: 30,
            searchBoxAutoFocus: true,
            activateOnMouseOver: true
        },
        _query: null,
        _queryObserverId: null,
        options: {
            isSubQuery: false,
            activeColumn: null,
            /// <option name="showAddRow" type="Boolean" default="true">
            /// <summary>Gets or sets a value indicating whether columns panel must show a special [add column] link at the bottom</summary>
            /// </option>
            showAddRow: true,
            /// <option name="showHeader" type="Boolean" default="true">
            /// <summary>Gets or sets a value indicating whether columns panel must show a header at the top</summary>
            /// </option>
            showHeader: true,
            /// <option name="showColumnCaptions" type="Boolean" default="true">
            /// <summary>Gets or sets a value indicating whether columns panel must show an editable caption for each column (i.e. "SELECT ColumnName AS ColumnCaption...")</summary>
            /// </option>
            showColumnCaptions: true,
            /// <option name="allowAggrColumns" type="Boolean" default="true">
            /// <summary>Gets or sets a value indicating whether columns panel allows user to use aggregated columns</summary>
            /// </option>
            allowAggrColumns: true,
            /// <option name="allowDuplicates" type="Boolean" default="true">
            /// <summary>Gets or sets a value indicating whether it's allowed to add exactly the same column more than once</summary>
            /// </option>
            allowDuplicates: true,
            /// <option name="allowCustomExpressions" type="Boolean" default="false">
            /// <summary>Gets or sets a value indicating whether it's allowed to use a custom expression for the column definition instead of some entity attribute.
            /// If it's turned on - a new menu item appears in the menu dropped on clicking on [f] button.
            ///</summary>
            /// </option>
            allowCustomExpressions: false,
            /// <option name="allowSorting" type="Boolean" default="true">
            /// <summary>Gets or sets a value indicating whether columns panel allows user to set columns sorting</summary>
            /// </option>
            allowSorting: true,
            /// <option name="attrElementFormat" type="String" default="'{entity} {attr}'">
            /// <summary>Gets or sets the format of the attribute display name. '{entity}' is replaced with entity name, '{attr}' is replaced with attribute name</summary>
            /// </option>
            attrElementFormat: '{entity} {attr}',
            /// <option name="titleElementFormat" type="String" default="null">
            /// <summary>
            /// Gets or sets the format of column's title display name. '{entity}' is replaced with entity name, '{attr}' is replaced with attribute name.
            /// Default value is null which means that columns panel will use the same format as it's set to attrElementFormat option
            ///</summary>
            /// </option>
            titleElementFormat: null,
            /// <option name="alwaysShowButtons" type="Boolean" default="false">
            /// <summary>Gets or sets a value indicating whether the service buttons are permanently displayed in all columns (true), or just in active column and the column user moves the cursor over (false)</summary>
            /// </option>
            alwaysShowButtons: false,
            /// <option name="accentActiveColumn" type="Boolean" default="true">
            /// <summary>Gets or sets a value indicating whether the active column should be backlighted and permanently display the service buttons</summary>
            /// </option>
            accentActiveColumn: true,
            /// <option name="menuSearchBoxAfter" type="Number" default="30">
            /// <summary>If the number of items in drop down menu exceeds this number then a search box will be displayed. Set this option to 0 if want to show the search box in any case</summary>
            /// </option>
            menuSearchBoxAfter: 30,
            /// <option name="allowDragDrop" type="Boolean" default="true">
            /// <summary>Gets or sets a value indicating whether the columns may be dragged and dropped</summary>
            /// </option>
            allowDragDrop: true,
            /// <option type="Object">
            /// <summary>
            /// Contains different options for popup menu that appears for selecting attributes in columns.\\
            /// Includes the following sub-options:
            /// </summary>
            /// <prop name="showSearchBoxAfter" type="integer" default="30">
            /// If the number of items in drop down menu exceeds this number then a search box will be displayed. 
            /// Set this option to 0 if want to show the search box in any case
            /// </prop> 
            /// <prop name="searchBoxAutoFocus" type="boolean" default="true">
            /// If true  - the SearchBox gets focus automatically when the menu level is shown.
            /// </prop>
            /// <prop name="activateOnMouseOver" type="boolean" default="true">
            /// If true  - the row in query panel will be highlighted when user moves mouse cursor over it.
            /// </prop> 
            /// <prop name="itemRenderedCallback" type="function" default="null">
            /// The callback that is called when the menu item has been rendered. It allows you to make any changes you need to the markup of the menu item.
            /// Parameters:
            ///     menuId - the ID of the menu
            ///     itemDiv - jQuery object that represents the menu item div
            /// For example, if you need to add some class:
            /// <code>
            /// itemRenderedCallbackHandler: function (menuId, itemDiv) {
            ///    itemDiv.addClass("some-cool-class");
            /// }
            /// </code>
            /// </prop>
            /// </option>
            menuOptions: {
                showSearchBoxAfter: 30,
                searchBoxAutoFocus: true,
                activateOnMouseOver: true,
                adjustHeight: true,
                itemRenderedCallback: null
            },
            /// <option name="attrPlacement" type="Integer" default="0">
            /// <summary>
            /// Defines where to display attributes in the tree:
            /// 0 - attributes are displayed after entities
            /// 1 - attributes are displayed before entities
            /// 2 - attributes and entities are mixed, and displayed in alphabetical order. In this case the "sortEntities" option value dosn't matter.
            /// </summary>
            /// </option>
            attrPlacement: 0,
            /// <option name="sortEntities" type="Integer" default="false">
            /// <summary>
            /// Defines whether entities and attributes should be sorted alphabetically. If false, they are displayed as listed in the model.
            /// </summary>
            /// </option>
            sortEntities: false,
            /// <option name="columnRenderedCallback" type="function" default="null">
            /// <summary>
            /// The callback that is called when the column's row has been rendered. It allows you to make any changes you need to the markup of the row.
            /// Parameters:
            ///     columnDiv - jQuery object that represents the column's row div
            /// For example, if you need to add some class:
            /// <code>
            /// columnRenderedCallbackHandler: function (columnDiv) {
            ///    columnDiv.addClass("some-cool-class");
            /// }
            /// </code>
            /// </summary>
            /// </option>
            columnRenderedCallback: null,
            /// <option name="customExpressionText" type="Integer" default="0">
            /// <summary>
            /// Gets or sets a value which defines what text should be used for custom expressions' links. Possible values are:
            ///   0 - show the SQL expression itself. Default behaviour.
            ///   1 - show special [Custom SQL] text.
            ///   2 - show column's title.
            /// </summary>
            /// </option>
            customExpressionText: 0,
        },
        _create: function () {
        },
        getQuery: function () {
            return this._query;
        },
        setQuery: function (query) {
            this._setQueryObserver(true); //removing old query observer
            this._query = query;
            this._setQueryObserver();
            this.refresh();
        },
        getModel: function () {
            var query = this.getQuery();
            return query ? query.getModel() : null;
        },
        getColumns: function () {
            var query = this.getQuery();
            return query ? query.getColumns() : null;
        },
        _getCssPrefix: function () {
            return "";
        },
        _customExpressionsPermitted: true,
        areCustomExpressionsAllowed: function () {
            return this.options.allowCustomExpressions && this._customExpressionsPermitted;
        },
        _render: function () {
            var self = this;
            self._clear();
            var model = this.getModel();
            self._updateLists();
            var cssClassPrefix = this._getCssPrefix();
            self.element.addClass(cssClassPrefix + '-panel');
            if (model && !model.isEmpty()) {
                self.options.entitiesList = model.getEntitiesTree({ addUIC: false, addUIR: true, addUIS: false, attrPlacement: self.options.attrPlacement, sortEntities: self.options.sortEntities });
                self.options.entitiesMenu = self._createEntitiesMenu();
                if (self.options.allowSorting != false) {
                    self.options.sortMenuList = [
                        { id: 'None', text: eqi18n.getText('CmdNotSorted') },
                        { id: 'Ascending', text: eqi18n.getText('CmdAscending') },
                        { id: 'Descending', text: eqi18n.getText('CmdDescending') },
                        { id: '---', text: '---' }
                    ];
                }
                else {
                    self.options.sortMenuList = [];
                }
                self.options.moveMenuList = [
                    { id: 'MoveTop', text: eqi18n.getText('CmdMoveToFirst') },
                    { id: 'MoveUp', text: eqi18n.getText('CmdMoveToPrev') },
                    { id: 'MoveDown', text: eqi18n.getText('CmdMoveToNext') },
                    { id: 'MoveBottom', text: eqi18n.getText('CmdMoveToLast') }
                ];
                Array.prototype.push.apply(self.options.sortMenuList, self.options.moveMenuList);
                self.options.sortMenu = self._createSortMenu();
                self.options.moveMenu = self._createSortMenu(true);
                var minusHeight = 0;
                var columns = self.getColumns();
                //Header row
                var headerCssPrefix = cssClassPrefix + "-header";
                if (self.options.showHeader != false) {
                    var headerBlock = $('<div class="' + headerCssPrefix + '"></div>')
                        .appendTo(this.element);
                    var exprBlock = $('<div class="' + headerCssPrefix + '-expression"></div>')
                        .text(eqi18n.getText('HeaderExpression'))
                        .appendTo(headerBlock);
                    if (self.options.showColumnCaptions) {
                        var titleBlock = $('<div class="' + headerCssPrefix + '-title"></div>')
                            .text(eqi18n.getText('HeaderTitle'))
                            .appendTo(headerBlock);
                    }
                    minusHeight += headerBlock.outerHeight() + 5;
                    this._headerBlock = headerBlock;
                }
                this._updateHeaderBlock();
                //Columns
                var colBlock = self._refreshByQuery(true);
                //AddRow
                if (self.options.showAddRow) {
                    var addRowBlock = $('<div class="eqjs-addrow ' + cssClassPrefix + '-addrow"></div>');
                    addRowBlock.appendTo(this.element);
                    if (!columns || columns.length === 0) {
                        addRowBlock.addClass('eqjs-addrow-empty');
                    }
                    var addRowLink = $('<a href="javascript:void(0)">' + eqi18n.getText('CmdClickToAddColumn') + '</a>');
                    addRowLink.appendTo(addRowBlock);
                    addRowLink.click(function (e) {
                        e.preventDefault();
                        self.showEntitiesMenu({
                            anchor: addRowLink,
                            selectedIds: null,
                            itemSelectedCallback: function (evt, data) {
                                var attrid = data.menuItem.id;
                                var attrobj = model.getAttributeById(attrid);
                                self.addNewColumn(attrid);
                                return false;
                            }
                        }, {});
                    });
                    minusHeight += addRowBlock.outerHeight() + 9;
                }
                if (colBlock) {
                    colBlock.show();
                    colBlock.css({ 'max-height': self.element.innerHeight() - minusHeight + 5 + 'px' });
                }
            }
        },
        _updateHeaderBlock: function () {
            if (this._headerBlock) {
                var columns = this.getColumns();
                if (columns && columns.length > 0) {
                    this._headerBlock.show();
                }
                else {
                    this._headerBlock.hide();
                }
            }
        },
        _updateLists: function () {
        },
        _setOption: function (key, value) {
            if (key == 'menuOptions') {
                this.options.menuOptions = $.extend({}, this._defaultMenuOptions, value);
            }
            else if (key == 'searchBoxAfter') {
                this.options[key] = value;
                this.options.menuOptions.showSearchBoxAfter = value;
            }
            else if (key == 'query') {
                this.setQuery(value);
            }
            else if (arguments.length == 2) {
                this.options[key] = value;
                this.refresh();
                return this;
            }
            else {
                return this.options[key];
            }
        },
        _setQueryObserver: function (remove) {
            var self = this;
            var query = this.getQuery();
            var queryObserver = function (event) {
                //if something has changed, and that is related to columns
                if (event.data && event.data.author !== self &&
                    event.data.changeType && event.data.changeType.indexOf("condition") < 0) {
                    self._render();
                }
            };
            if (query) {
                if (remove && self._queryObserverId)
                    query.removeChangedCallback(self._queryObserverId);
                else
                    self._queryObserverId = query.addChangedCallback(queryObserver);
            }
        },
        _clear: function () {
            this.element.html('');
        },
        _addColumnElement: function (columnsBlock, column, index) {
            var self = this;
            var newColBlock = $('<div></div>');
            var rows = columnsBlock.find('[class*=' + self._getCssPrefix() + '-row]');
            if (index == 0) {
                newColBlock.prependTo(columnsBlock);
            }
            else if (index > 0 && index < rows.length) {
                newColBlock.insertAfter(rows[index - 1]);
            }
            else {
                newColBlock.appendTo(columnsBlock);
            }
            if (!column.blockId) {
                this.trySetBlockId(column);
            }
            if (column.blockId) {
                newColBlock.attr('id', column.blockId);
            }
            var funcBody = "element.ColumnRow_" + column.expr.tag + "({columnsPanel: self}); " +
                "element.ColumnRow_" + column.expr.tag + "('init', column);";
            var addWidget = new Function("self, element, column", funcBody);
            addWidget(self, newColBlock, column);
            if (this.options.columnRenderedCallback) {
                this.options.columnRenderedCallback(newColBlock);
            }
        },
        _refreshByQuery: function (hide) {
            var self = this;
            if (!this.getQuery()) {
                return;
            }
            //Columns block
            var columnsBlock = $('<div></div>'), contentBlock = $('<div></div>');
            var cssClassPrefix = this._getCssPrefix();
            columnsBlock.addClass(cssClassPrefix + '-columns');
            columnsBlock.appendTo(contentBlock);
            contentBlock.appendTo(self.element);
            if (hide) {
                columnsBlock.hide();
            }
            var columns = self.getColumns();
            var colLength = columns.length;
            for (var colIdx = 0; colIdx < colLength; colIdx++) {
                self._addColumnElement(columnsBlock, columns[colIdx]);
            }
            var oldIdx, newIdx, newIdxDrop, justDropped = false, toReturn = false, draggableAttr = null, overSortable = false, overDroppable = false;
            var model = self.getModel();
            if (self.options.allowDragDrop) {
                columnsBlock.sortable({
                    containment: contentBlock,
                    tolerance: 'pointer',
                    axis: self.options.isColumnsBar ? null : 'y',
                    placeholder: "ui-state-highlight eqjs-highlight",
                    scrollSpeed: 3,
                    delay: 100,
                    distance: 13,
                    cursorAt: { top: 10 },
                    forceHelperSize: false,
                    handle: 'div, a',
                    start: function (event, ui) {
                        oldIdx = ui.item.index();
                        ui.item.addClass(cssClassPrefix + "-column-sort");
                        overSortable = true;
                    },
                    update: function (event, ui) {
                        overSortable = false;
                        if (!justDropped && !ui.item.hasClass(cssClassPrefix + "-row")) {
                            ui.item.remove();
                            return; //not a column - so do nothing
                        }
                        //var attrid = ui.item.attr("data-id");
                        //if (attrid) {
                        //    var attr = model.getAttributeById(attrid);
                        //    if (attr.uir != true) {
                        //        ui.item.remove();
                        //        return;
                        //    }
                        //}
                        newIdx = ui.item.index();
                        toReturn = false;
                        if (justDropped) {
                            self.addNewColumn(draggableAttr, newIdx);
                            ui.item.remove();
                            justDropped = false;
                        }
                        else if (oldIdx != newIdx) {
                            self.getQuery().moveColumn(oldIdx, newIdx, self);
                        }
                        ;
                    },
                    over: function (event, ui) {
                        overSortable = true;
                    },
                    out: function (event, ui) {
                        overSortable = false;
                    },
                    stop: function (event, ui) {
                        overSortable = false;
                        ui.item.removeClass(cssClassPrefix + '-column-sort');
                        return true;
                    }
                });
                self.element.droppable({
                    hoverClass: "eqjs-drophover",
                    scope: "entityAttr",
                    drop: function (event, ui) {
                        overDroppable = false;
                        var attrId = ui.draggable.attr('data-id');
                        if (!model.checkAttrProperty(attrId, "usedInResult")) {
                            return;
                        }
                        if (!overSortable) { //!columns || columns.length === 0 || 
                            self.addNewColumn(attrId);
                            self.refresh();
                        }
                        else {
                            justDropped = true;
                        }
                    },
                    over: function (event, ui) {
                        overDroppable = true;
                        ui.helper.addClass(cssClassPrefix + '-column-drag');
                        var attrId = ui.draggable.attr('data-id');
                        if (!model.checkAttrProperty(attrId, "usedInResult")) {
                            ui.helper.addClass(cssClassPrefix + '-column-drag-forbidden');
                        }
                    },
                    out: function (event, ui) {
                        overDroppable = false;
                        ui.helper.removeClass(cssClassPrefix + '-column-drag');
                        ui.helper.removeClass(cssClassPrefix + '-column-drag-forbidden');
                    },
                    activate: function (event, ui) {
                        draggableAttr = ui.draggable.attr('data-id');
                    }
                });
            }
            //(!columnsBlock.children().length) ? contentBlock.hide() : contentBlock.show();
            return columnsBlock;
        },
        /// <method name="clearColumns">
        /// <summary>Clears the list of columns in associated query and redraws a panel, if needed.</summary>
        /// <notes>
        /// This method is deprecated. Use Query.clearColumns() instead. 
        /// </notes>
        /// </method>
        clearColumns: function (needRefresh) {
            var query = this.getQuery();
            if (!query)
                return;
            query.clearColumns();
            if (needRefresh !== false)
                this.refresh();
        },
        _createEntitiesMenu: function () {
            var model = this.getModel();
            if (!model || model.isEmpty())
                return null;
            var self = this;
            var menuDiv = $('<div></div>')
                .hide()
                .appendTo(this.element);
            var menuId = self.element.attr('id');
            if (menuId) {
                menuId += '-EntitiesMenu';
            }
            var options = { "items": this.options.entitiesList, adjustHeight: self.options.adjustEntitiesMenuHeight, id: menuId, domWriteItemsId: self.options.domWriteItemsId };
            equtils.assign(options, self.options.menuOptions);
            menuDiv.PopupMenu(options);
            return menuDiv;
        },
        showEntitiesMenu: function (menuOptions, eventArgs) {
            var self = this;
            self.options.entitiesMenu.PopupMenu("showMenu", menuOptions);
        },
        _createSortMenu: function (noSorting) {
            var model = this.getModel();
            if (!model || model.isEmpty())
                return null;
            var menuDiv = $('<div></div>')
                .hide()
                .appendTo(this.element);
            var self = this;
            var menuId = self.element.attr('id');
            if (menuId) {
                menuId += '-SortMenu';
            }
            var items = noSorting ? this.options.moveMenuList : this.options.sortMenuList;
            var menuOptions = { "items": items, id: menuId, domWriteItemsId: this.options.domWriteItemsId };
            equtils.assign(menuOptions, self.options.menuOptions);
            menuDiv.PopupMenu(menuOptions);
            return menuDiv;
        },
        //_fireQueryChange: function (changeType) {
        //    var self = this;
        //    this.getQuery().fireChangedEvent({
        //        "source": self,
        //        "changeType": "query." + changeType
        //    });
        //},
        _fireColumnChange: function (changeType, column) {
            var self = this;
            column = column || self._column;
            this.getQuery().fireChangedEvent({
                "author": self,
                "changeType": "column." + changeType,
                "column": column
            });
        },
        _getDefaultColumnCaption: function (attr) {
            var format = this.options.titleElementFormat || this.options.attrElementFormat;
            var model = this.getModel();
            return model.getAttributeText(attr, format);
        },
        /// <method name="addNewColumn">
        /// <summary>Adds a new column to the query and updates the columns panel</summary>
        /// <param name="attrid" type="String (or Array of Strings)">
        /// <summary>The ID (or the array of IDs) of the attribute the new column is based on.</summary>
        /// </param>
        /// <param name="index" type="Integer">
        /// <summary>The position in the columns list the new column(s) should be inserted to. If undefined, the column is added to the end of the list.</summary>
        /// </param>
        /// <returns type="PlainObject">
        /// The added column object
        /// </returns>
        /// </method>
        addNewColumn: function (attrid, index) {
            var self = this;
            var model = this.getModel();
            var getColumnByAttrId = function (attrid) {
                var attribute = model.getAttributeById(attrid);
                if (!attribute) {
                    return null;
                }
                if (!attribute.usedInResult) {
                    if (attribute.lookupAttr) {
                        attrid = attribute.lookupAttr;
                        attribute = model.getAttributeById(attrid);
                        if (!attribute || !attribute.usedInResult) {
                            return null;
                        }
                    }
                    else
                        return null;
                }
                var column = new Column();
                column.caption = self._getDefaultColumnCaption(attribute);
                column.sorting = SortDirection.None;
                column.sortIndex = -1;
                column.expr.tag = ExprTag.EntityAttribute;
                column.expr.id = attrid;
                column.params.concat(attribute.params);
                return column;
            };
            if (!this.getQuery()) {
                return;
            }
            var colToAdd, col;
            if (Array.isArray(attrid)) {
                colToAdd = [];
                var attrLength = attrid.length;
                for (var i = 0; i < attrLength; i++) {
                    col = getColumnByAttrId(attrid[i]);
                    if (col) {
                        colToAdd.push(col);
                    }
                }
            }
            else
                colToAdd = getColumnByAttrId(attrid);
            self.addColumn(colToAdd, index);
            return colToAdd;
        },
        _checkColumn: function (col) {
            if (!this.options.allowDuplicates) {
                var query = this.getQuery();
                var columns = query.getColumns();
                var clen = columns.length;
                var colJson = JSON.stringify(col.expr);
                for (var i = 0; i < clen; i++) {
                    var qcolJson = JSON.stringify(columns[i].expr);
                    if (qcolJson === colJson) {
                        return null;
                    }
                }
            }
            return col;
        },
        _checkColumnsArray: function (cols) {
            var i = 0, len = cols.length;
            var result = [];
            for (; i < len; i++) {
                if (this._checkColumn(cols[i]))
                    result.push(cols[i]);
            }
            return result;
        },
        /// <method name="addColumn">
        /// <summary>Adds a new column to the query and updates the columns panel</summary>
        /// <param name="column" type="PlainObject (or Array of PlainObject)">
        /// <summary>The column object (or the array of such objects) to be added.</summary>
        /// </param>
        /// <param name="index" type="Integer">
        /// <summary>The position in the columns list the new column(s) should be inserted to. If undefined, the column is added to the end of the list.</summary>
        /// </param>
        /// </method>
        addColumn: function (column, index) {
            var self = this;
            var query = this.getQuery();
            if (!query) {
                return;
            }
            if (Array.isArray(column))
                column = this._checkColumnsArray(column);
            else
                column = this._checkColumn(column);
            if (!column || (Array.isArray(column) && column.length == 0)) {
                return;
            }
            query.addColumnObj(column, index, self);
            var columnsBlock = self.element.find('[class*=' + self._getCssPrefix() + '-columns]');
            if (columnsBlock.length > 0) {
                var columns = column;
                if (columns.length) {
                    var i;
                    for (i = 0; i < columns.length; ++i) {
                        self._addColumnElement(columnsBlock, columns[i], index + i);
                    }
                }
                else {
                    self._addColumnElement(columnsBlock, column, index);
                }
                this._updateHeaderBlock();
            }
            else {
                self.refresh();
            }
            //self._fireColumnChange("add", column);
        },
        trySetBlockId: function (col) {
            var blockId = this.getNewColId();
            if (blockId) {
                col.blockId = blockId;
            }
        },
        /// <method name="removeColumn">
        /// <summary>Remove the column object from the list of columns and updates the columns panel</summary>
        /// <param name="column" type="PlainObject">
        /// <summary>The column object to be removed.</summary>
        /// </param>
        /// </method>
        removeColumn: function (column) {
            var self = this;
            var query = this.getQuery();
            if (!query || !column) {
                return;
            }
            var columnArr = column;
            if (columnArr.length) {
                var i;
                for (i = 0; i < columnArr.length; ++i) {
                    self._removeColumnElement(columnArr[i]);
                }
                query.removeColumns(columnArr, this);
            }
            else {
                self._removeColumnElement(column);
                query.removeColumn(column, this);
            }
        },
        _removeColumnElement: function (column) {
            var cssClassPrefix = this._getCssPrefix();
            var query = this.getQuery();
            var columns = query.getColumns();
            var index = columns.indexOf(column);
            if (index >= 0) {
                var colElement = this.element.find('[class*=' + cssClassPrefix + '-row]')
                    .filter(function (index) {
                    return (this.column == column);
                });
                if (colElement) {
                    colElement.detach();
                    colElement.remove();
                }
            }
        },
        /// <method name="removeColumnByAttrId">
        /// <summary>Remove the column object from the list of columns and updates the columns panel</summary>
        /// <param name="attrId" type="String">
        /// <summary>The ID of the attribute. The first found column with such an attribute ID will be removed.</summary>
        /// </param>
        /// </method>
        removeColumnByAttrId: function (attrId) {
            var self = this;
            var isColumn;
            if (Array.isArray(attrId)) {
                isColumn = function (id) {
                    var arrLen = attrId.length;
                    for (var i = 0; i < arrLen; i++) {
                        if (attrId[i] == id) {
                            return true;
                        }
                    }
                    return false;
                };
            }
            else {
                isColumn = function (id) {
                    return attrId == id;
                };
            }
            var query = this.getQuery();
            if (!query) {
                return;
            }
            var colsToRemove = [];
            var index = 0;
            var columns = query.getColumns();
            var colCount = columns.length;
            while (index < colCount) {
                var col = columns[index];
                if (col.expr.tag == ExprTag.EntityAttribute && isColumn(col.expr.id)) {
                    colsToRemove.push(columns[index]);
                }
                index++;
            }
            self.removeColumn(colsToRemove);
        },
        _moveColumn: function (index1, index2) {
            var self = this;
            var query = this.getQuery();
            if (!query)
                return;
            var columnsBlock = self.element.find('[class*=' + self._getCssPrefix() + '-columns]');
            var rows = columnsBlock.find('[class*=' + self._getCssPrefix() + '-row]');
            var colToMove = $(rows[index1]);
            if (index2 == 0) {
                colToMove.prependTo(columnsBlock);
            }
            else if (index2 > 0 && index2 < rows.length - 1) {
                if (index1 < index2) {
                    colToMove.insertAfter(rows[index2]);
                }
                else {
                    colToMove.insertAfter(rows[index2 - 1]);
                }
            }
            else {
                colToMove.appendTo(columnsBlock);
            }
            query.moveColumn(index1, index2, self);
        },
        /// <method name="moveColumn">
        /// <summary>Moves the column object from its current position to specified direction</summary>
        /// <param name="column" type="PlainObject">
        /// <summary>The column object to be moved.</summary>
        /// </param>
        /// <param name="direction" type="String">
        /// <summary>One of the following: 'MoveTop', 'MoveUp', 'MoveDown', 'MoveBottom'</summary>
        /// </param>
        /// </method>
        moveColumn: function (column, direction) {
            var self = this;
            var query = this.getQuery();
            var columns = query.getColumns();
            var index = columns.indexOf(column);
            if (index >= 0) {
                switch (direction) {
                    case 'MoveTop':
                        if (index == 0) {
                            return;
                        }
                        self._moveColumn(index, 0);
                        break;
                    case 'MoveUp':
                        if (index == 0) {
                            return;
                        }
                        self._moveColumn(index, index - 1);
                        break;
                    case 'MoveDown':
                        if (index == columns.length - 1) {
                            return;
                        }
                        self._moveColumn(index, index + 1);
                        break;
                    case 'MoveBottom':
                        if (index == columns.length - 1) {
                            return;
                        }
                        self._moveColumn(index, columns.length - 1);
                        break;
                }
                ;
            }
        },
        /// <method name="refresh">
        /// <summary>Re-renders the panel</summary>
        /// </method>
        refresh: function () {
            this._render();
        },
        resize: function () {
            this._render();
        },
        /// <method name="setActiveColumnWidget">
        /// <summary>Activates the particular column in the panel</summary>
        /// <param name="columnWidget" type="Object">
        /// <summary>The ColumnRow_ENTATTR or ColumnRow_AGGRFUNC object to activate.</summary>
        /// </param>
        /// </method>
        setActiveColumnWidget: function (columnWidget) {
            this.deactivateColumnWidget();
            this._activeColumnWidget = columnWidget;
            if (this._activeColumnWidget) {
                this._activeColumnWidget.internalActivate();
                this.options.activeColumn = this._activeColumnWidget.getColumn();
            }
        },
        deactivateColumnWidget: function () {
            if (this._activeColumnWidget) {
                this._activeColumnWidget.internalDeactivate();
                this.options.activeColumn = null;
            }
        },
        getNewColId: function () {
            if (this.element.attr('id')) {
                return this.element.attr('id') + '-col-' + ++this._globalColCounter;
            }
        }
    });
    $.widget("eqjs.ColumnsPanel", $.eqjs.ColumnsContainer, {
        _getCssPrefix: function () {
            return "eqjs-qc";
        }
    });
    $.widget("eqjs.ColumnsBar", $.eqjs.ColumnsContainer, {
        _create: function () {
            this.options.showHeader = false;
            this.options.isColumnsBar = true;
        },
        _getCssPrefix: function () {
            return "eqjs-cb";
        },
        _customExpressionsPermitted: false
    });
    $.widget("eqjs.SortingBar", $.eqjs.ColumnsContainer, {
        _create: function () {
            this.options.allowDragDrop = false;
            this.options.showHeader = false;
            this.options.accentActiveColumn = false;
        },
        moveColumn: function (column, direction) {
            var self = this;
            var query = this.getQuery();
            var columns = query.getSortedColumns();
            var index = $.inArray(column, columns);
            if (index >= 0) {
                switch (direction) {
                    case 'MoveTop':
                        if (index == 0) {
                            return;
                        }
                        equtils.moveArrayItem(columns, index, 0);
                        break;
                    case 'MoveUp':
                        if (index == 0) {
                            return;
                        }
                        equtils.moveArrayItem(columns, index, index - 1);
                        break;
                    case 'MoveDown':
                        if (index == columns.length - 1) {
                            return;
                        }
                        self._moveColumn(index, index + 1);
                        equtils.moveArrayItem(columns, index, index + 1);
                        break;
                    case 'MoveBottom':
                        if (index == columns.length - 1) {
                            return;
                        }
                        equtils.moveArrayItem(columns, index, columns.length - 1);
                        break;
                }
                ;
                columns.forEach(function (item, i, arr) {
                    item.sortIndex = i;
                });
                query.fireChangedEvent("query.column.sorting", 100);
                self.refresh();
            }
        },
        getColumns: function () {
            var query = this.getQuery();
            return query.getSortedColumns();
        },
        _getCssPrefix: function () {
            return "eqjs-srtb";
        },
        _customExpressionsPermitted: false
    });
}
//# sourceMappingURL=eq.columnspanel.js.map