angular.module('addConditionDirective', [])
    .directive('addEditCondition', ['$q', 'rulesService', 'autocompleteService', '$timeout', '$modal', 'inventoryFilterService', 'inventoryDataService', function ($q, rulesService, autocompleteService, $timeout, $modal, inventoryFilterService, inventoryDataService) {
        return {
            restrict: 'A',
            scope: {
                source: '=',
                dca: '=',
                ruleData: '=',
                showAddButton: '=',
                ruleId: '=',
                rulesList: '='
            },
            templateUrl: MP_SITE_URL + '/directives/partials/add_edit_condition.php',
            link: function (scope) {
                this.$modal = $modal;
                this.scope = scope;
                this.ruleId = scope.ruleId;
                this.rulesList = scope.rulesList;
                this.DCA = scope.dca;
                this.rulesService = rulesService;
                this.autocompleteService = autocompleteService;
                this._inventoryFilterService = inventoryFilterService;
                this._inventoryDataService = inventoryDataService;

                scope.openAddCheckModal = this.openAddCheckModal.bind(this);

            },
            openAddCheckModal: function (id = null) {
                let self = this;
                this.modalInstance = this.$modal.open({
                    templateUrl: 'addCheck.html',
                    backdrop: 'static',
                    keyboard: true,
                    windowClass: 'add-check-modal',
                    controller: function ($scope, $modalInstance, $parent, $rootScope) {
                        $scope.rulesList = $parent.rulesList;
                        $scope.DCA = $parent.DCA;
                        $scope.existingRuleData = false;
                        $scope.modalData = {};
                        $scope.ruleData = {conditionMustBeMet: 'true'};
                        $scope.conditionFor = [
                            {"value": "true",   "label": "passing"},
                            {"value": "false", "label": "failing"}
                        ];
                        $scope.form = {};
                        $scope.ruleId = id;

                        $scope.filterData = {filters: [], entriesFilter: {includes: {}, excludes: {}}, group: null};

                        $scope.InventorySQL = {};
                        $scope.InventoryUI = {};
                        $scope.applicationName = 'inventory_rule';

                        // see inventory_data_addons
                        $scope.CFE_Mapping_addFields = CFE_Mapping_addFields;
                        $scope.CFE_Mapping_removeFields = CFE_Mapping_removeFields;
                        $scope.CFE_Mapping_addToFilters = CFE_Mapping_addToFilters;

                        if (id !== null) {
                            $parent.rulesService.getrules([id]).then(
                                result => {
                                    $scope.ruleData = result.data[0];
                                    Object.keys($scope.ruleData).map(function(key) {
                                        // if property contains condition (customConditions,policyConditions,etc)
                                        // and contains an array then set to object, otherwise UI will not be bonded with model
                                        if (key.includes('Conditions') && Array.isArray($scope.ruleData[key])) {
                                            $scope.ruleData[key] = {};
                                        }
                                    });
                                    $scope.ruleData.conditionMustBeMet = $scope.ruleData.conditionMustBeMet.toString();
                                    $scope.hostContextState = {hostContexts: $scope.ruleData.hostcontexts};

                                    if ($scope.ruleData.filterdata === null && $scope.ruleData?.hostcontexts?.includes) {
                                        $scope.filterData.filters = [
                                            ...$scope.ruleData.hostcontexts.includes.map(classItem => ({"type":"class","value":classItem,"condition":"matches"}))
                                        ]
                                    }

                                    if ($scope.ruleData.filterdata?.filters) {
                                        $scope.$on('inventoryDirectiveReady_EVENT', function () {
                                            self._inventoryFilterService.convertFilterObjectToFilters(
                                                $scope.ruleData.filterdata.filters,
                                                $scope.InventoryUI.CFE_mapping
                                            ).then(parsedFilters => {
                                                $scope.filterData.filters = parsedFilters;
                                            });
                                        });
                                    }
                                    $scope.filterData.group = $scope.ruleData.filterdata?.group || null;
                                    if ($scope.ruleData.filterdata?.filters?.hostFilter) {
                                        $scope.filterData.entriesFilter =
                                        {
                                            includes: ($scope.ruleData.filterdata?.filters?.hostFilter?.includes?.entries || {}),
                                            excludes: ($scope.ruleData.filterdata?.filters?.hostFilter?.excludes?.entries || {})
                                        }
                                    }

                                    $scope.InventorySQL = $scope.ruleData.inventoryConditions;
                                    // wait 1 sec until DOM update
                                    setTimeout(processPageBeforeLeave, 1000);
                                },
                                error => notify.error(error.data)
                            );
                        }

                        $scope.$on("hostContextApply_Event", function (event, hostcontexts) {
                            $scope.ruleData.hostcontexts = hostcontexts.hostcontexts;
                        });

                        $scope.$on("INV_FILTER_CHANGED", function () {
                            $scope.refreshInventoryRuleData();
                        });

                        $scope.$watch('filterData', function(filterdata) {
                            if (!filterdata) return;

                            if (Array.isArray(filterdata.entriesFilter.includes)) {
                                $scope.filterData.entriesFilter.includes = {};
                            }
                            if (Array.isArray(filterdata.entriesFilter.excludes)) {
                                $scope.filterData.entriesFilter.excludes = {};
                            }
                        })
                        $scope.$watch('ruleData.type', function (value) {
                            switch (value) {
                                case 'fileChanged':
                                    if ($scope.ruleData.fileChangedConditions == undefined) {
                                        $scope.ruleData.fileChangedConditions = {
                                            'condition': 'matches',
                                            'timePeriod': 24
                                        };
                                    }
                                    break;
                                case 'softwareupdate':
                                    if ($scope.ruleData.softwareUpdateConditions == undefined) {
                                        // set default software update condition
                                        $scope.ruleData.softwareUpdateConditions = {'condition': 'is'};
                                    } else if ($scope.ruleData.softwareUpdateConditions.condition == undefined) {
                                        // set default software update condition in case of missing value in the database
                                        $scope.ruleData.softwareUpdateConditions.condition = 'matches';
                                    }
                                    break;
                            }
                        });
                        let validateTimeout;
                        $scope.$watch('ruleData.customConditions.sql', function () {
                            $scope.form.ruleForm.$valid = false;
                            if (validateTimeout) $timeout.cancel(validateTimeout);
                            validateTimeout = $timeout(function () {
                                $scope.validateCustomQuery()
                            }.bind(this), 2000);
                        }.bind(this))

                        $scope.close = function () {
                            $modalInstance.close('cancel');
                            $parent.scope.ruleData = {conditionMustBeMet: 'true'};
                            $rootScope.$broadcast('cancel_Rule_Event');
                            // reset onbeforeunload when modal is closed
                            unbindBeforeUnload();
                        };

                        $scope.selectExistingCheck = function (check) {
                            const noneOptionIndex = this.rulesList.findIndex(el => el.id === -1);
                            if (check.type === 'cancel') {
                                if (noneOptionIndex !== -1) {
                                    this.rulesList[noneOptionIndex].name = '';
                                }
                                $scope.existingRuleData = false;
                            } else {
                                if (noneOptionIndex !== -1) {
                                    this.rulesList[noneOptionIndex].name = 'None';
                                }
                                $scope.existingRuleData = check;
                            }
                        }

                        $scope.addExistingCheck = function () {
                            $rootScope.$broadcast('select_check_event', $scope.existingRuleData.id);
                            $scope.close();
                        }

                        $scope.saveRule = function () {

                            if ($scope.ruleData['type'] === 'inventory') {
                                this.refreshInventoryRuleData();
                            }

                            $scope.ruleData.filterdata = {
                                group: $scope.filterData?.group && $scope.filterData?.group?.type === 'shared' ? $scope.filterData.group : null,
                                filters: {
                                    filter: self._inventoryFilterService.processFilters($scope.filterData.filters),
                                    hostFilter: self._inventoryFilterService.processEntriesFilters($scope.filterData),
                                    hostContextInclude: self._inventoryFilterService.processClassFilters($scope.filterData.filters),
                                }
                            }                   

                            // create rule
                            $parent.rulesService.saverule($scope.ruleData).then(
                                function (result) {
                                    $rootScope.$broadcast('saveRule_Success_Event', result.data);
                                    $scope.close();
                                },
                                function (error) {
                                    $rootScope.$broadcast('saveRule_Fail_Event', error.data);
                                    if (error.data.length > 0 && error.data[0].text != undefined) {
                                        notify.error(error.data[0].text);
                                    }
                                });

                        };


                        $scope.setPolicyConditionType = function (value) {
                            $scope.ruleData.policyConditions = $scope.ruleData.policyConditions || {};
                            $scope.ruleData.policyConditions.filterBy = value;
                        };

                        $scope.autocompleteList = function (listType, inputValue, inputParentType, inputParentValue) {
                            if (listType !== '') {
                                return $parent.autocompleteService.load(listType.toLowerCase(), inputValue, inputParentType, inputParentValue);
                            }
                        };

                        $scope.autocompleteValidateValue = function ($item, stringModelName) {
                            let arrayModelName = stringModelName.split('.');

                            if (arrayModelName.length > 0) {
                                let obj = $scope;
                                stringModelName.split('.').forEach(function (propery) {
                                    obj = (obj[propery] != undefined) ? obj[propery] : null;
                                });

                                if (obj !== null) {
                                    obj = '';
                                }
                            }

                        };

                        $scope.refreshInventoryRuleData = function () {
                            // note $scope.InventorySQL object is "connected" to inventory directive
                            $scope.ruleData['inventoryConditions'] = $scope.InventorySQL;
                            $scope.$broadcast('updateVariablesDictionary_EVENT');
                        };

                        $scope.validateCustomQuery = function () {
                            if ($scope.ruleData.customConditions == undefined || $scope.ruleData.customConditions.sql == undefined) {
                                return;
                            }
                            let sql = $scope.ruleData.customConditions.sql;
                            $parent.rulesService.validateCustomSql(sql).then(
                                function (result) {
                                    $scope.ruleData.customConditions.errors = [];
                                    $scope.form.ruleForm.$valid = true;
                                    result.data.forEach(function (value) {
                                        $scope.ruleData.customConditions.errors.push(value);
                                        $scope.form.ruleForm.$valid = false;
                                    });
                                },
                                function (error) {
                                    $parent.scope.$emit('deleteRule_Fail_Event', error.data);
                                });
                        };
                    },
                    resolve: {
                        $parent: function () {
                            return self;
                        }
                    }
                });
            },
        };
    }]);