/*-
 * ~~~~~~licensing~~~~~~
 * entaxy-management-plugin
 * ==========
 * Copyright (C) 2020 - 2023 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('entaxySelect', {
        bindings: {
            type: '<',
            filter: '<',
            model: '=',
            updateParent: '<',
            updateParentFn: '<',
            options: '=',
            creationEnabled: '<',
            formController: '<'
        },
        template:
        `
          <div class="custom-select">
            <button type="button" class="btn-select form-control dropdown-toggle" id="filter" data-toggle="dropdown" aria-haspopup="true" aria-expanded="false">
              {{$ctrl.selectedOption.name}}
              <span class="caret"></span>
            </button>
            <ul class="dropdown-menu">
              <li ng-repeat="option in $ctrl.options" id="option.name" ng-click="$ctrl.changeSelection(option)">{{ option.name }}</li>
              <li id="addItem" class="dropdown-option-new" ng-click="$ctrl.showModal()" ng-if="$ctrl.creationEnabled">
                <span class="pficon pficon-add-circle-o"></span>
                {{$ctrl.createObjectOptionTitle}}
              </li>
            </ul>
          </div>
        `,
        controller: entaxySelectController
    })
    .name;

    function entaxySelectController(workspace, jolokiaService, jolokia, $q, $uibModal, entaxyService) {
        'ngInject';

        let ctrl = this;

        ctrl.$onInit = function() {

            ctrl.itemType = Entaxy.getItemTypeFromRuntimeType(ctrl.type);

            if (ctrl.creationEnabled) {
                ctrl.createObjectOptionTitle = 'New private ' + ctrl.itemType + '...';
            }

            if (!ctrl.options) {

                let domain = entaxyService.getDomainFolder();
                let typedMBeans = entaxyService.getAllChildMBeansByRuntimeType(domain, ctrl.type);

                if (ctrl.filter) {
                    let filteredMbeans = [];
                    typedMBeans.forEach(mbean => {
                        let label = jolokia.getAttribute(mbean.objectName, 'Label');
                        if (label.match(ctrl.filter)) {
                            filteredMbeans.push(mbean);
                        }
                    });
                    typedMBeans = filteredMbeans;
                }

                let items = typedMBeans.map(mbean => { return { name: jolokia.getAttribute(mbean.objectName, 'Name') }; });

                if (items && items.length > 0) {
                    ctrl.options = items.sort(Entaxy.compareBy('name'));
                    ctrl.changeSelection(items[0]);
                } else {
                    ctrl.options = [];
                    let notificationType = ctrl.creationEnabled ? 'warning' : 'danger';
                    Core.notification(notificationType, 'There are no suitable ' + ctrl.itemType, 5000);
                    // todo close the modal if creation isn't enabled
                }
            }  else {
                ctrl.selectedOption = ctrl.options.find((option) => option.name === ctrl.model || option.value === ctrl.model);
            }
        }

        ctrl.changeSelection = function (option) {
            if (ctrl.selectedOption !== option) {
                let previousOption = ctrl.selectedOption;
                ctrl.selectedOption = option;
                ctrl.model = option.value ? option.value : option.name;

                if (previousOption && ctrl.formController && !ctrl.formController.$dirty) {
                    ctrl.formController.$setDirty();
                }

                if (ctrl.updateParent) {
                    if (previousOption) {
                        Core.notification('warning',
                            'Changing ' + ctrl.itemType + ' field value may lead to changes in other fields of the current object. ' +
                            'Please, make sure to revise all fields before accepting.', 10000);
                    }
                    ctrl.updateParentFn(previousOption, option, Entaxy.capitalize(ctrl.itemType));
                }
            }
        }

        ctrl.showModal = function() {

            let factories = [];
            let promises = [];

            let factoryFolder = entaxyService.getDomainFolder().findDescendant(child => child.title === ctrl.type);

            if (factoryFolder && factoryFolder.children) {
                factoryFolder.children.forEach((child) => {
                    promises.push(jolokiaService.getAttributes(child.objectName, ['Abstract', 'DisplayName', 'Label', 'Description', 'Deprecated'])
                    .then((result) => {
                        let label = result['Label'];

                        if (!result['Abstract']) {
                            if (!ctrl.filter || (ctrl.filter && label && label.indexOf(ctrl.filter) > -1)) {
                                factories.push({
                                    name: child.title,
                                    displayName: result['DisplayName'] ? result['DisplayName'] : child.title,
                                    label: result['Label'],
                                    mbeanName: child.objectName,
                                    description: result['Description'] ? result['Description'] : 'There is no description for this factory.',
                                    additionalInfo: result['Deprecated'] ? ['[DEPRECATED]'] : undefined
                                });
                            }
                        }
                    }));
                });

                $uibModal.open({
                    component: 'entaxyModal',
                    resolve: {
                        mode: () => Entaxy.MODAL_MODES.ADD,
                        itemType: () => Entaxy.capitalize(ctrl.itemType),
                        factories: $q.all(promises).then(() => factories)
                    },
                    size: 'xl',
                    backdrop: 'static',
                    windowTopClass: 'modal-top-margin-override'
                })
                .result.then(args => {
                    addItem(args);
                },
                reason => {
                    if (reason) {
                        Core.notification('danger', reason, 5000);
                    }
                });
            }
        }

        function addItem(args) {

            let factoryId = args.factoryId.name;

            let objectId = args.fields.find((field) => field.name === 'objectId').value;

            let fields = objectId ? args.fields.filter((field) => field.name !== 'objectId') : args.fields;

            let properties = fields.reduce((obj, cur) => ({ ...obj, [cur.name] : cur.value }), {});

            let newObjectProperties = {
                factoryId: factoryId,
                objectId: objectId,
                scope: 'private',
                properties: properties
            };

            let newObjectOption = {
                name: objectId ? objectId : ('private-' + ctrl.itemType),
                value: newObjectProperties
            };

            ctrl.options.push(newObjectOption);
            ctrl.changeSelection(newObjectOption);
        }
    }
    entaxySelectController.$inject = ['workspace', 'jolokiaService', 'jolokia', '$q', '$uibModal', 'entaxyService'];

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