/*-
 * ~~~~~~licensing~~~~~~
 * entaxy-management-plugin
 * ==========
 * Copyright (C) 2020 - 2025 EmDev LLC
 * ==========
 * You may not use this file except in accordance with the License Terms of the Copyright
 * Holder located at: https://entaxy.ru/eula . All copyrights, all intellectual property
 * rights to the Software and any copies are the property of the Copyright Holder. Unless
 * it is explicitly allowed the Copyright Holder, the User is prohibited from using the
 * Software for commercial purposes to provide services to third parties.
 * 
 * The Copyright Holder hereby declares that the Software is provided on an "AS IS".
 * Under no circumstances does the Copyright Holder guarantee or promise that the
 * Software provided by him will be suitable or not suitable for the specific purposes
 * of the User, that the Software will meet all commercial and personal subjective
 * expectations of the User, that the Software will work properly, without technical
 * errors, quickly and uninterruptedly.
 * 
 * Under no circumstances shall the Copyright Holder or its Affiliates is not liable
 * to the User for any direct or indirect losses of the User, his expenses or actual
 * damage, including, downtime; loss of bussines; lost profit; lost earnings; loss
 * or damage to data, property, etc.
 * ~~~~~~/licensing~~~~~~
 */
var Entaxy;
(function (Entaxy) {
    Entaxy._module
    .component('entaxyModalGroupFields', {
        bindings: {
            groups: '<',
            fields: '<',
            errors: '<',
            mode: '<',
            useFormDirty: '<',
            isFormDirty: '='
        },
        template:
        `
          <div class="modal-group-fields-container">
            <div class="modal-groups-list-container">
              <entaxy-modal-list class="group-list" items="$ctrl.groups" items-label="Group" items-label-plural="Groups"
                selected="$ctrl.selectedGroup" change-selection="$ctrl.change" filter="$ctrl.matchesFilter">
              </entaxy-modal-list>
            </div>
            <div class="modal-group-fields-form-container">
              <form name="entaxyObjectForm" class="form-horizontal">
                <entaxy-form-fields items="$ctrl.viewedFormFields" errors="$ctrl.errors" mode="$ctrl.mode"                      
                      update-fields-after-selection-change-fn="$ctrl.updateFieldsAfterSelectionChange"
                      form-controller="entaxyObjectForm" set-focus-on="$ctrl.setFocusOn"></entaxy-form-fields>
              </form>
            </div>
          </div>
        `,
        controller: entaxyModalGroupFieldsController
    })
    .name;

    function entaxyModalGroupFieldsController(entaxyService, $scope, $cookies) {
        'ngInject';

        let ctrl = this;

        ctrl.$onInit = function() {

            let selectedGroupName = $cookies.getObject('profile-properties-group');
            if (selectedGroupName) {
                let selectedGroup = ctrl.groups.find(group => group.name === selectedGroupName);
                ctrl.selectedGroup = selectedGroup ? selectedGroup : ctrl.groups[0];
                $cookies.remove('profile-properties-group');
            } else {
                ctrl.selectedGroup = ctrl.groups[0];
            }

            if (ctrl.useFormDirty) {
                $scope.$watch('entaxyObjectForm.$dirty', function (newValue) {
                    ctrl.isFormDirty = newValue;
                });

                $scope.$watch('$ctrl.isFormDirty', function (newValue) {
                    if ($scope.entaxyObjectForm.$dirty != newValue) {
                        if (newValue) {
                            $scope.entaxyObjectForm.$setDirty();
                        } else {
                            $scope.entaxyObjectForm.$setPristine();
                        }
                    }
                });
            }

            populateDisplayBlocks();
            manageDisplayBlocks();
        }

        ctrl.$onChanges = function(changes) {
            if (changes.errors && changes.errors.currentValue) {
                let errorKeys = Object.keys(changes.errors.currentValue);
                if (errorKeys.length > 0) {
                    let errorField = ctrl.fields.find(field => field.name === errorKeys[0]);
                    ctrl.selectedGroup = ctrl.groups.find(group => group.name === errorField.group);
                }
            }
        }

        ctrl.change = function(group) {
            ctrl.viewedFormFields = ctrl.fields.filter((formField) => formField.group === group.name);
            ctrl.selectedGroup = group;
            let setFocusOn = ctrl.viewedFormFields
                .find(formField => !formField.isBackRef && !formField.isHidden && !formField.readOnly);
            if (setFocusOn) {
                ctrl.setFocusOn = setFocusOn.name;
            }
        }

        ctrl.matchesFilter = function(group, filter) {
            let match;

            let groupFields = ctrl.fields.filter((formField) => formField.group === group.name);

            for (let i = 0; i < groupFields.length; i++) {
                let field = groupFields[i];
                if (!field.isHidden && !field.isBackRef) {
                    if ((field.tag && field.tag.toLowerCase().match(filter.value.toLowerCase()) !== null) ||
                        (field.displayName &&
                            field.displayName.toLowerCase().match(filter.value.toLowerCase()) !== null) ||
                            field.name.toLowerCase().match(filter.value.toLowerCase()) !== null) {
                        match = true;
                        return match;
                    }
                }
            }
            match = group.displayName.toLowerCase().match(filter.value.toLowerCase()) !== null;

            return match;
        };

        let displayBlocks = {};
        function populateDisplayBlocks() {
            if (ctrl.fields && ctrl.fields.length > 1) {
                ctrl.fields.forEach(formField => {
                    if (formField.ui && formField.ui.displayBlocks) {
                        let managedBy = formField.ui.displayBlocksManagedBy;
                        if (!displayBlocks[managedBy]) {
                            displayBlocks[managedBy] = {};
                        }
                        formField.ui.displayBlocks.forEach(displayBlock => {
                            if (!displayBlocks[managedBy][displayBlock]) {
                                displayBlocks[managedBy][displayBlock] = [formField];
                            } else {
                                displayBlocks[managedBy][displayBlock].push(formField);
                            }
                        });
                        if (!formField.ui.originProperties) {
                            formField.ui.originProperties = {
                                required: formField.required,
                                isHidden: formField.isHidden
                            }
                        }
                    }
                });
            }
        }

        function manageDisplayBlocks() {
            if (Object.keys(displayBlocks).length > 0) {
                ctrl.managingFields = getSortedManagingFields();
                for (let i = 0; i < ctrl.managingFields.length; i++) {
                    $scope.$watch('$ctrl.managingFields[' + i + '].value', function (newValue) {
                        Object.keys(displayBlocks[ctrl.managingFields[i].name])
                            .filter(displayBlock => displayBlock !== newValue)
                            .forEach(displayBlock => {
                                let fieldsToHide = displayBlocks[ctrl.managingFields[i].name][displayBlock]
                                    .filter(fieldToHide => fieldToHide.group === ctrl.managingFields[i].group);
                                hideFields(fieldsToHide);
                            });
                        if (displayBlocks[ctrl.managingFields[i].name][newValue]) {
                            let fieldsToDisplay = displayBlocks[ctrl.managingFields[i].name][newValue]
                                .filter(fieldToDisplay => fieldToDisplay.group === ctrl.managingFields[i].group);
                            displayFields(fieldsToDisplay);
                        }
                    });
                }
            }
        }

        function getSortedManagingFields () {
            let managingFields = ctrl.fields.filter(formField =>
                formField.ui && formField.ui.manageDisplayBlocksByValue);
            let managingTrees = {};
            let topManagingFields = managingFields.filter(formField => !formField.ui.displayBlocksManagedBy);
            topManagingFields.forEach(topManagingField => {
                managingTrees[topManagingField.name] = getManagingTree(topManagingField.name, managingFields);
            });
            let sorted = [];
            sortManagingFields(managingTrees, managingFields, sorted);
            return sorted;
        }

        function getManagingTree(topManagingFieldName, managingFields) {
            let tree = {};
            managingFields
                .filter(formField => formField.ui && formField.ui.displayBlocksManagedBy === topManagingFieldName)
                .forEach(formField => {
                    tree[formField.name] = getManagingTree(formField.name, managingFields);
                });
            return tree;
        }

        function sortManagingFields(managingTrees, managingFields, sorted) {
            Object.keys(managingTrees)
                .forEach(managingFieldName => {
                    sorted.unshift(managingFields.find(formField => formField.name === managingFieldName));
                    sortManagingFields(managingTrees[managingFieldName], managingFields, sorted);
                });
        }

        function hideFields(fieldsToHide) {
            fieldsToHide.forEach(formField => {
                formField.required = false;
                formField.isHidden = true;
                if (!formField.ui.transmitAlways) {
                    formField.ignored = true;
                }
                if (formField.ui.manageDisplayBlocksByValue) {
                    let extraFieldsToHide = displayBlocks[formField.name][formField.value];
                    if (extraFieldsToHide && extraFieldsToHide.length > 0) {
                        hideFields(extraFieldsToHide);
                    }
                }
            });
        }

        function displayFields(fieldsToDisplay) {
            fieldsToDisplay.forEach(formField => {
                formField.required = formField.ui.originProperties.required;
                formField.isHidden = formField.ui.originProperties.isHidden;
                delete formField.ignored;
                if (formField.ui.manageDisplayBlocksByValue) {
                    let extraFieldsToDisplay = displayBlocks[formField.name][formField.value];
                    if (extraFieldsToDisplay && extraFieldsToDisplay.length > 0) {
                        displayFields(extraFieldsToDisplay);
                    }
                }
            });
        }

        ctrl.updateFieldsAfterSelectionChange = function (oldItem, newItem) {

            if (oldItem) {
                changeFieldsFromSelected(oldItem, true);
            }

            changeFieldsFromSelected(newItem, false);
        }

        function changeFieldsFromSelected(item, toDefaults) {
            if (item.mbeanName) {
                entaxyService.readConfiguration(item.mbeanName)
                .then(itemInfo => {
                    let properties = itemInfo.properties;

                    changeFieldsValuesFromProperties(properties, toDefaults);

                }).catch(error => {
                    Entaxy.notificationError(error);
                    Entaxy.log.error(error);
                });
            } else if (item.value) {
                let properties = item.value.properties;

                changeFieldsValuesFromProperties(properties, toDefaults);
            }
        }

        function changeFieldsValuesFromProperties(properties, toDefaults) {
            if (properties && Object.keys(properties).length > 0) {
                let keys = Object.keys(properties);

                keys.forEach(key => {
                    let field = ctrl.fields.find(field => field.name === key);
                    if (field && !field.ignoreChildChanges && !field.isHidden) {
                        field.value = toDefaults ? field.defaultValue : properties[key];
                    }
                });
            }
        }
    }
    entaxyModalGroupFieldsController.$inject = ['entaxyService', '$scope', '$cookies'];

})(Entaxy || (Entaxy = {}));
