/*jslint node: true */
/*jslint browser: true*/
/*jslint nomen: true*/
/*global BaseController, angular, $*/

'use strict';

var analyzerController = BaseController.extend({
    /**
     * Initialize  Controller
     * @param $scope, current controller scope
     */
    init: function (
        $scope,
        $rootScope,
        $timeout,
        $modal,
        policyService,
        paginationService,
        reportService,
        policySummaryService,
        inventoryFilterService,
        actionHelper
    ) {
        this._super($scope);
        this.$modal = $modal;
        this.$timeout = $timeout;
        this.policyService = policyService;
        this.inventoryFilterService = inventoryFilterService;
        this.policySummaryService = policySummaryService;
        this.$scope.selectedFile = {};
        this.$scope.selectedDir = {};
        this.$scope.policiesInfo = {};
        this.$scope.paginator = paginationService;
        this.$scope.reportService = reportService;
        this.actionHelper = actionHelper;
        this.rootScope = $rootScope;
        this.$scope.policyPath = '/var/cfengine/inputs';
        this.$scope.copyingEnabled = true;
        this.$scope.showAllowCopyingMessage = false;
        this.errorMessage = 'Error encountered. Please view the logs for more detailed information.';

        let self = this;

        self.$scope.UI = {}
        self.$scope.showEnvironmentFilterButtons = true;
        this.$scope.promiseOutcomes = [
            {id: 'KEPT', name: 'Kept', selected: false, class: 'green icon-ok-sign'},
            {id: 'NOTKEPT', name: 'Not Kept', selected: true, class: 'red icon-warning-sign'},
            {id: 'REPAIRED', name: 'Repaired', selected: false, class: 'orange icon-wrench'},
        ];

        this.$scope.fileContents = '';

        this.policyService.enablingStatus().then(function (result) {
            self.$scope.copyingEnabled = result.data.copying_request_sent;
            self.$scope.showAllowCopyingMessage = !result.data.policy_directory_exits;

            if (result.data.policy_directory_exits === true) {
                self.policyService.getPolicyFiles().then(function (data) {
                    $scope.files = data.data;
                })
            }
        });

        this._initVIEWParams();
        this.$scope.SQL = {};
        this.$scope.SQL.filters = [];
        this.$scope.filterData = {relativeFilePath: "", promiseOutcome: ['NOTKEPT'], inventory: []};
        this.$scope.SQL.SQLString = this.policySummaryService.getSql(this.$scope.filterData);

        self.$scope.alertData = {};
        self.$scope.hostcontexts = {};
        self.$scope.excludedHosts = '';
    },

    defineScope: function () {
        this.$scope.instance = "indexController";
        this.$scope.onFileSelected = this.onFileSelected.bind(this);
        this.$scope.onSummaryFileSelected = this.onSummaryFileSelected.bind(this);
        this.$scope.onDirectorySelected = this.onDirectorySelected.bind(this);
        this.$scope.onLineSelected = this.onLineSelected.bind(this);
        this.$scope.onOutcomeSelected = this.onOutcomeSelected.bind(this);
        this.$scope.removeFilter = this.removeFilter.bind(this);
        this.$scope.allowCopying = this.allowCopying.bind(this);


        this.$scope.sortReorder = this.sortReorder.bind(this);
        this.$scope.runQuery = this.runQuery.bind(this);
    },

    defineListeners: function () {
        var self = this;

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

        self.$scope.$watchCollection('[files, hostcontexts]',  function () {
            self.policyService.getPolicyStatistic(self.$scope.filterData).then(function (data) {
                self.$scope.statistics = data.data;
            }).catch(function (error) {
                self.$scope.VIEW.errorMessage = error.data[0].text || self.errorMessage;
            });
        })

        self.$scope.$watch('selectedFile', function (value, oldValue) {
            if (oldValue != value && value.hasOwnProperty('path')) {
                self.policyService.getPolicyFile(value.path.relative).then(function (data) {
                    self.$scope.fileContents = data.data;
                }).catch(function (data) {
                    self.$scope.fileContents = 'File not found';
                });
                ;
            }
        })

        self.$scope.$watch('selectedDir', function (dir) {
            if (dir != undefined && dir.hasOwnProperty('path')) {
                let data = Object.assign(self.$scope.filterData, {dir: dir.path.relative})
                self.$scope.SQL.SQLString = self.policySummaryService.getSql(data);
            } else {
                delete self.$scope.filterData.dir;
                self.$scope.SQL.SQLString = self.policySummaryService.getSql(self.$scope.filterData);
            }
        })

        let oldCollection = [];
        self.$scope.$watchCollection('[filterData.promiseOutcome.length, filterData.relativeFilePath]', function (collection) {

            let extendedFilter = Object.assign(self.$scope.filterData, {hash: self.$scope.selectedFile.hasOwnProperty('hash') ? self.$scope.selectedFile.hash : false})
            self.$scope.SQL.SQLString = self.policySummaryService.getSql(extendedFilter);

            // Update policy info for editor to highlight lines just in case when file is selected
            if (collection[2] != '') {
                self.policyService.getPolicyInfoByFilePath(self.$scope.filterData).then(function (data) {
                    self.$scope.policiesInfo = data.data;
                }).catch(function (error) {
                    self.$scope.VIEW.errorMessage = error.data[0].text || self.errorMessage;
                });
            }

            // Update statistics for file tree just in case when outcomes were changed
            if ((collection[0] != oldCollection[0] || collection[1] != oldCollection[1]) && oldCollection.length > 0) {
                self.policyService.getPolicyStatistic(self.$scope.filterData).then(function (data) {
                    self.$scope.statistics = data.data;
                }).catch(function (error) {
                    self.$scope.VIEW.errorMessage = error.data[0].text || self.errorMessage;
                });
            }

            oldCollection = collection;
        });

        self.$scope.$watch('SQL.SQLString', function (sql) {
            if (sql !== undefined && sql.length > 0) {
                self._runQuery();
            }
        });

        self.$scope.$on("hostContextApply_Event", function (event, hostContextObj) {
            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.$scope.filterData.includes = ((self.$scope.SQL.hostcontexts !== undefined && self.$scope.SQL.hostcontexts.includes !== undefined) ? self.$scope.SQL.hostcontexts.includes : []);
            self.$scope.$broadcast('environmentFilter_EVENT');
            self.$scope.$broadcast('applyInvFilters_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)};
                self.$scope.filterData.excludes = ((self.$scope.SQL.excludedHosts !== undefined && self.$scope.SQL.excludedHosts.excludes !== undefined) ? self.$scope.SQL.excludedHosts.excludes : []);
            } else {
                self.$scope.alertData.excludedHosts = '';
                self.$scope.excludedHosts = '';
                self.$scope.SQL.excludedHosts = '';
            }
        });

        self.$scope.$on('runQuery_EVENT', function () {
            self.$scope.filterData.inventory = self.inventoryFilterService.processFilters(self.$scope.SQL.filters);
            self.$scope.SQL.SQLString = self.policySummaryService.getSql(self.$scope.filterData);
            self._runQuery();
        })
    },

    onFileSelected: function (selectedFile) {
        this.$scope.VIEW.sortColumn = '';
        this.$scope.selectedFile = selectedFile;
        this.$scope.filterData.relativeFilePath = selectedFile.path.relative;
        this.$scope.selectedDir = {};
    },
    onSummaryFileSelected: function (selectedFile) {
        let self = this;
        this.$scope.VIEW.sortColumn = '';
        selectedFile.path.relative = selectedFile.path.absolute.substring(this.$scope.policyPath.length);

        self.policyService.getPolicyFiles().then(function (data) {
            self.$scope.files = data.data;
        }).catch(function () {
            self.$scope.fileContents = 'File not found';
        });

        let hash = $('.file[relative-path="' + selectedFile.path.relative + '"]').attr('hash')
        selectedFile.hash = hash;
        self.$scope.selectedFile = selectedFile;
        self.$scope.filterData.relativeFilePath = selectedFile.path.relative;
    },
    onDirectorySelected: function (selectedDir) {
        if(!this.$scope.selectedFile.hasOwnProperty('path')) {
            this.$scope.selectedDir = selectedDir;
        }
    },
    onLineSelected: function (selectedLine) {
        this.$scope.selectedLine = selectedLine;
        $([document.documentElement, document.body]).animate({
            scrollTop: $("#editor").offset().top - 50
        }, 800);
    },
    onOutcomeSelected: function (outcomes) {
        this.$scope.promiseOutcomes = outcomes;
        let result = [];
        outcomes.forEach(function (value) {
            if (value.selected == true) {
                result.push(value.id);
            }
        })

        this.$scope.filterData.promiseOutcome = result;
    },
    removeFilter: function (data) {
        let self = this;

        switch (data.type) {
            case 'dir':
                self.$scope.selectedDir = {};
                break;
            case 'file':
                self.$scope.selectedFile = {};
                self.$scope.fileContents = '';
                self.$scope.filterData.relativeFilePath = '';
                self.$scope.selectedLine = 0;
                break;
            case 'outcome':
                self.$scope.promiseOutcomes.forEach(function (outcome, key) {
                    if (outcome.id == data.value) {
                        self.$scope.promiseOutcomes[key].selected = !self.$scope.promiseOutcomes[key].selected;
                    }
                })
                //remove from filterData.promiseOutcome unselected filter
                self.$scope.filterData.promiseOutcome.splice(self.$scope.filterData.promiseOutcome.indexOf(data.value), 1);
                break;
        }
    },

    allowCopying: function () {
        let self = this;
        this.policyService.enableCopying().then(async function () {
            self.$scope.copyingEnabled = true;
            common.globalSpinner.show();
            try {
                await self.actionHelper.triggerHubsAgentRun();
            } catch(e) {}
            common.globalSpinner.hide();
            document.location.reload();
        }).catch(function (error) {
            self.$scope.VIEW.errorMessage = error?.data?.[0]?.text || self.errorMessage;
        });
    },
    sortReorder: function (col) {
        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._runQuery('reorder');
        }
    },

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

        self.$scope.VIEW.sortColumn = '';
        self.$scope.VIEW.sortDescending = 0;

        self.$scope.VIEW.tablehead = [];
    },

    _runQuery: function (action) {
        let self = this;

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


        var data = $.param({
            SQLString: self.$scope.SQL.SQLString.length > 0 ? encodeURIComponent(self.$scope.SQL.SQLString) : false,
            sortColumn: self.$scope.VIEW.sortColumn,
            sortDescending: self.$scope.VIEW.sortDescending,

            skip: self.$scope.paginator.skip,
            limit: self.$scope.paginator.rowsPerPage,

            includes: ((self.$scope.SQL.hostcontexts !== undefined && self.$scope.SQL.hostcontexts.includes !== undefined) ? self.$scope.SQL.hostcontexts.includes : []),
            excludes: ((self.$scope.SQL.excludedHosts !== undefined && self.$scope.SQL.excludedHosts.excludes !== undefined) ? self.$scope.SQL.excludedHosts.excludes : []),
            inventoryFilter:  self.inventoryFilterService.processFilters(self.$scope.SQL.filters)
        });

        common.globalSpinner.show();
        self.$scope.reportService.runQuery(data).then(
            function (result) {
                self.$scope.result = 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 = 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);

                common.globalSpinner.hide();
            },
            function (error) {
                self.$scope.VIEW.errorMessage = error.data[0].text || self.errorMessage;
                common.globalSpinner.hide();
            });
    },
});


analyzerController.$inject = [
    '$scope',
    '$rootScope',
    '$timeout',
    '$modal',
    'policyService',
    'IEPaginationService',
    'reportService',
    'policySummaryService',
    'inventoryFilterService',
    'actionHelper'
];

policyAnalyzerApp.controller('analyzerController', analyzerController);
