/*-
 * ~~~~~~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('entaxyModal', {
        bindings: {
            modalInstance: '<',
            resolve: '<'
        },
        template:
        `
          <div class="entaxy-modal-container">
            <div class="modal-header">
              <button type="button" class="close" aria-label="Close" ng-click="$ctrl.cancel()">
                <span class="pficon pficon-close" aria-hidden="true"></span>
              </button>
              <h4 class="modal-title">{{$ctrl.modalTitle}}</h4>
            </div>

            <div ng-if="$ctrl.step1">
              <div class="modal-body-header">
                <h2>{{$ctrl.firstStepTitle}}</h2>
              </div>
              <div class="modal-body">
                <entaxy-modal-list items="$ctrl.containers" selected="$ctrl.selectedContainer"
                      change-selection="$ctrl.changeContainerSelection" enable-dbl-click="true"></entaxy-modal-list>
              </div>
              <div class="modal-footer">
                <button type="button" class="btn btn-default" ng-click="$ctrl.next()"
                      ng-disabled="!$ctrl.selectedContainer">Next</button>
              </div>
            </div>

            <div ng-if="$ctrl.step2">
              <div class="modal-body-header">
                <h2>{{$ctrl.secondStepTitle}}</h2>
              </div>
              <div class="modal-body">
                <entaxy-modal-list-with-description items="$ctrl.factories" selected-item="$ctrl.selectedFactory"
                    change-selection="$ctrl.changeFactorySelection" show-deprecated="$ctrl.showDeprecated">
                </entaxy-modal-list-with-description>
              </div>
              <div class="modal-footer">
                <button type="button" class="btn btn-default" ng-if="$ctrl.containers"
                      ng-click="$ctrl.back()">Back</button>
                <button type="button" class="btn btn-default" ng-click="$ctrl.next()"
                      ng-disabled="!$ctrl.selectedFactory">Next</button>
              </div>
            </div>

            <div ng-if="$ctrl.step3">
              <div class="modal-body-header form-header">
                <h2>{{$ctrl.thirdStepTitle}}</h2>
                <span ng-if="$ctrl.shouldShowChangesNote()">
                  There are unsaved changes
                </span>
              </div>
              <div class="modal-body">
                <entaxy-modal-group-fields groups="$ctrl.groups" fields="$ctrl.formFields"
                      use-form-dirty="true" is-form-dirty="$ctrl.isFormDirty"
                      errors="$ctrl.errors" mode="$ctrl.mode"></entaxy-modal-group-fields>
              </div>
              <div class="modal-footer">
                <button type="button" class="btn btn-default" ng-if="$ctrl.factories.length > 1 || $ctrl.containers"
                      ng-click="$ctrl.back()">Back</button>
                <button type="submit" class="btn btn-primary" ng-click="$ctrl.save()">{{$ctrl.submitBtnTitle}}</button>
              </div>
            <div>
          </div>
        `,
        controller: entaxyModalController
    })
    .name;

    function entaxyModalController($scope, entaxyService, entaxyHotkeysService,
                                   entaxyPrivateObjectsCacheService, entaxyProfileDiagramService) {
        'ngInject';

        var ctrl = this;

        ctrl.$onInit = function() {

            ctrl.mode = ctrl.resolve.mode;

            if (!ctrl.mode) {
                ctrl.cancel('Mode is not defined');
            }

            entaxyHotkeysService.setHotkeys($scope, getHotkeysConfigs());

            ctrl.hasChangedPrivateObjects = ctrl.mode !== Entaxy.MODAL_MODES.ADD ?
                entaxyPrivateObjectsCacheService.isChanged(ctrl.resolve.itemMbeanName) : false;

            ctrl.hasChangesFromDiagram = ctrl.mode === Entaxy.MODAL_MODES.EDIT ?
                entaxyProfileDiagramService.hasChanges(ctrl.resolve.itemMbeanName) : false;

            ctrl.itemType = ctrl.resolve.itemType ? ctrl.resolve.itemType : 'Item';

            let extraToTitle = ctrl.resolve.parentName ? (' to ' + ctrl.resolve.parentName) : '';

            ctrl.modalTitle = ctrl.mode + ' ' + ctrl.itemType + extraToTitle;

            ctrl.submitBtnTitle = Entaxy.getButtonTitleByMode(ctrl.mode);

            let containerType = ctrl.resolve.containerType ? ctrl.resolve.containerType : 'Container';

            ctrl.firstStepTitle = ctrl.resolve.firstStepTitle ?
                ctrl.resolve.firstStepTitle :
                'Choose ' + containerType.toLowerCase() + ' to attach ' + ctrl.itemType.toLowerCase() + ' to';

            ctrl.secondStepTitle = ctrl.resolve.secondStepTitle ? ctrl.resolve.secondStepTitle : 'Choose factory';

            ctrl.thirdStepTitle = ctrl.resolve.itemName ? ctrl.mode + ' properties for ' + ctrl.resolve.itemName
                : ctrl.resolve.thirdStepTitle ? ctrl.resolve.thirdStepTitle : 'Fill in fields';

            if (ctrl.mode !== Entaxy.MODAL_MODES.ADD || ctrl.resolve.useTemplate) {
                ctrl.properties = ctrl.resolve.info.properties;
                ctrl.configurableOnly = !ctrl.resolve.useTemplate ? ctrl.resolve.info.configurableOnly : false;
            }

            ctrl.containers = ctrl.resolve.containers;

            ctrl.factories = ctrl.resolve.factories ? ctrl.resolve.factories : null;

            if (!ctrl.factories || ctrl.factories.length === 0) {
                ctrl.cancel('Factories are not found');
            } else if (ctrl.factories.length === 1) {
                ctrl.selectedFactory = ctrl.factories[0];
            }

            ctrl.factories.sort(Entaxy.compareBy('displayName'));

            if (ctrl.containers) {
                ctrl.step1 = true;
                ctrl.step2 = false;
                ctrl.step3 = false
            } else {
                if (ctrl.factories.length > 1) {
                    ctrl.step1 = false;
                    ctrl.step2 = true;
                    ctrl.step3 = false;
                } else if (ctrl.factories.length === 1) {
                    ctrl.next();
                }
            }
        }

        ctrl.next = function() {

            if (ctrl.step1 === true) {
                if (ctrl.factories.length > 1) {
                    ctrl.step1 = false;
                    ctrl.step2 = true;
                } else if (ctrl.factories.length === 1) {
                    defineFormFields();
                }
            } else {
                defineFormFields();
            }
        }

        function defineFormFields() {
            let container = ctrl.formFields ?
                ctrl.formFields.find(field => field.name === '__entaxyContainerId') : undefined;

            if (!ctrl.formFields || ctrl.selectedFactory.name !== ctrl.formFields[0].value
                                || (ctrl.containers && container.value !== ctrl.selectedContainer.name)) {

                ctrl.formFields = [];

                ctrl.formFields.push({
                    label: 'Factory',
                    name: 'factoryId',
                    type: 'text',
                    description: ctrl.selectedFactory.description,
                    value: ctrl.selectedFactory.displayName,
                    originalValue: ctrl.selectedFactory.name,
                    readOnly: true,
                    required: ctrl.mode === Entaxy.MODAL_MODES.VIEW ? false : true,
                    group: 'general'
                });

                entaxyService.getFields(ctrl.selectedFactory.mbeanName)
                .then((response) => {

                    let groups = new Set();
                    groups.add('general');

                    _.forEach(JSON.parse(response), (field) => {

                        let objectId = undefined;
                        if (ctrl.mode !== Entaxy.MODAL_MODES.ADD) {
                            objectId = ctrl.resolve.info['objectId'];
                        }
                        let profileName = ctrl.selectedContainer ?
                            ctrl.selectedContainer.name : ctrl.resolve.parentName;
                        let formField = entaxyService.makeFormField(field, objectId, ctrl.properties,
                            ctrl.configurableOnly, ctrl.mode, ctrl.resolve.itemMbeanName, profileName);
                        if (formField) {
                            ctrl.formFields.push(formField);
                            if (!formField.isBackRef && !formField.isHidden) {
                                groups.add(formField.group);
                            }
                        }
                    });

                    if (ctrl.mode !== Entaxy.MODAL_MODES.VIEW) {
                        processDependencies();
                    }

                    ctrl.groups = Array.from(groups).map((group) => { return { name: group, displayName: group }; });

                    ctrl.step1 = false;
                    ctrl.step2 = false;
                    ctrl.step3 = true;
                });
            } else {
                ctrl.step1 = false;
                ctrl.step2 = false;
                ctrl.step3 = true;
            }
        }

        let watchers = [];
        function processDependencies() {
            let dependentFormFields = entaxyService.getDependentFormFields(ctrl.formFields, ctrl.configurableOnly);
            ctrl.definingFormFields = entaxyService.getDefiningFormFields(dependentFormFields, ctrl.formFields);

            for (let i = 0; i < ctrl.definingFormFields.length; i++) {
                if (ctrl.definingFormFields[i].value) {
                    let initialRunDependentFormFields = ctrl.mode === Entaxy.MODAL_MODES.ADD ?
                        dependentFormFields :
                        dependentFormFields.filter(field => (field.typeInfo && field.typeInfo.type === 'list'));
                    entaxyService.processDependencies(initialRunDependentFormFields,
                                                      ctrl.definingFormFields,
                                                      ctrl.definingFormFields[i].name,
                                                      ctrl.definingFormFields[i].value,
                                                      undefined);
                }
                watchers.push(
                    $scope.$watch('$ctrl.definingFormFields[' + i + '].value', function(newValue, oldValue) {
                        if (newValue !== oldValue) {
                            Entaxy.changingFieldValueNotification('defining');

                            entaxyService.processDependencies(dependentFormFields,
                                                              ctrl.definingFormFields,
                                                              ctrl.definingFormFields[i].name,
                                                              newValue,
                                                              oldValue);
                        }
                    })
                );
            }
        }

        ctrl.back = function() {
            if (ctrl.step2 === true) {
                ctrl.step1 = true;
                ctrl.step2 = false;
            } else if (ctrl.step3 === true) {
                ctrl.errors = undefined;
                clearWatchers();
                if (ctrl.factories.length > 1) {
                    ctrl.step2 = true;
                } else if (ctrl.factories.length === 1) {
                    ctrl.step1 = true;
                }
                ctrl.step3 = false;
            }
        }

        function clearWatchers() {
            if (watchers && watchers.length > 0) {
                watchers.forEach(watcher => {
                    watcher();
                });
            }
        }

        ctrl.cancel = function(reason) {
            ctrl.modalInstance.dismiss(reason);
        }

        ctrl.changeContainerSelection = function(item, isDblClicked) {
            ctrl.selectedContainer = item;
            if (isDblClicked) {
                ctrl.next();
            }
        }

        ctrl.changeFactorySelection = function(item, isDblClicked) {
            ctrl.selectedFactory = item;
            if (isDblClicked) {
                ctrl.next();
            }
        }

        ctrl.shouldShowChangesNote = function () {
            return ctrl.mode !== Entaxy.MODAL_MODES.ADD &&
                (ctrl.isFormDirty || ctrl.hasChangedPrivateObjects || ctrl.hasChangesFromDiagram);
        }

        ctrl.save = function() {

            if (ctrl.mode === Entaxy.MODAL_MODES.VIEW) {
                ctrl.cancel();
            }

            let isConfirmationNeeded = ctrl.mode === Entaxy.MODAL_MODES.EDIT &&
                !ctrl.isFormDirty && !ctrl.hasChangedPrivateObjects && !ctrl.hasChangesFromDiagram;
            entaxyService.requestConfirmationForSavingIfNeededAndProceed(isConfirmationNeeded, save);
        }

        function save () {
            let profileMBeanName = ctrl.selectedContainer ? ctrl.selectedContainer.mbeanName : undefined;

            entaxyService.validateFields(ctrl.formFields, ctrl.selectedFactory,
                profileMBeanName, ctrl.resolve.checkUniquenessParentFields)
            .then(errors => {
                ctrl.errors = errors;

                if (Object.keys(ctrl.errors).length === 0) {
                    if (ctrl.resolve.returnFormFields) {
                        ctrl.modalInstance.close(Entaxy.deepCopy(ctrl.formFields));
                    } else {
                        let args = entaxyService.getArguments(ctrl.formFields, ctrl.factories);
                        args.configProperties = ctrl.properties;
                        args.configurableOnly = ctrl.configurableOnly;
                        ctrl.modalInstance.close(args);
                    }
                }
            });
        }

        function getHotkeysConfigs() {
            return [
                {
                    ...Entaxy.getSaveHotkeyDescription(),
                    callback: function (event) {
                        event.preventDefault();
                        if (ctrl.mode === Entaxy.MODAL_MODES.EDIT ||
                            (ctrl.mode === Entaxy.MODAL_MODES.ADD && ctrl.step3)) {
                            ctrl.save();
                        }
                    }
                },
                {
                    ...Entaxy.getBackHotkeyDescription(),
                    callback: function (event) {
                        event.preventDefault();
                        if ((ctrl.step2 && ctrl.containers) ||
                            (ctrl.step3 && (ctrl.factories.length > 1 || ctrl.containers))) {
                            ctrl.back();
                        }
                    }
                },
                {
                    ...Entaxy.getNextHotkeyDescription(),
                    callback: function (event) {
                        event.preventDefault();
                        if ((ctrl.step1 && ctrl.selectedContainer) || (ctrl.step2 && ctrl.selectedFactory)) {
                            ctrl.next();
                        }
                    }
                }
            ];
        }
    }
    entaxyModalController.$inject = ['$scope', 'entaxyService', 'entaxyHotkeysService',
        'entaxyPrivateObjectsCacheService', 'entaxyProfileDiagramService'];

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