/*jslint node: true */
/*jslint browser: true*/
/*jslint nomen: true*/
/*global angular, BaseController, CFE_mapping, defaultSQL, alert, $, common*/

'use strict';

var inventoryController = BaseController.extend({
    /**
     * Initialize  Controller
     * @param $scope
     * @param $q
     * @param $location
     * @param $routeParams
     * @param $http
     * @param reportService
     * @param inventoryService
     * @param paginationService
     * @param commonHelper
     * @param inventoryHelper
     * @param notificationService
     * @param wizardSharedService
     * @param modalWindowService
     * @param inventoryDataService
     * @param inventoryFilterService
     */

    init: function ($scope, $q, $location, $routeParams, $http, reportService, inventoryService, paginationService,
                    commonHelper, inventoryHelper, notificationService, wizardSharedService, modalWindowService,
                    inventoryDataService, inventoryFilterService, $rootScope, $modal) {
        var self = this;
        this._super($scope);
        this._reportService = reportService;
        this._inventoryService = inventoryService;
        this._inventoryFilterService = inventoryFilterService;
        this._inventoryDataService = inventoryDataService;
        this._notificationService = notificationService;
        this._commonHelper = commonHelper;
        this._inventoryHelper = inventoryHelper;
        this.$modal = $modal;

        this.$scope.paginator = paginationService;
        this.$location = $location;
        this._$q = $q;
        this.$http = $http;
        this.$routeParams = $routeParams;


        this._wizardSharedService = wizardSharedService;
        this.$scope.modalWindow = modalWindowService;


        self.$scope.Math = Math;
        self.$scope.showFilter = false;
        self.$scope.showAllFilters = true;

        // see invenory_data_addons
        self.$scope.CFE_Mapping_addFields = CFE_Mapping_addFields;
        self.$scope.CFE_Mapping_removeFields = CFE_Mapping_removeFields;
        self.$scope.CFE_Mapping_addToFilters = CFE_Mapping_addToFilters;
        self.$scope.selectDefaultColumns = this.$routeParams.columns != undefined && this.$routeParams.columns.length > 0 ?  this.$routeParams.columns.split(',') :  selectDefaultColumns;
        self.$scope.urlFilter = this.$routeParams.filter != undefined && this.$routeParams.filter.length > 0 ?
            JSON.parse(this.$routeParams.filter) :
            null;
        self.$scope.groupFilters = this.$routeParams.group_filters != undefined && this.$routeParams.group_filters.length > 0 ?
            JSON.parse(this.$routeParams.group_filters) :
            null;
        self.$scope.searchQuery = this.$routeParams.searchQuery ?? null;

        self.$scope.display = false;

        self.$scope.notifications = {};


        self.$scope.alertData   = {};
        self.$scope.hostcontexts = {};
        self.$scope.excludedHosts = '';
        self.$scope.hostselectionstate = (this.$routeParams.include === undefined) ? {} : {hostkey: [this.$routeParams.include]};

        self.$scope.showEnvironmentFilterButtons = true;


        self.$scope.UI = {};
        self.$scope.SQL = {};

        self.$scope.SQL.filters = [];
        self.$scope.SQL.columns = [];
        self.$scope.SQL.selectedGroup = undefined;
        self.$scope.filters = [];
        self.$scope.selectedCols = [];
        self.$scope.SQL.entriesFilter = {includes: {...self.$scope.hostselectionstate}, excludes: {}};

        self.$scope.reportRoles = {};

        self.$scope.roles = this._commonHelper.getRolesArray();
        self.$scope.is_admin = self._commonHelper.checkifAdmin(self.$scope.roles);

        self.$scope.savedSearchName = {};
        self.$scope.savedSearchCategory = {};
        self.$scope.savedSearchCategory.input = 'inventory';
        self.$scope.reportCategory = self.$scope.savedSearchCategory.input;

        self.$scope.is_public = {};

        self.$scope.reportId = '';
        self.$scope.reportLabel = '';

        self.$scope.is_own = 1;
        self.$scope.can_edit = 1;
        self.$scope.can_edit_columns = 1;
        self.$scope.can_delete = 1;
        self.$scope.readonly = 0;
        self.$scope.is_public.input = 0;
        self.$scope.show_buttons = 1;

        self.$scope.initializing = true;

        self._initVIEWParams();

        $rootScope.$on('inv_variables_loaded', function (event, data) {
            // set variable type for inventory filter
            if (self.$scope.urlFilter !== null) {
                const variable = data[`attribute_name=attribute_name=${self.$scope.urlFilter.label}`];
                if (variable != undefined) {
                    self.$scope.urlFilter.type = variable.type;
                }
            }
        });

        self.$scope.$watch('selectedCols', function (newValue, oldValue) {
            // get difference after check/uncheck
            if (!self.$scope.initializing) {
                var diff = $(newValue).not(oldValue).get();
                if (!diff.length) {
                    diff = $(oldValue).not(newValue).get();

                    // column has been removed - clear sortColumn if it equals a removed column
                    angular.forEach(diff, function (key, value) {
                        if (key === self.$scope.VIEW.sortColumn) {
                            self.$scope.VIEW.sortColumn = '';
                        }
                    });
                }

                if (diff.length === 1) {
                    // avoid calling on initial load of saved report or default columns
                    var pos = newValue.indexOf(diff[0]);
                    self.$scope.$broadcast('modifyColumn_EVENT', diff[0], pos);
                }
            }

        }, true);
        self._resetChart();
    },

    _loadReport_or_RunDefault: function () {
        var self = this;

        if (self.$routeParams.reportid) {
            self._loadReport(self.$routeParams.reportid);
        }
        else if (self.$scope.searchQuery) {
            self.$scope.SQL.filters = [self._inventoryFilterService.filterFromSearchQuery(self.$scope.searchQuery)]
            self.$scope.selectedCols = self.$scope.selectDefaultColumns;
            self.$scope.$broadcast('runDefaultReport_EVENT', self.$scope.selectDefaultColumns);
        }
        else if (self.$routeParams.alertid) {
            self._loadInventoryAlert(self.$routeParams.alertid);
        }
        else if (self.$scope.groupFilters) {
            self.$scope.selectedCols = self.$scope.selectDefaultColumns;
            self.$scope.$broadcast('runDefaultReport_EVENT', self.$scope.selectDefaultColumns);
        }
        else if (sessionStorage.getItem('inventory_sql')) {
            // if not a saved report, but a page refresh/reload from browser back navigation
            self.$scope.SQL = JSON.parse(sessionStorage.getItem('inventory_sql'));
            self._updateSelectedColumnsAndSyncWithDCA(self.$scope.SQL.columns);
            self._getTableData();
        }
        else {
            self.$scope.is_own = 1;
            self.$scope.can_edit = 1;
            self.$scope.selectedCols = self.$scope.selectDefaultColumns;
            self.$scope.$broadcast('runDefaultReport_EVENT', self.$scope.selectDefaultColumns);
        }

        self._wizardSharedService.reportPropertiesChanged(self._commonHelper.getReportData(self.$scope));
    },

    _resetChart: function () {
        var self = this;
        self.$scope.chartConfig = {
            chart: {
                type: 'pie',
                backgroundColor: 'transparent',
                height: '360',
            },
            exporting: {
                enabled: false
            },
            plotOptions: {
                column: {
                    allowPointSelect: true,
                    cursor: 'pointer'
                },
                pie: {
                    allowPointSelect: true,
                    cursor: 'pointer',
                    colors: ['#646EB7', '#274BA7', '#FEDB3E', '#F5821F', '#F89B56', '#F2CDB5','#E5E5E5'],
                    dataLabels: {
                        enabled: true,
                        format: '<b>{point.name}</b>: {y}'
                    }
                }
            },
            tooltip: {
                formatter: function () {
                    if (this.percentage) {
                        return '<b>' + this.point.name + '</b><br/>Hosts: ' + this.y + '<br/>' + this.percentage.toFixed(1) + '%';
                    } else {
                        return '<b>' + this.point.name + '</b><br/>Hosts: ' + this.y;
                    }
                }
            },
            legend: {
                enabled: false
            }
            ,
            series: [{
                data: []
            }],
            title: {
                text: ''
            },
            subtitle: {
                text: 'by # hosts'
            },
            xAxis: {
                categories: [],
                title: {
                    text: null
                },
                allowDecimals: false
            },
            yAxis: {
                allowDecimals: false,
                min: 0,
                title: {
                    text: '# hosts'
                }
            },
            credits: {
                enabled: false
            },
            loading: false
        };
    },
    _loadReport: function (reportid) {
        var self = this;
        var $scope = self.$scope;
        self._reportService.loadReport(reportid).then(
            function (result) {
                var data = result.data;
                var formData = angular.fromJson(data['AdvancedReportsData']);

                if (formData.SQL !== undefined) {
                    $scope.SQL = {...$scope.SQL, ...angular.fromJson(formData.SQL)};
                    // transform hostsFilters into entriesFilter
                    if ($scope.SQL.hasOwnProperty('hostsFilters')) {
                        $scope.SQL.entriesFilter = self._inventoryFilterService.hostsFilterToEntries($scope.SQL.hostsFilters);
                        delete $scope.SQL.hostsFilters;
                    }
                    self._updateSelectedColumnsAndSyncWithDCA($scope.SQL.columns);
                    self.$scope.filters = angular.copy($scope.SQL.filters);
                    self._wizardSharedService.scopeStateChanged(self.$scope.SQL);
                }

                $scope.reportLabel = data.label;
                $scope.reportId = reportid;
                $scope.savedSearchName.input = data.label;

                $scope.can_edit = data.can_edit;
                $scope.can_delete = data.can_delete;
                $scope.is_own = data.is_own;
                $scope.readonly = data.readonly;
                $scope.is_public = {};
                $scope.is_public.input = Boolean(data.is_public);
                $scope.loadedSearch = true;
                $scope.reportRolesTMP = (data.sharedPermission !== undefined ? angular.fromJson(data.sharedPermission) : {});

                angular.forEach($scope.reportRolesTMP, function (key, value) {
                    $scope.reportRoles[key] = true;
                });

                self._wizardSharedService.reportPropertiesChanged(self._commonHelper.getReportData(self.$scope));
                self.$scope.$broadcast('reportLoaded_EVENT', self.$scope.SQL);
            },
            function (error) {
                var reportError = self._notificationService.createObjectForNotification('error', 500, 'Unable to load report');
                self._notificationService.setNotification(reportError.type, reportError.data);
            });
    },

    _loadInventoryAlert: function (alertid) {
        var self = this;
        var $scope = self.$scope;
        self._reportService.loadInventoryAlert(alertid).then(
            function (result) {
                var data = result.data;
                var formData;
                var tmp = {};

                tmp.SQL = {};
                tmp.SQL.filters = [];
                tmp.SQL.columns = [];

                tmp.SQL.filters = data.rule.inventoryConditions.filters;
                tmp.SQL.columns = data.rule.inventoryConditions.columns;

                angular.forEach(tmp.SQL.columns, function (field, index) {
                    tmp.SQL.columns[index]['selected'] = true;
                });

                $scope.SQL = tmp.SQL;
                self._updateSelectedColumnsAndSyncWithDCA($scope.SQL.columns);
                self.$scope.filters = angular.copy($scope.SQL.filters);
                self._wizardSharedService.scopeStateChanged(self.$scope.SQL);


                $scope.reportLabel = data.alert.name;
                //$scope.reportId = reportid;
                $scope.savedSearchName.input = data.alert.name;

                $scope.can_edit = 1;
                $scope.can_delete = 0;
                $scope.is_own = 1;
                $scope.readonly = 0;
                $scope.is_public = {};
                $scope.is_public.input = 1;
                $scope.loadedSearch = false;
                $scope.reportRolesTMP = {};


                var hostcontexts = {};

                hostcontexts = data.alert.hostContexts ? data.alert.hostContexts : {};


                self.$scope.SQL.hostcontexts = hostcontexts;
                self.$scope.hostcontexts = hostcontexts;

                var excludedHosts = data.alert.excludedHosts ? data.alert.excludedHosts : '';

                self.$scope.SQL.excludedHosts = excludedHosts;
                self.$scope.excludedHosts = excludedHosts;

                self.$scope.alertData.hostContexts = hostcontexts;
                self.$scope.alertData.excludedHosts = excludedHosts;

                var contextTmp = {};
                contextTmp.hostContexts = hostcontexts || '';
                contextTmp.excludedHosts = excludedHosts || '';
                self.$scope.hostselectionstate = contextTmp;

                self._wizardSharedService.reportPropertiesChanged(self._commonHelper.getReportData(self.$scope));
                self.$scope.$broadcast('reportLoaded_EVENT', self.$scope.SQL);
            },
            function (error) {
                var reportError = self._notificationService.createObjectForNotification('error', 500, 'Unable to load report');
                self._notificationService.setNotification(reportError.type, reportError.data);
            });
    },

    /*restore columns - load only id from saved report and map to self.$scope.CFE_mapping*/
    _updateSelectedColumnsAndSyncWithDCA: function (data) {
        var self = this;
        var colArray = [];
        /*properties for UI object synced with directive*/
        angular.forEach(data, function (field, index) {

            // sync with DCA.
            // Overwrite similar properties with value from DCA. This works almost like merge + extend
            // by doing this we can be sure that report is always up-to-date to the current state of field vocabulary and DCA
            // NOTE: in this case - DCA is the only source of information about field label, type etc
            if (self.$scope.UI.CFE_mapping[field.attribute_name]) {
                angular.forEach(self.$scope.UI.CFE_mapping[field.attribute_name], function (itemPropertyValue, itemPropertyName) {
                    if (itemPropertyName !== '$$hashKey') { // skip hashkey field
                        field[itemPropertyName] = itemPropertyValue;
                    }
                });
            }

            // add item to selected cols, needed for chosen
            colArray.push(field.label);

            // update UI form
            if (self.$scope.UI.CFE_mapping[field.attribute_name]) {
                self.$scope.UI.CFE_mapping[field.attribute_name].selected = true;
            }
        });
        self.$scope.selectedCols = colArray;
    },
    defineScope: function () {
        this.$scope.instance = "inventoryController";

        this.$scope.modifyColumn = this.modifyColumn.bind(this);

        this.$scope.sortReorder = this.sortReorder.bind(this);
        this.$scope.sortCategory = this.sortCategory.bind(this);

        this.$scope.scheduleReport = this.scheduleReport.bind(this);
        this.$scope.saveReport = this.saveReport.bind(this);
        this.$scope.copyReport = this.copyReport.bind(this);

        this.$scope.clearAll = this.clearAll.bind(this);

        this.$scope.setChartData = this.setChartData.bind(this);
        this.$scope.exportChart = this.exportChart.bind(this);

        this.$scope.openInsertColumnDialog = this.openInsertColumnDialog.bind(this);

        this.$scope.colSelected = this.colSelected.bind(this);
        this.$scope.noSort = this.noSort.bind(this);

        this.$scope.highlightSearch = this.highlightSearch.bind(this);

        //TODO: refactor
        this.$scope.roles_disablePublicReport = this.roles_disablePublicReport.bind(this);
        this.$scope.publicReport_disableRoles = this.publicReport_disableRoles.bind(this);

        this.$scope.runReport = this.runReport.bind(this);
    },

    exportChart: function (type) {
        var self = this;
        var charts1 = $('#chart1').highcharts(); // not ideal way to get highcharts object
        switch (type) {
            case 'print':
                charts1.print();
                break;
            case 'img':
                charts1.exportChartLocal({type: "image/png"});
                break;
        }
    },

    openInsertColumnDialog: function () {
        let self = this;

        this.hostListModalInstance = self.$modal.open({
            templateUrl: 'insertColumnsModal.html',
            backdrop: 'static',
            windowClass: 'insert-inventory-column-modal',
            keyboard: true,
            controller: function ($scope, $modalInstance, $parent) {
                $scope.data = {searchAttribute: ''};
                $scope.UI = $parent.$scope.UI;
                $scope.selectedCols = angular.copy($parent.$scope.selectedCols);
                $scope.noSort = $parent.$scope.noSort;
                $scope.highlightSearch = $parent.$scope.highlightSearch;

                $scope.sortableColumnsConfig = {
                    cancel: ".unsortable",
                    items: "li:not(.unsortable)",
                    tolerance: "pointer",
                    handle: ".active-column-sortable",
                    placeholder: "inventory-column-placeholder",
                    start: function (e, ui) {
                        ui.placeholder.width(ui.item.width() + 24); // add 24px padding to the width
                    }
                };

                $scope.isColumnSelected = name => $scope.selectedCols.includes(name);

                $scope.close = () => $modalInstance.close('cancel');
                $scope.resetColumn = () => {
                    $scope.selectedCols = angular.copy($parent.$scope.selectDefaultColumns);
                }
                $scope.removeColumn = index => $scope.selectedCols.splice(index, 1);

                $scope.apply = () => {
                    $parent.$scope.$broadcast('modifyColumns_EVENT', $scope.selectedCols);
                    $parent.$scope.initializing = true;
                    $parent.$scope.selectedCols = $scope.selectedCols;
                    $scope.close()
                }
            },
            resolve: {
                $parent: function () {
                    return self;
                },
            }
        });
    },

    modifyColumn: function (field) {
        var self = this;
        self.$scope.$broadcast('modifyColumn_EVENT', field);
    },

    highlightSearch: function (text, search) {
        if (!search) {
            return text;
        }
        let reg = new RegExp('('+search+')', 'gi');
        return text.replace(reg, '<strong>$1</strong>');
    },

    defineListeners: function () {
        var self = this;

        self.$scope.$on("runQuery_EVENT", function (event) {
            self._getTableData();
        });

        self.$scope.$on('paginatorChange', function () {
            self._getTableData('paging');
        });

        self.$scope.$on('clearFilters_EVENT', function () {
            self.$scope.$broadcast('clearAll_EVENT');
        });

        self.$scope.$on('inventoryDirectiveReady_EVENT', function (event) {
            self._loadReport_or_RunDefault();
        });

        self.$scope.$on('inventory_variables_loaded', function (event,data) {
            let attrs = {};
            for(const property in data.CFE_mapping) {
                attrs[data.CFE_mapping[property].label] = data.CFE_mapping[property];
            }
            self.$scope.inventoryAttributes = attrs;
        });

        self.$scope.$on("hostContextApply_Event", function (event, hostContextObj) {
            // because for the inventory context filter combined with field filter we do the following:
            // 1. get hostcontext
            // 2. broadcast event to recalculate filter
            self.$scope.SQL.hostcontexts = angular.copy(hostContextObj.hostcontexts);
            self.$scope.SQL.hostcontextsprofileid = angular.copy(hostContextObj.hostcontextsprofileid);
            self.$scope.SQL.hostcontextspath = angular.copy(hostContextObj.hostcontextspath);
            self.$scope.hostcontexts = self.$scope.SQL.hostcontexts;
            self.$scope.alertData.hostContexts = self.$scope.SQL.hostcontexts;
            self._wizardSharedService.reportPropertiesChanged(self._commonHelper.getReportData(self.$scope));
            self.$scope.$broadcast('environmentFilter_EVENT');
        });

        self.$scope.$on('environmentExcludeChanged_Event', function(event, excludedHosts) {
            if (Object.keys(excludedHosts).length)
            {
                self.$scope.alertData.excludedHosts = {name: Object.values(excludedHosts).join(', '), excludes: Object.keys(excludedHosts)};
                self.$scope.SQL.excludedHosts = {name: Object.values(excludedHosts).join(', '), excludes: Object.keys(excludedHosts)};
                self.$scope.excludedHosts = {name: Object.values(excludedHosts).join(', '), excludes: Object.keys(excludedHosts)};
            }
            else {
                self.$scope.alertData.excludedHosts = '';
                self.$scope.excludedHosts = '';
                self.$scope.SQL.excludedHosts = '';
            }
        });

        (function handleOutsideOfFilterClick() {
            let timeout;
            const filterTree = document.querySelector('#filterTree');

            // closes filter when outside of filter container or button click
            const clickOutsideFilterHandler =  e => {
                if (
                    !e.target.closest('#filterTree') &&
                    !e.target.classList.contains('inv-filter') &&
                    !e.target.closest('.inv-filter') &&
                    !e.target.closest('.modal.include') &&
                    e.target.parentNode !== null &&
                    !e.target.classList.contains('dnc')
                ) {
                    self.$scope.showFilter = false;
                    self.$scope.$apply();
                }
            };

            // re-add the event listener that handles a click outside of filters
            // otherwise, newly added DOM elements will not properly see their closest
            // use a 200 ms threshold to avoid redundant operations
            function handleFilterTreeMutation() {
                clearTimeout(timeout);
                document.removeEventListener('click', clickOutsideFilterHandler);
                timeout = setTimeout(() => document.addEventListener('click', clickOutsideFilterHandler), 200);
            }

            const observer = new MutationObserver(handleFilterTreeMutation);

            // observe filter tree changes to childList
            observer.observe(filterTree, { childList: true, subtree: true });
        })()
    },
    clearAll: function () {
        var self = this;
        self.$scope.SQL.selectedGroup = undefined;
        sessionStorage.removeItem('inventory_sql');
        self.$scope.groupFilters = null
        self._initVIEWParams();
        self.$scope.currentChart = {};
        self._resetChart();
        self.$scope.$broadcast('clearAll_EVENT');
        self.$scope.$broadcast('runDefaultReport_EVENT',self._getColumns());
    },
    scheduleReport: function () {
        var self = this;
        self._wizardSharedService.scopeStateChanged(self.$scope.SQL);
        self._wizardSharedService.reportPropertiesChanged(self._commonHelper.getReportData(self.$scope));
        var url = '/report/schedule';
        if (self.$scope.reportId !== undefined && self.$scope.reportId !== '') {
            url = url + '/' + self.$scope.reportId;
        }
        self.$location.path(url);
    },
    saveReport: function (isOverwrite) {
        var self = this;

        self.$scope.$broadcast('updateVariablesDictionary_EVENT');

        self._commonHelper.saveReport(isOverwrite, self.$scope, 'inventory-result');
    },
    sortCategory: function (column) {
        var self = this;

        if (column.category === 'Hardware') {
            return 0;
        }
        if (column.category === 'Software') {
            return 1;
        }
        if (column.category === 'Network') {
            return 2;
        }
        if (column.category === 'User defined') {
            return 3;
        }
        if (column.category === 'Missing attribute_name') {
            return 4;
        }
    },

    _getTableData: async function (action) {
        var self = this;

        if (self.$scope.groupFilters !== null && self.$scope.SQL.filters.length == 0) {
            self.$scope.SQL.filters = await self._inventoryFilterService.convertFilterObjectToFilters(
                self.$scope.groupFilters,
                self.$scope.UI.CFE_mapping
            );

            self.$scope.SQL.entriesFilter = {
                ...{includes: (self.$scope.groupFilters.hostFilter?.includes?.entries || {})},
                ...{excludes: (self.$scope.groupFilters.hostFilter?.excludes?.entries || {})}
            };
        }

        self._runQuery(action).then(
            function (result) {
                self.$scope.result = self._commonHelper.removeHostkeyFromResult(result.data);
                // do not reset table header and sorting params if result table column headers are the same
                if (action !== 'reorder' && action !== 'paging' && action !== 'environmentFilter') {
                    self._initVIEWParams();

                    angular.forEach(self.$scope.result.header, function (field, key) {
                        var tmp = {};
                        tmp.name = field.columnName;
                        tmp.type = self.$scope.inventoryAttributes[field.columnName] !== undefined ?
                            self.$scope.inventoryAttributes[field.columnName].type :
                            field.columnType;

                        tmp.sort = 0;
                        tmp.fieldIndex = key;
                        tmp.nameToSort = tmp.name + '_' + key;
                        self.$scope.VIEW.tablehead.push(tmp);
                    });
                }

                self.$scope.VIEW.rows = self.$scope.result.rows;
                self.$scope.VIEW.rowCount = self.$scope.result.rowCount;
                self.$scope.paginator.refreshPaginator(result.data.rowCount);

                if (self.$scope.result.rowCount === 0) {
                    var error = self._notificationService.createObjectForNotification('warning', 505, 'Query returned 0 rows');
                    self._notificationService.setNotification(error.type, error.data);
                }

                self.$scope.display = true;
                // allow checking/unchecking columns to update
                self.$scope.initializing = false;
                self.$scope.originalFilters = angular.copy(self.$scope.SQL.filters);
                const excludedHosts = self.$scope.SQL.entriesFilter ? Object.values(self.$scope.SQL.entriesFilter.excludes).reduce((acc, curr) => acc + curr.length, 0) : 0;
                const includedHosts = self.$scope.SQL.entriesFilter ? Object.values(self.$scope.SQL.entriesFilter.includes).reduce((acc, curr) => acc + curr.length, 0) : 0;
                self.$scope.originalFiltersLength = self.$scope.originalFilters.length + Number(!!excludedHosts) + Number(!!includedHosts);
            },
            function (error) {
                // error getting result data
            }
        );
    },
//////////////////////////////////////////////////////////////////////////////////////////////////////////////777

    _runQuery: function (action) {
        var self = this, data = '';
        self._notificationService.resetNotification();

        self.$scope.SQL.hostcontexts = self.$scope.hostcontexts || '';
        self.$scope.SQL.excludedHosts = self.$scope.excludedHosts || '';

        if (self.$scope.urlFilter !== null && self.$scope.SQL.filters.length == 0) {
            self.$scope.SQL.filters = [self.$scope.urlFilter];
        }

        var rowLimit = self.$scope.paginator.rowsPerPage;
        var skip = self.$scope.paginator.skip;

        // reset pagination to default if this is new query
        if (action !== 'reorder' && action !== 'paging' && action !== 'environmentFilter' && action !== 'chart') {
            self.$scope.paginator.paginationReset();
        }

        if (action === 'chart') {
            // no limit for chart data
            rowLimit = null;
            skip = 0;
        }

        let contextIncludes = (self.$scope.SQL.hostcontexts && self.$scope.SQL.hostcontexts.includes !== undefined ?  self.$scope.SQL.hostcontexts.includes : []);
        const params = {
            select: self._getColumns(),
            sort: self._getSort(),
            filter: self._inventoryFilterService.processFilters(self.$scope.SQL.filters),
            hostFilter: self._inventoryFilterService.processEntriesFilters(self.$scope.SQL),
            group: self.$scope.SQL.selectedGroup,
            start: skip,
            limit: rowLimit,
            showSQL: true,
            hostContextInclude: [...contextIncludes, ...self._inventoryFilterService.processClassFilters(self.$scope.SQL.filters)],
            hostContextExclude: (self.$scope.SQL.excludedHosts && self.$scope.SQL.excludedHosts.excludes !== undefined ? self.$scope.SQL.excludedHosts.excludes : []),
        };

        return self._inventoryDataService.getData(params).then(
            function (result) {
                self._updateSQLSTRING(result.data.query);
                common.globalSpinner.hide();
                return result;
            },
            function (error) {
                error.data[0].text = error.data[0].text || 'Error encountered.Please view the logs for more detailed information.';
                self._notificationService.setNotification('error', error.data);
                common.globalSpinner.hide();
            }
        );
    },

    _updateSQLSTRING: function(sql){
        this.$scope.SQL.SQLSTRING = sql;
    },

    _getSort: function () {
        var self = this,
            sort = self.$scope.VIEW.sortColumn || '';

        if(sort !== '' && !self.$scope.VIEW.sortDescending ){
            sort = '-' + sort;
        }
        return sort;
    },

    _getColumns: function () {
        let self = this;
        return self.$scope.SQL.hasOwnProperty('columns') ? self.$scope.SQL.columns.map(function (e) {
            return e['attribute_name'].replace('attribute_name=', '');
        }) : self.$scope.selectDefaultColumns;
    },

    _initVIEWParams: function () {
        var self = this;
        self.$scope.VIEW = {};

        self.$scope.VIEW.sortColumn = '';
        self.$scope.VIEW.sortDescending = 0;
        self.$scope.VIEW.tablehead = [];
    },

    sortReorder: function (col, e) {
        var self = this;
        angular.forEach(self.$scope.VIEW.tablehead, function (el) {
            if (el.nameToSort === col) {
                el.sort = el.sort > 0 ? -1 : 1;
                self.$scope.VIEW.sortColumn = el.name;
                self.$scope.VIEW.sortDescending = el.sort > 0 ? 0 : 1;
            } else {
                el.sort = null;
            }
        });

        if (self.$scope.VIEW.sortColumn !== undefined && self.$scope.VIEW.sortColumn !== '') {
            self._getTableData('reorder');
        }
    },

    /*
     *
     * CHARTS
     *
     *
     */
    setChartData: function (title, idx) {
        var self = this;
        //run query without pagination limit
        self._runQuery('chart').then(
            function (result) {
                self.$scope.chartresult = self._commonHelper.removeHostkeyFromResult(result.data);
                self.$scope.modalWindow.open('showChartPopup', self.$scope);

                if (!title && !idx && self.$scope.currentChart) {
                    title = self.$scope.currentChart.title;
                    idx = self.$scope.currentChart.index;
                } else {
                    // save current chart details for updating on filter change
                    self.$scope.currentChart = {title: title, index: idx};
                }

                if (title && idx !== '0') {
                    self.$scope.showChart = true;
                    var array = [];

                    angular.forEach(self.$scope.chartresult.rows, function (res) {
                        array.push(res[idx]);
                    });

                    self.$scope.chartConfig.title.text = title;
                    self.$scope.chartConfig.xAxis.title.text = title;
                    self.$scope.chartConfig.series[0] = {
                        color: widgetColors.mainColor(),
                        name: title,
                        data: self._convertArray(array)
                    };

                } else {
                    self.$scope.showChart = false;
                }
            },
            function (error) {
                // todo error handle for no data
            });
    },

    _convertArray: function (arr) {
        var self = this;
        var obj = {};
        for (var i = 0, j = arr.length; i < j; i++) {
            if (obj[arr[i]]) {
                obj[arr[i]]++;
            }
            else {
                obj[arr[i]] = 1;
            }
        }
        var array = [];
        var axis = [];
        angular.forEach(obj, function (key, value) {
            array.push([value, key]);
            axis.push(value);
        });

        self.$scope.chartConfig.xAxis.categories = axis;
        return array;
    },

    copyReport: function (isOverwrite) {
        var self = this;
        var $scope = self.$scope;
        self._commonHelper.copyReport(self.$scope.reportId, self.$scope.savedSearchName.input, $scope, isOverwrite, 'inventory-result');
    },

    /*
     * When user clicks on public report checkbox
     */
    publicReport_disableRoles: function () {
        var self = this;
        var $scope = self.$scope;
        self._commonHelper.publicReport_disableRoles($scope.is_public.input, $scope);
    },
    // when user clicks on roles
    roles_disablePublicReport: function () {
        var self = this;
        var $scope = self.$scope;
        self._commonHelper.roles_disablePublicReport($scope.is_public.input, $scope);
    },

    colSelected: function (col) {
        var self = this;
        return self.$scope.selectedCols.indexOf(col.label) === -1;
    },

    noSort: function (obj) {

        if (!obj) {
            return [];
        }
        return Object.keys(obj);
    },

    runReport: function () {
        this.$scope.$broadcast('environmentFilter_EVENT');
        this._runQuery();
    }

});


inventoryController.$inject = ['$scope',
    '$q',
    '$location',
    '$routeParams',
    '$http',
    'reportService',
    'inventoryService',
    'paginationService',
    'commonHelper',
    'inventoryHelper',
    'notificationService',
    'wizardSharedService',
    'modalWindowService',
    'inventoryDataService',
    'inventoryFilterService',
    '$rootScope',
    '$modal'
];
