/*-
 * ~~~~~~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('entaxySource', {
        template:
        `
          <div class="route-source-header-container">
            <div>
              <h2>
                Source
              </h2>
              <span ng-if="$ctrl.xml.trim().length === 0">
                {{$ctrl.errorMessage}}
              </span>
              <span ng-if="($ctrl.isDirty || $ctrl.hasChangedPrivateObjects) && $ctrl.xml.trim().length > 0">
                There are unsaved changes
              </span>
            </div>
            <button type="submit" class="btn btn-primary" ng-click="$ctrl.saveAll()"
                    ng-if="$ctrl.isContentPresent && !$ctrl.readOnly && $ctrl.private"
                    ng-disabled="!$ctrl.isOwnerChanged && !$ctrl.isDirty">Save all</button>
            <button type="submit" class="btn btn-primary" ng-click="$ctrl.save()"
                    ng-if="$ctrl.isContentPresent && !$ctrl.readOnly">Save</button>
          </div>
          <div ng-if="$ctrl.isContentReady">
            <div class="xml-route-source-container">
              <entaxy-xml-editor class="entaxy-editor" source-doc="$ctrl.xml" read-only="$ctrl.readOnly">
              </entaxy-xml-editor>
            </div>
          </div>
          <div ng-if="$ctrl.isContentPresent === false">There is no viewable content.</div>
        `,
        controller: entaxySourceController
    })
    .name;

    function entaxySourceController(workspace, $location, operationsService, $scope, entaxyHotkeysService,
                                    entaxyService, entaxyAttributesCacheService, entaxyPrivateObjectsCacheService) {
        'ngInject';

        let ctrl = this;
        ctrl.errorMessage = 'Value cannot be empty';

        ctrl.$onInit = function() {
            entaxyHotkeysService.setHotkeys($scope, getHotkeysConfigs());

            let selectedMbean = workspace.getSelectedMBean();
            let selectedMbeanName = selectedMbean.objectName;

            if (selectedMbeanName) {
                populateExistentObjectInfo(selectedMbeanName);
            } else {
                populateAddedObjectInfo(selectedMbean);
            }
        }

        function populateExistentObjectInfo(mbeanName) {
            let attributes = entaxyAttributesCacheService.getAttributes(mbeanName);

            if (attributes.Scope === Entaxy.SCOPE.PRIVATE) {
                ctrl.private = true;
                ctrl.objectFullId = attributes.ObjectFullId;
                ctrl.owner = attributes.Owner;
                ctrl.isToRemoval = entaxyPrivateObjectsCacheService.isObjectSetToRemoval(ctrl.objectFullId);
                ctrl.itemInfo = entaxyPrivateObjectsCacheService.getChangedObjectConfig(ctrl.objectFullId);
            } else if (entaxyPrivateObjectsCacheService.isChanged(mbeanName)) {
                ctrl.hasChangedPrivateObjects = true;
            }

            entaxyService.readObjectClusterState(mbeanName).then(objectClusterState => {
                ctrl.nonClustered = objectClusterState === Entaxy.OBJECT_CLUSTER_STATE.NON_CLUSTERED;
                if (ctrl.nonClustered) {
                    Entaxy.notificationInfo(Entaxy.NON_CLUSTERED_MESSAGE.EDITING);
                } else {
                    ctrl.local = objectClusterState === Entaxy.OBJECT_CLUSTER_STATE.LOCAL;
                }
            }).catch(e => Entaxy.notificationError(e));

            if (!ctrl.itemInfo) {
                entaxyService.readConfiguration(mbeanName).then(info => {
                    init(info);

                    if (ctrl.isContentPresent) {
                        if (!ctrl.private) {
                            ctrl.args = entaxyService.getArgumentsFromConfig(info);
                        } else {
                            ctrl.itemInfo = info;
                        }
                    }
                });
            } else {
                init(ctrl.itemInfo);
            }
        }

        function populateAddedObjectInfo(mbean) {
            ctrl.private = true;

            let parentMbeanName = mbean.parent.objectName;
            let objectsInfo = entaxyPrivateObjectsCacheService.getAddedObjectsInfo(parentMbeanName);
            let objectInfo = objectsInfo.find(objInfo => mbean.key === mbean.parent.key + '-' + objInfo.ui.id);

            ctrl.itemInfo = objectInfo;
            ctrl.owner = ctrl.itemInfo.ui.owner;
            ctrl.isToRemoval = ctrl.itemInfo.toRemoval;

            init(objectInfo);
        }

        function init(info) {
            setOwnerChanged();
            ctrl.readOnly = info.configurableOnly || ctrl.nonClustered || ctrl.isToRemoval;

            let routeContent = info.properties.routeContent;
            if (routeContent) {
                ctrl.isContentPresent = true;

                entaxyService.getXmlFromConfigPropertyValue(routeContent).then(xml => {
                    ctrl.isContentReady = true;
                    ctrl.xml = xml;
                });
            } else {
                ctrl.isContentPresent = false;
            }
        }

        $scope.$watch('$ctrl.xml', function (newValue, oldValue) {
            if (newValue && oldValue && newValue !== oldValue) {
                if (!ctrl.isDirty) {
                    ctrl.isDirty = true;
                }
            }
        });

        setTimeout( function () {
            ctrl.activeTabIndex = entaxyService.getActiveTabIndex();
        })

        $scope.$on("$locationChangeStart", function(event) {
            if (ctrl.isDirty && !confirm(Entaxy.CONFIRMATION.UNSAVED_CHANGES)) {
                event.preventDefault();
                ctrl.isTreeOrTabSelectionUpdateNeeded = true;
            }
        });

        $scope.$watch('$ctrl.isTreeOrTabSelectionUpdateNeeded', function (newValue) {
            if (newValue) {
                setTimeout(function () {
                    entaxyService.updateTabSelection(ctrl.activeTabIndex);
                });
                Jmx.updateTreeSelectionFromURL($location, $(entaxyTreeElementId));
                ctrl.isTreeOrTabSelectionUpdateNeeded = false;
            }
        });

        ctrl.save = function() {
            let isConfirmationNeeded = !ctrl.isDirty && !ctrl.hasChangedPrivateObjects;
            entaxyService.requestConfirmationForSavingIfNeededAndProceed(isConfirmationNeeded, save);
        };

        ctrl.saveAll = function () {
            entaxyService.requestConfirmationForSavingOwnerAndProceed(saveAll);
        }

        function save() {
            if (ctrl.xml.trim().length !== 0) {
                let base64Xml = Entaxy.stringToBase64(ctrl.xml);
                if (!ctrl.private) {
                    let property = ctrl.args.fields.find(property => property.name === 'routeContent');
                    property.value = base64Xml;

                    entaxyService.resolveRoutesFieldValueAndAddNew(ctrl.args, workspace.getSelectedMBean())
                    .then(() => {
                        entaxyService.saveItem(ctrl.args, ctrl.local, update);
                    });
                } else {
                    ctrl.itemInfo.properties.routeContent = base64Xml;

                    let selectedMbean = workspace.getSelectedMBean();
                    if (selectedMbean.objectName) {
                        entaxyPrivateObjectsCacheService
                            .addChanges(selectedMbean, ctrl.objectFullId, ctrl.owner, ctrl.itemInfo);
                    } else {
                        let routeContentFormField = ctrl.itemInfo.ui.formFields
                            .find(formField => formField.name === 'routeContent');
                        routeContentFormField.value = ctrl.xml;
                    }

                    Entaxy.notificationSuccess('Operation Succeeded');
                    update();
                }
            }
        }

        function saveAll() {
            if (ctrl.xml.trim().length !== 0) {
                let base64Xml = Entaxy.stringToBase64(ctrl.xml);
                ctrl.itemInfo.properties.routeContent = base64Xml;

                let selectedMbean = workspace.getSelectedMBean();
                if (selectedMbean.objectName) {
                    entaxyPrivateObjectsCacheService
                        .addChanges(selectedMbean, ctrl.objectFullId, ctrl.owner, ctrl.itemInfo);
                } else {
                    let routeContentFormField = ctrl.itemInfo.ui.formFields
                        .find(formField => formField.name === 'routeContent');
                    routeContentFormField.value = ctrl.xml;
                }

                let ownerMbean = entaxyPrivateObjectsCacheService.findOwnerMbean(selectedMbean, ctrl.owner);
                let ownerMbeanName = ownerMbean.objectName;

                entaxyService.readObjectClusterState(ownerMbeanName).then(objectClusterState => {
                    if (objectClusterState !== Entaxy.OBJECT_CLUSTER_STATE.NON_CLUSTERED) {
                        let local = objectClusterState === Entaxy.OBJECT_CLUSTER_STATE.LOCAL;

                        entaxyService.readConfiguration(ownerMbeanName)
                        .then(objectInfo => {
                            let args = entaxyService.getArgumentsFromConfig(objectInfo);

                            entaxyService.resolveRoutesFieldValueAndAddNew(args, ownerMbean)
                            .then(() => {
                                entaxyService.resolveResourceRefFields(args.fields)
                                .then(() => entaxyService.saveItem(args, local, update));
                            });
                        }).catch(error => {
                            Entaxy.notificationError(error);
                            Entaxy.log.error(error);
                        });
                    } else {
                        Entaxy.notificationError(Entaxy.NON_CLUSTERED_MESSAGE.EDITING);
                    }
                }).catch(e => Entaxy.notificationError(e));
            }
        }

        function update(properties, objectId) {
            if (ctrl.private && objectId && !ctrl.objectFullId) {
                let nid = $location.search().nid;
                let oldId = ctrl.itemInfo.ui.id;
                $location.search('nid', nid.replace('-' + oldId, ''));
            }
            if (!ctrl.private && objectId) {
                ctrl.hasChangedPrivateObjects = entaxyPrivateObjectsCacheService
                    .isChanged(workspace.getSelectedMBeanName());
            }
            setOwnerChanged();
            ctrl.isDirty = false;
        }

        function setOwnerChanged() {
            if (ctrl.private) {
                ctrl.isOwnerChanged = entaxyPrivateObjectsCacheService
                    .isOwnerChanged(workspace.getSelectedMBean(), ctrl.owner);
            }
        }

        function getHotkeysConfigs() {
            return [
                {
                    ...Entaxy.getSaveHotkeyDescription(),
                    callback: function (event) {
                        event.preventDefault();
                        if (ctrl.isContentPresent && !ctrl.readOnly) {
                            ctrl.save();
                        }
                    }
                },
                {
                    ...Entaxy.getSaveAllHotkeyDescription(),
                    callback: function(event) {
                        event.preventDefault();
                        if (ctrl.isContentPresent && !ctrl.readOnly && ctrl.private &&
                            (ctrl.isOwnerChanged || ctrl.isDirty)) {
                            ctrl.saveAll();
                        }
                    }
                }
            ];
        }
    }
    entaxySourceController.$inject = ['workspace', '$location', 'operationsService', '$scope', 'entaxyHotkeysService',
        'entaxyService', 'entaxyAttributesCacheService', 'entaxyPrivateObjectsCacheService'];

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