/*
 * Licensed to the Apache Software Foundation (ASF) under one or more
 * contributor license agreements.  See the NOTICE file distributed with
 * this work for additional information regarding copyright ownership.
 * The ASF licenses this file to You under the Apache License, Version 2.0
 * (the "License"); you may not use this file except in compliance with
 * the License.  You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

import { TdDataTableService } from '@covalent/core';
import { FdsDialogService } from '@flow-design-system/dialogs';
import { FdsSnackBarService } from '@flow-design-system/snackbars';
import { Component } from '@angular/core';
import NfRegistryService from 'services/nf-registry.service';
import { ActivatedRoute, Router } from '@angular/router';
import NfRegistryApi from 'services/nf-registry.api';
import { MatDialog } from '@angular/material';
import NfRegistryAddUsersToGroup from 'components/administration/users/dialogs/add-users-to-group/nf-registry-add-users-to-group';

/**
 * NfRegistryManageGroup constructor.
 *
 * @param nfRegistryApi         The api service.
 * @param nfRegistryService     The nf-registry.service module.
 * @param tdDataTableService    The covalent data table service module.
 * @param fdsDialogService      The FDS dialog service.
 * @param fdsSnackBarService    The FDS snack bar service module.
 * @param activatedRoute        The angular route module.
 * @param router                The angular router module.
 * @param matDialog             The angular material dialog module.
 * @constructor
 */
function NfRegistryManageGroup(nfRegistryApi, nfRegistryService, tdDataTableService, fdsDialogService, fdsSnackBarService, activatedRoute, router, matDialog) {
    // local state
    this.sortBy = null;
    this.sortOrder = null;
    this.filteredUsers = [];
    this.usersSearchTerms = [];
    this.groupname = '';
    this.manageGroupPerspective = 'membership';
    this.usersColumns = [
        {
            name: 'identity',
            label: 'Display Name',
            sortable: true,
            tooltip: 'Group name.',
            width: 100
        }
    ];

    // Services
    this.nfRegistryService = nfRegistryService;
    this.route = activatedRoute;
    this.router = router;
    this.dialog = matDialog;
    this.nfRegistryApi = nfRegistryApi;
    this.dialogService = fdsDialogService;
    this.snackBarService = fdsSnackBarService;
    this.dataTableService = tdDataTableService;
}

NfRegistryManageGroup.prototype = {
    constructor: NfRegistryManageGroup,

    /**
     * Initialize the component.
     */
    ngOnInit: function () {
        var self = this;
        // subscribe to the route params
        this.$subscription = self.route.params
            .switchMap(function (params) {
                return self.nfRegistryApi.getUserGroup(params['groupId']);
            })
            .subscribe(function (response) {
                if (!response.status || response.status === 200) {
                    self.nfRegistryService.sidenav.open();
                    self.nfRegistryService.group = response;
                    self.groupname = response.identity;
                    self.filterUsers();
                } else if (response.status === 404) {
                    self.router.navigateByUrl('/nifi-registry/administration/users');
                } else if (response.status === 409) {
                    self.router.navigateByUrl('/nifi-registry/administration/workflow');
                }
            });
    },

    /**
     * Destroy the component.
     */
    ngOnDestroy: function () {
        this.nfRegistryService.sidenav.close();
        this.$subscription.unsubscribe();
    },

    /**
     * Navigate to administer users for current registry.
     */
    closeSideNav: function () {
        this.router.navigateByUrl('/nifi-registry/administration/users');
    },

    /**
     * Toggles the manage bucket privileges for the group.
     *
     * @param $event
     * @param policyAction      The action to be toggled
     */
    toggleGroupManageBucketsPrivileges: function ($event, policyAction) {
        var self = this;
        if ($event.checked) {
            // eslint-disable-next-line no-restricted-syntax
            for (const resource in this.nfRegistryService.BUCKETS_PRIVS) {
                if (this.nfRegistryService.BUCKETS_PRIVS.hasOwnProperty(resource)) {
                    this.nfRegistryService.BUCKETS_PRIVS[resource].forEach(function (action) {
                        if (!policyAction || (action === policyAction)) {
                            self.nfRegistryApi.getPolicyActionResource(action, resource).subscribe(function (policy) {
                                if (policy.status && policy.status === 404) {
                                    // resource does NOT exist, let's create it
                                    self.nfRegistryApi.postPolicyActionResource(action, resource, self.nfRegistryService.group.users, []).subscribe(
                                        function (response) {
                                            // can manage buckets privileges created and granted!!!...now update the view
                                            response.userGroups.forEach(function (group) {
                                                if (group.identifier === self.nfRegistryService.group.identifier) {
                                                    self.nfRegistryApi.getUserGroup(self.nfRegistryService.group.identifier).subscribe(function (response) {
                                                        self.nfRegistryService.group = response;
                                                    });
                                                }
                                            });
                                        }
                                    );
                                } else {
                                    // resource exists, let's update it
                                    policy.userGroups.push(self.nfRegistryService.group);
                                    self.nfRegistryApi.putPolicyActionResource(policy.identifier, policy.action,
                                        policy.resource, policy.users, policy.userGroups).subscribe(
                                        function (response) {
                                            // can manage buckets privileges updated!!!...now update the view
                                            response.userGroups.forEach(function (group) {
                                                if (group.identifier === self.nfRegistryService.group.identifier) {
                                                    self.nfRegistryApi.getUserGroup(self.nfRegistryService.group.identifier).subscribe(function (response) {
                                                        self.nfRegistryService.group = response;
                                                    });
                                                }
                                            });
                                        }
                                    );
                                }
                            });
                        }
                    });
                }
            }
        } else {
            // Remove the current group from the administrator resources
            // eslint-disable-next-line no-restricted-syntax
            for (const resource in this.nfRegistryService.BUCKETS_PRIVS) {
                if (this.nfRegistryService.BUCKETS_PRIVS.hasOwnProperty(resource)) {
                    this.nfRegistryService.BUCKETS_PRIVS[resource].forEach(function (action) {
                        if (!policyAction || (action === policyAction)) {
                            self.nfRegistryApi.getPolicyActionResource(action, resource).subscribe(function (policy) {
                                if (policy.status && policy.status === 404) {
                                    // resource does NOT exist
                                } else {
                                    // resource exists, let's filter out the current group and update it
                                    policy.userGroups = policy.userGroups.filter(function (group) {
                                        return (group.identifier !== self.nfRegistryService.group.identifier);
                                    });
                                    self.nfRegistryApi.putPolicyActionResource(policy.identifier, policy.action,
                                        policy.resource, policy.users, policy.userGroups).subscribe(
                                        function (response) {
                                            // can manage buckets privileges updated!!!...now update the view
                                            self.nfRegistryApi.getUserGroup(self.nfRegistryService.group.identifier).subscribe(function (response) {
                                                self.nfRegistryService.group = response;
                                            });
                                        }
                                    );
                                }
                            });
                        }
                    });
                }
            }
        }
    },

    /**
     * Toggles the manage tenants privileges for the group.
     *
     * @param $event
     * @param policyAction      The action to be toggled
     */
    toggleGroupManageTenantsPrivileges: function ($event, policyAction) {
        var self = this;
        if ($event.checked) {
            // eslint-disable-next-line no-restricted-syntax
            for (const resource in this.nfRegistryService.TENANTS_PRIVS) {
                if (this.nfRegistryService.TENANTS_PRIVS.hasOwnProperty(resource)) {
                    this.nfRegistryService.TENANTS_PRIVS[resource].forEach(function (action) {
                        if (!policyAction || (action === policyAction)) {
                            self.nfRegistryApi.getPolicyActionResource(action, resource).subscribe(function (policy) {
                                if (policy.status && policy.status === 404) {
                                    // resource does NOT exist, let's create it
                                    self.nfRegistryApi.postPolicyActionResource(action, resource, self.nfRegistryService.group.users, []).subscribe(
                                        function (response) {
                                            // can manage tenants privileges created and granted!!!...now update the view
                                            response.userGroups.forEach(function (group) {
                                                if (group.identifier === self.nfRegistryService.group.identifier) {
                                                    self.nfRegistryApi.getUserGroup(self.nfRegistryService.group.identifier).subscribe(function (response) {
                                                        self.nfRegistryService.group = response;
                                                    });
                                                }
                                            });
                                        }
                                    );
                                } else {
                                    // resource exists, let's update it
                                    policy.userGroups.push(self.nfRegistryService.group);
                                    self.nfRegistryApi.putPolicyActionResource(policy.identifier, policy.action,
                                        policy.resource, policy.users, policy.userGroups).subscribe(
                                        function (response) {
                                            // can manage tenants privileges updated!!!...now update the view
                                            response.userGroups.forEach(function (group) {
                                                if (group.identifier === self.nfRegistryService.group.identifier) {
                                                    self.nfRegistryApi.getUserGroup(self.nfRegistryService.group.identifier).subscribe(function (response) {
                                                        self.nfRegistryService.group = response;
                                                    });
                                                }
                                            });
                                        }
                                    );
                                }
                            });
                        }
                    });
                }
            }
        } else {
            // Remove the current group from the administrator resources
            // eslint-disable-next-line no-restricted-syntax
            for (const resource in this.nfRegistryService.TENANTS_PRIVS) {
                if (this.nfRegistryService.TENANTS_PRIVS.hasOwnProperty(resource)) {
                    this.nfRegistryService.TENANTS_PRIVS[resource].forEach(function (action) {
                        if (!policyAction || (action === policyAction)) {
                            self.nfRegistryApi.getPolicyActionResource(action, resource).subscribe(function (policy) {
                                if (policy.status && policy.status === 404) {
                                    // resource does NOT exist
                                } else {
                                    // resource exists, let's filter out the current group and update it
                                    policy.userGroups = policy.userGroups.filter(function (group) {
                                        return (group.identifier !== self.nfRegistryService.group.identifier);
                                    });
                                    self.nfRegistryApi.putPolicyActionResource(policy.identifier, policy.action,
                                        policy.resource, policy.users, policy.userGroups).subscribe(
                                        function (response) {
                                            // can manage tenants privileges updated!!!...now update the view
                                            self.nfRegistryApi.getUserGroup(self.nfRegistryService.group.identifier).subscribe(function (response) {
                                                self.nfRegistryService.group = response;
                                            });
                                        }
                                    );
                                }
                            });
                        }
                    });
                }
            }
        }
    },

    /**
     * Toggles the manage policies privileges for the group.
     *
     * @param $event
     * @param policyAction      The action to be toggled
     */
    toggleGroupManagePoliciesPrivileges: function ($event, policyAction) {
        var self = this;
        if ($event.checked) {
            // eslint-disable-next-line no-restricted-syntax
            for (const resource in this.nfRegistryService.POLICIES_PRIVS) {
                if (this.nfRegistryService.POLICIES_PRIVS.hasOwnProperty(resource)) {
                    this.nfRegistryService.POLICIES_PRIVS[resource].forEach(function (action) {
                        if (!policyAction || (action === policyAction)) {
                            self.nfRegistryApi.getPolicyActionResource(action, resource).subscribe(function (policy) {
                                if (policy.status && policy.status === 404) {
                                    // resource does NOT exist, let's create it
                                    self.nfRegistryApi.postPolicyActionResource(action, resource, self.nfRegistryService.group.users, []).subscribe(
                                        function (response) {
                                            // can manage policies privileges created and granted!!!...now update the view
                                            response.userGroups.forEach(function (group) {
                                                if (group.identifier === self.nfRegistryService.group.identifier) {
                                                    self.nfRegistryApi.getUserGroup(self.nfRegistryService.group.identifier).subscribe(function (response) {
                                                        self.nfRegistryService.group = response;
                                                    });
                                                }
                                            });
                                        }
                                    );
                                } else {
                                    // resource exists, let's update it
                                    policy.userGroups.push(self.nfRegistryService.group);
                                    self.nfRegistryApi.putPolicyActionResource(policy.identifier, policy.action,
                                        policy.resource, policy.users, policy.userGroups).subscribe(
                                        function (response) {
                                            // can manage policies privileges updated!!!...now update the view
                                            response.userGroups.forEach(function (group) {
                                                if (group.identifier === self.nfRegistryService.group.identifier) {
                                                    self.nfRegistryApi.getUserGroup(self.nfRegistryService.group.identifier).subscribe(function (response) {
                                                        self.nfRegistryService.group = response;
                                                    });
                                                }
                                            });
                                        }
                                    );
                                }
                            });
                        }
                    });
                }
            }
        } else {
            // Remove the current group from the administrator resources
            // eslint-disable-next-line no-restricted-syntax
            for (const resource in this.nfRegistryService.POLICIES_PRIVS) {
                if (this.nfRegistryService.POLICIES_PRIVS.hasOwnProperty(resource)) {
                    this.nfRegistryService.POLICIES_PRIVS[resource].forEach(function (action) {
                        if (!policyAction || (action === policyAction)) {
                            self.nfRegistryApi.getPolicyActionResource(action, resource).subscribe(function (policy) {
                                if (policy.status && policy.status === 404) {
                                    // resource does NOT exist
                                } else {
                                    // resource exists, let's filter out the current group and update it
                                    policy.userGroups = policy.userGroups.filter(function (group) {
                                        return (group.identifier !== self.nfRegistryService.group.identifier);
                                    });
                                    self.nfRegistryApi.putPolicyActionResource(policy.identifier, policy.action,
                                        policy.resource, policy.users, policy.userGroups).subscribe(
                                        function (response) {
                                            // can manage policies privileges updated!!!...now update the view
                                            self.nfRegistryApi.getUserGroup(self.nfRegistryService.group.identifier).subscribe(function (response) {
                                                self.nfRegistryService.group = response;
                                            });
                                        }
                                    );
                                }
                            });
                        }
                    });
                }
            }
        }
    },

    /**
     * Toggles the manage proxy privileges for the group.
     *
     * @param $event
     * @param policyAction      The action to be toggled
     */
    toggleGroupManageProxyPrivileges: function ($event, policyAction) {
        var self = this;
        if ($event.checked) {
            // eslint-disable-next-line no-restricted-syntax
            for (const resource in this.nfRegistryService.PROXY_PRIVS) {
                if (this.nfRegistryService.PROXY_PRIVS.hasOwnProperty(resource)) {
                    this.nfRegistryService.PROXY_PRIVS[resource].forEach(function (action) {
                        if (!policyAction || (action === policyAction)) {
                            self.nfRegistryApi.getPolicyActionResource(action, resource).subscribe(function (policy) {
                                if (policy.status && policy.status === 404) {
                                    // resource does NOT exist, let's create it
                                    self.nfRegistryApi.postPolicyActionResource(action, resource, self.nfRegistryService.group.users, []).subscribe(
                                        function (response) {
                                            // can manage proxy privileges created and granted!!!...now update the view
                                            response.userGroups.forEach(function (group) {
                                                if (group.identifier === self.nfRegistryService.group.identifier) {
                                                    self.nfRegistryApi.getUserGroup(self.nfRegistryService.group.identifier).subscribe(function (response) {
                                                        self.nfRegistryService.group = response;
                                                    });
                                                }
                                            });
                                        }
                                    );
                                } else {
                                    // resource exists, let's update it
                                    policy.userGroups.push(self.nfRegistryService.group);
                                    self.nfRegistryApi.putPolicyActionResource(policy.identifier, policy.action,
                                        policy.resource, policy.users, policy.userGroups).subscribe(
                                        function (response) {
                                            // can manage proxy privileges updated!!!...now update the view
                                            response.userGroups.forEach(function (group) {
                                                if (group.identifier === self.nfRegistryService.group.identifier) {
                                                    self.nfRegistryApi.getUserGroup(self.nfRegistryService.group.identifier).subscribe(function (response) {
                                                        self.nfRegistryService.group = response;
                                                    });
                                                }
                                            });
                                        }
                                    );
                                }
                            });
                        }
                    });
                }
            }
        } else {
            // Remove the current group from the administrator resources
            // eslint-disable-next-line no-restricted-syntax
            for (const resource in this.nfRegistryService.PROXY_PRIVS) {
                if (this.nfRegistryService.PROXY_PRIVS.hasOwnProperty(resource)) {
                    this.nfRegistryService.PROXY_PRIVS[resource].forEach(function (action) {
                        if (!policyAction || (action === policyAction)) {
                            self.nfRegistryApi.getPolicyActionResource(action, resource).subscribe(function (policy) {
                                if (policy.status && policy.status === 404) {
                                    // resource does NOT exist
                                } else {
                                    // resource exists, let's filter out the current group and update it
                                    policy.userGroups = policy.userGroups.filter(function (group) {
                                        return (group.identifier !== self.nfRegistryService.group.identifier);
                                    });
                                    self.nfRegistryApi.putPolicyActionResource(policy.identifier, policy.action,
                                        policy.resource, policy.users, policy.userGroups).subscribe(
                                        function (response) {
                                            // can manage proxy privileges updated!!!...now update the view
                                            self.nfRegistryApi.getUserGroup(self.nfRegistryService.group.identifier).subscribe(function (response) {
                                                self.nfRegistryService.group = response;
                                            });
                                        }
                                    );
                                }
                            });
                        }
                    });
                }
            }
        }
    },

    /**
     * Opens a modal dialog UX enabling the addition of users to this group.
     */
    addUsersToGroup: function () {
        var self = this;
        this.dialog.open(NfRegistryAddUsersToGroup, {
            data: {
                group: this.nfRegistryService.group,
                disableClose: true
            }
        }).afterClosed().subscribe(function () {
            self.nfRegistryApi.getUserGroup(self.nfRegistryService.group.identifier)
                .subscribe(function (response) {
                    self.nfRegistryService.group = response;
                    self.groupname = response.identity;
                    self.filterUsers();
                });
        });
    },

    /**
     * Filter users.
     *
     * @param {string} [sortBy]       The column name to sort `usersColumns` by.
     * @param {string} [sortOrder]    The order. Either 'ASC' or 'DES'
     */
    filterUsers: function (sortBy, sortOrder) {
        // if `sortOrder` is `undefined` then use 'ASC'
        if (sortOrder === undefined) {
            if (this.sortOrder === undefined) {
                sortOrder = 'ASC';
            } else {
                sortOrder = this.sortOrder;
            }
        }
        // if `sortBy` is `undefined` then find the first sortable column in `usersColumns`
        if (sortBy === undefined) {
            if (this.sortBy === undefined) {
                var arrayLength = this.usersColumns.length;
                for (var i = 0; i < arrayLength; i++) {
                    if (this.usersColumns[i].sortable === true) {
                        sortBy = this.usersColumns[i].name;
                        //only one column can be actively sorted so we reset all to inactive
                        this.usersColumns.forEach(function (c) {
                            c.active = false;
                        });
                        //and set this column as the actively sorted column
                        this.usersColumns[i].active = true;
                        this.usersColumns[i].sortOrder = sortOrder;
                        break;
                    }
                }
            } else {
                sortBy = this.sortBy;
            }
        }

        var newUsersData = this.nfRegistryService.group.users || [];

        for (var i = 0; i < this.usersSearchTerms.length; i++) {
            newUsersData = this.filterData(newUsersData, this.usersSearchTerms[i], true);
        }

        newUsersData = this.dataTableService.sortData(newUsersData, sortBy, sortOrder);
        this.filteredUsers = newUsersData;
    },

    /**
     * Sort `users` by `column`.
     *
     * @param column    The column to sort by.
     */
    sortUsers: function (column) {
        if (column.sortable) {
            this.sortBy = column.name;
            this.sortOrder = (column.sortOrder === 'ASC') ? 'DESC' : 'ASC';
            column.sortOrder = this.sortOrder;
            this.filterUsers(this.sortBy, this.sortOrder);

            //only one column can be actively sorted so we reset all to inactive
            this.usersColumns.forEach(function (c) {
                c.active = false;
            });
            //and set this column as the actively sorted column
            column.active = true;
        }
    },

    /**
     * Remove user from group.
     *
     * @param user
     */
    removeUserFromGroup: function (user) {
        var self = this;
        var users = this.nfRegistryService.group.users.filter(function (u) {
            return u.identifier !== user.identifier;
        });

        this.nfRegistryApi.updateUserGroup(this.nfRegistryService.group.identifier, this.nfRegistryService.group.identity, users).subscribe(function (response) {
            self.nfRegistryApi.getUserGroup(self.nfRegistryService.group.identifier)
                .subscribe(function (response) {
                    self.nfRegistryService.group = response;
                    self.filterUsers();
                });
            self.snackBarService.openCoaster({
                title: 'Success',
                message: 'The user has been removed from the ' + self.nfRegistryService.group.identity + ' group.',
                verticalPosition: 'bottom',
                horizontalPosition: 'right',
                icon: 'fa fa-check-circle-o',
                color: '#1EB475',
                duration: 3000
            });
        });
    },

    /**
     * Update group name.
     *
     * @param groupname
     */
    updateGroupName: function (groupname) {
        var self = this;
        this.nfRegistryApi.updateUserGroup(this.nfRegistryService.group.identifier, groupname, this.nfRegistryService.group.users).subscribe(function (response) {
            if (!response.status || response.status === 200) {
                self.nfRegistryService.group = response;
                self.nfRegistryService.groups.filter(function (group) {
                    return self.nfRegistryService.group.identifier === group.identifier;
                }).forEach(function (group) {
                    group.identity = response.identity;
                });
                self.snackBarService.openCoaster({
                    title: 'Success',
                    message: 'This group name has been updated.',
                    verticalPosition: 'bottom',
                    horizontalPosition: 'right',
                    icon: 'fa fa-check-circle-o',
                    color: '#1EB475',
                    duration: 3000
                });
            } else if (response.status === 409) {
                self.groupname = self.nfRegistryService.group.identity;
                self.dialogService.openConfirm({
                    title: 'Error',
                    message: 'This group already exists. Please enter a different identity/group name.',
                    acceptButton: 'Ok',
                    acceptButtonColor: 'fds-warn'
                });
            }
        });
    },

    /**
     * Determine if 'Special Privileges' can be edited.
     * @returns {boolean}
     */
    canEditSpecialPrivileges: function () {
        return this.nfRegistryService.currentUser.resourcePermissions.policies.canWrite
                && this.nfRegistryService.registry.config.supportsConfigurableAuthorizer;
    }
};

NfRegistryManageGroup.annotations = [
    new Component({
        templateUrl: './nf-registry-manage-group.html'
    })
];

NfRegistryManageGroup.parameters = [
    NfRegistryApi,
    NfRegistryService,
    TdDataTableService,
    FdsDialogService,
    FdsSnackBarService,
    ActivatedRoute,
    Router,
    MatDialog
];

export default NfRegistryManageGroup;
