/*-
 * ~~~~~~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('entaxyGroupsAndRolesList', {
        bindings: {
            username: '<',
            reloadFn: '<'
        },
        template:
        `
            <entaxy-expandable-list items="$ctrl.items" action-buttons="$ctrl.actionButtons" use-toolbar="true"
                toolbar-action-buttons="$ctrl.toolbarActionButtons"
                enable-toolbar-action-buttons="$ctrl.username ? true : false"
                empty-state-config="$ctrl.emptyStateConfig">
            </entaxy-expandable-list>
        `,
        controller: EntaxyGroupsAndRolesListController
    })
    .name;

    function EntaxyGroupsAndRolesListController(workspace, operationsService, entaxyService, $q, $scope, $uibModal) {
        'ngInject';

        let ctrl = this;
        let selectedMbeanName = workspace.getSelectedMBeanName();

        let ITEM_TYPES = {
            ROLE: 'Role',
            GROUP: 'Group'
        }

        ctrl.toolbarActionButtons = [
            { name: 'Add Group', actionFn: () => showAddGroupModal(), isDisabled: ctrl.username ? false : true },
            { name: 'Add Role', actionFn: () => showAddRoleModal(), isDisabled: ctrl.username ? false : true }
        ];

        ctrl.emptyStateConfig = {
            title: 'There is no selected user'
        };

        ctrl.actionButtons = [{
            name: 'Delete',
            actionFn: deleteRoleOrGroup
        }];

        $scope.$watch('$ctrl.username', function (newValue, oldValue) {
            if (newValue) {
                populateItems();
            } else {
                ctrl.items = [];
            }
        })

        function populateItems() {
            let promises = [];
            promises.push(listRolesOrGroups(ctrl.username, 'listRolesForUser'));
            promises.push(listRolesOrGroups(ctrl.username, 'listGroupsForUser'));
            promises.push(operationsService.executeOperation(selectedMbeanName, { name: 'listGroups'}, []));

            $q.all(promises).then(result => {
                let roles = JSON.parse(result[0]);
                ctrl.roles = JSON.parse(result[0]).map(role => role.name);

                let items = [];

                let userGroups = JSON.parse(result[1]);
                let allGroups = JSON.parse(result[2]);
                userGroups.forEach(group => {
                    let groupWithRoles = allGroups.find(groupWithRoles => group.name === groupWithRoles.name);
                    groupWithRoles.roles = groupWithRoles.roles.split(',').sort(Entaxy.compare());
                    groupWithRoles.isGroup = true;

                    roles = roles.filter(role => !groupWithRoles.roles.includes(role.name));

                    items.push(groupWithRoles);
                });

                items.push(...roles);

                items.map(item => {
                    item.displayName = item.name;
                    if (item.roles) {
                        item.sublist = item.roles.map(role => {
                            return {
                                displayName: role,
                                typeIcon: 'pf pficon-user',
                                disableRowExpansion: true
                            };
                        });
                    } else {
                        item.disableRowExpansion = true;
                    }

                    item.typeIcon = item.isGroup ? 'pf pficon-users' : 'pf pficon-user';

                    return item;
                });

                ctrl.items = items.sort(Entaxy.compareBy('displayName'));
            });
        }

        function listRolesOrGroups(username, operationName) {
            return operationsService.executeOperation(selectedMbeanName, { name: operationName }, [ username ]);
        }

        function showAddRoleModal() {
            openUserManagementModalAndProcess(ITEM_TYPES.ROLE);
        }

        function showAddGroupModal() {
            operationsService.executeOperation(selectedMbeanName, {name: 'listGroups'}, [])
            .then(list => {
                let items = JSON.parse(list);
                let values = items
                    .filter(item => !includesGroup(item.name))
                    .map(item => item.name)
                    .sort(Entaxy.compare());
                openUserManagementModalAndProcess(ITEM_TYPES.GROUP, values);
            });
        }

        function openUserManagementModalAndProcess(itemType, values) {
            if (itemType === ITEM_TYPES.GROUP && values.length === 0) {
                Entaxy.notificationInfo('There are no groups that can be added');
                return;
            }

            $uibModal.open({
                component: 'entaxyUserManagementModal',
                resolve: {
                    modalTitle: () => 'Add ' + itemType + ' to ' + ctrl.username,
                    formFields: () => getFormFields(itemType, values)
                },
                backdrop: 'static'
            }).result.then((args) => {
                entaxyService.processUserManagementOperation('add' + itemType, args, populateItems);
            }, reason => {
                if (reason && reason !== Entaxy.MODAL_CANCEL_REASON.ESCAPE_KEY_PRESS) {
                    Entaxy.notificationError(reason);
                }
            });
        }

        function getFormFields(itemType, values) {
            let formFields = [
                {
                    label: 'Username',
                    name: 'username',
                    type: 'text',
                    required: true,
                    value: ctrl.username,
                    readOnly: true
                },
                {
                    label: itemType + ' Name',
                    name: Entaxy.uncapitalize(itemType),
                    type: 'text',
                    required: true,
                    enum: itemType === ITEM_TYPES.GROUP ? true : false,
                    values: itemType === ITEM_TYPES.GROUP ? values : undefined,
                    validation: itemType === ITEM_TYPES.ROLE ? {
                        checkUniqueness: true,
                        values: ctrl.roles
                    } : undefined,
                    setFocused: itemType === ITEM_TYPES.ROLE ? true : undefined
                }
            ];

            return formFields;
        }

        function includesGroup(itemName) {
            let item = ctrl.items.find(item => item.name === itemName);
            return item && item.isGroup;
        }

        function deleteRoleOrGroup(action, item) {
            let operationName = item.isGroup ? 'deleteGroup' : 'deleteRole';
            let postProcessFn = item.isGroup ? ctrl.reloadFn : populateItems;
            entaxyService.processUserManagementOperation(operationName, [ ctrl.username, item.name ], postProcessFn);
        }
    }
    EntaxyGroupsAndRolesListController.$inject = ['workspace', 'operationsService', 'entaxyService', '$q', '$scope',
        '$uibModal'];

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