'use strict';

/* global angular */
/* global Clipboard */
/* global async */
/* global $ */

angular.module('Application').controller('UsersController', ['$scope', '$location', '$translate', '$timeout', 'Client', function ($scope, $location, $translate, $timeout, Client) {
    Client.onReady(function () { if (!Client.getUserInfo().isAtLeastUserManager) $location.path('/'); });

    $scope.ldapProvider = [
        { name: 'Active Directory', value: 'ad' },
        { name: 'Jumpcloud', value: 'jumpcloud' },
        { name: 'Okta', value: 'okta' },
        { name: 'Univention Corporate Server (UCS)', value: 'univention' },
        { name: 'Other', value: 'other' },
        { name: 'Disabled', value: 'noop' }
    ];

    $scope.ready = false;
    $scope.users = []; // users of current page
    $scope.allUsersById = [];
    $scope.groups = [];
    $scope.groupsById = { };
    $scope.config = Client.getConfig();
    $scope.userInfo = Client.getUserInfo();

    $scope.openSubscriptionSetup = function () {
        Client.openSubscriptionSetup($scope.$parent.subscription);
    };

    $scope.roles = [];
    $scope.allUsers = []; // all the users and not just current page, have to load this for group assignment

    $scope.userSearchString = '';
    $scope.currentPage = 1;
    $scope.pageItemCount = [
        { name: $translate.instant('main.pagination.perPageSelector', { n: 20 }), value: 20 },
        { name: $translate.instant('main.pagination.perPageSelector', { n: 50 }), value: 50 },
        { name: $translate.instant('main.pagination.perPageSelector', { n: 100 }), value: 100 }
    ];
    $scope.pageItems = $scope.pageItemCount[0];
    $scope.userRefreshBusy = true;

    $scope.groupMembers = function (group) {
        return group.userIds.filter(function (uid) { return !!$scope.allUsersById[uid]; }).map(function (uid) { return $scope.allUsersById[uid].username || $scope.allUsersById[uid].email; }).join(' ');
    };

    $scope.canEdit = function (user) {
        let roleInt1 = $scope.roles.findIndex(function (role) { return role.id === $scope.userInfo.role; });
        let roleInt2 = $scope.roles.findIndex(function (role) { return role.id === user.role; });

        return (roleInt1 - roleInt2) >= 0;
    };

    $scope.transferOwnership = {
        busy: false,
        error: null,
        selectedUser: null,

        show: function () {
            $scope.transferOwnership.error = null;
            $scope.transferOwnership.selectedUser = null;

            $('#transferOwnershipModal').modal('show');
        },

        submit: function () {
            $scope.transferOwnership.busy = true;

            Client.changeOwnership($scope.transferOwnership.selectedUser.id, function (error) {
                $scope.transferOwnership.busy = false;

                if (error) {
                    $scope.transferOwnership.error = error.message;
                    console.error('Unable to change user role:', error);
                    return;
                }

                $('#transferOwnershipModal').modal('hide');

                // current user was demoted, reload to refresh UI state
                window.location.reload();
            });
        }
    };

    $scope.userremove = {
        busy: false,
        error: null,
        userInfo: {},

        show: function (userInfo) {
            $scope.userremove.error = null;
            $scope.userremove.userInfo = userInfo;

            $('#userRemoveModal').modal('show');
        },

        submit: function () {
            $scope.userremove.busy = true;

            Client.removeUser($scope.userremove.userInfo.id, function (error) {
                $scope.userremove.busy = false;

                if (error && error.statusCode === 403) return $scope.userremove.error = error.message;
                else if (error) return console.error('Unable to delete user.', error);

                $scope.userremove.userInfo = {};

                refresh();
                refreshAllUsers();

                $('#userRemoveModal').modal('hide');
            });
        }
    };

    $scope.useradd = {
        busy: false,
        alreadyTaken: false,
        error: {},
        email: '',
        username: '',
        displayName: '',
        sendInvite: true,
        selectedGroups: [],
        role: 'user',

        show: function () {
            if ($scope.config.features.userMaxCount && $scope.config.features.userMaxCount <= $scope.allUsers.length) {
                $('#subscriptionRequiredModal').modal('show');
                return;
            }

            $scope.useradd.error = {};
            $scope.useradd.email = '';
            $scope.useradd.username = '';
            $scope.useradd.displayName = '';
            $scope.useradd.selectedGroups = [];
            $scope.useradd.role = 'user';

            $scope.useradd_form.$setUntouched();
            $scope.useradd_form.$setPristine();

            $('#userAddModal').modal('show');
        },

        submit: function () {
            $scope.useradd.busy = true;

            $scope.useradd.alreadyTaken = false;
            $scope.useradd.error.email = null;
            $scope.useradd.error.username = null;
            $scope.useradd.error.displayName = null;

            var user = {
                username: $scope.useradd.username || null,
                email: $scope.useradd.email,
                displayName: $scope.useradd.displayName,
                role: $scope.useradd.role
            };

            Client.createUser(user, function (error, newUserInfo) {
                if (error) {
                    $scope.useradd.busy = false;

                    if (error.statusCode === 409) {
                        if (error.message.toLowerCase().indexOf('email') !== -1) {
                            $scope.useradd.error.email = 'Email already taken';
                            $scope.useradd_form.email.$setPristine();
                            $('#inputUserAddEmail').focus();
                        } else if (error.message.toLowerCase().indexOf('username') !== -1 || error.message.toLowerCase().indexOf('mailbox') !== -1) {
                            $scope.useradd.error.username = 'Username already taken';
                            $scope.useradd_form.username.$setPristine();
                            $('#inputUserAddUsername').focus();
                        } else {
                            // should not happen!!
                            console.error(error.message);
                        }
                        return;
                    } else if (error.statusCode === 400) {
                        if (error.message.toLowerCase().indexOf('email') !== -1) {
                            $scope.useradd.error.email = 'Invalid Email';
                            $scope.useradd.error.emailAttempted = $scope.useradd.email;
                            $scope.useradd_form.email.$setPristine();
                            $('#inputUserAddEmail').focus();
                        } else if (error.message.toLowerCase().indexOf('username') !== -1) {
                            $scope.useradd.error.username = error.message;
                            $scope.useradd_form.username.$setPristine();
                            $('#inputUserAddUsername').focus();
                        } else {
                            console.error('Unable to create user.', error.statusCode, error.message);
                        }
                        return;
                    } else {
                        return console.error('Unable to create user.', error.statusCode, error.message);
                    }
                }

                var groupIds = $scope.useradd.selectedGroups.map(function (g) { return g.id; });
                var NOOP = function (next) { next(); };

                async.series([
                    Client.setGroups.bind(Client, newUserInfo.id, groupIds),
                    $scope.useradd.sendInvite ? Client.createInvite.bind(Client, newUserInfo.id) : NOOP,
                    $scope.useradd.sendInvite ? Client.sendInvite.bind(Client, newUserInfo.id) : NOOP
                ], function (error) {
                    $scope.useradd.busy = false;

                    if (error) return console.error(error);

                    refresh();
                    refreshAllUsers();

                    $('#userAddModal').modal('hide');
                });
            });
        }
    };

    $scope.useredit = {
        busy: false,
        error: {},
        userInfo: {},

        // form fields
        email: '',
        fallbackEmail: '',
        aliases: {},
        displayName: '',
        active: false,
        source: '',
        selectedGroups: [],
        role: '',

        show: function (userInfo) {
            $scope.useredit.error = {};
            $scope.useredit.email = userInfo.email;
            $scope.useredit.displayName = userInfo.displayName;
            $scope.useredit.fallbackEmail = userInfo.fallbackEmail;
            $scope.useredit.userInfo = userInfo;
            $scope.useredit.selectedGroups = userInfo.groupIds.map(function (gid) { return $scope.groupsById[gid]; });
            $scope.useredit.active = userInfo.active;
            $scope.useredit.source = userInfo.source;
            $scope.useredit.role = userInfo.role;

            $scope.useredit_form.$setPristine();
            $scope.useredit_form.$setUntouched();

            $('#userEditModal').modal('show');
        },

        submit: function () {
            $scope.useredit.error = {};
            $scope.useredit.busy = true;

            var userId = $scope.useredit.userInfo.id;
            var data = {
                id: userId
            };

            // only send if not the current active user
            if (userId !== $scope.userInfo.id) {
                data.active = $scope.useredit.active;
                data.role = $scope.useredit.role;
            }

            // only change those if it is a local user
            if (!$scope.useredit.source) {
                data.email = $scope.useredit.email;
                data.displayName = $scope.useredit.displayName;
                data.fallbackEmail = $scope.useredit.fallbackEmail;
            }

            Client.updateUser(data, function (error) {
                if (error) {
                    $scope.useredit.busy = false;

                    if (error.statusCode === 409) {
                        $scope.useredit.error.email = 'Email already taken';
                        $scope.useredit_form.email.$setPristine();
                        $('#inputUserEditEmail').focus();
                    } else {
                        $scope.useredit.error.generic = error.message;
                        console.error('Unable to update user:', error);
                    }

                    return;
                }

                var groupIds = $scope.useredit.selectedGroups.map(function (g) { return g.id; });

                Client.setGroups(data.id, groupIds, function (error) {
                    $scope.useredit.busy = false;

                    if (error) return console.error('Unable to update groups for user:', error);

                    refreshUsers(false);

                    $('#userEditModal').modal('hide');
                });
            });
        }
    };

    $scope.groupAdd = {
        busy: false,
        error: {},
        name: '',
        selectedUsers: [],

        show: function () {
            if (!$scope.config.features.userGroups && $scope.groups.length > 0) {
                $('#subscriptionRequiredGroupModal').modal('show');
                return;
            }

            $scope.groupAdd.busy = false;

            $scope.groupAdd.error = {};
            $scope.groupAdd.name = '';

            $scope.groupAddForm.$setUntouched();
            $scope.groupAddForm.$setPristine();

            $('#groupAddModal').modal('show');
        },

        submit: function () {
            $scope.groupAdd.busy = true;
            $scope.groupAdd.error = {};

            Client.createGroup($scope.groupAdd.name, function (error, result) {
                if (error) {
                    $scope.groupAdd.busy = false;

                    if (error.statusCode === 409) {
                        $scope.groupAdd.error.name = 'Name already taken';
                        $scope.groupAddForm.name.$setPristine();
                        $('#groupAddName').focus();
                        return;
                    } else if (error.statusCode === 400) {
                        $scope.groupAdd.error.name = error.message;
                        $scope.groupAddForm.name.$setPristine();
                        $('#groupAddName').focus();
                        return;
                    } else {
                        return console.error('Unable to create group.', error.statusCode, error.message);
                    }
                }

                var userIds = $scope.groupAdd.selectedUsers.map(function (u) { return u.id; });

                Client.setGroupMembers(result.id, userIds, function (error) {
                    $scope.groupAdd.busy = false;

                    if (error) return console.error('Unable to add memebers.', error.statusCode, error.message);

                    refresh();

                    $('#groupAddModal').modal('hide');
                });
            });
        }
    };

    $scope.groupEdit = {
        busy: false,
        error: {},
        groupInfo: {},
        name: '',
        source: '',
        selectedUsers: [],
        selectedApps: [],
        selectedAppsOriginal: [],
        apps: [],

        show: function (groupInfo) {
            $scope.groupEdit.error = {};
            $scope.groupEdit.groupInfo = groupInfo;
            $scope.groupEdit.name = groupInfo.name;
            $scope.groupEdit.source = groupInfo.source;
            $scope.groupEdit.selectedUsers = groupInfo.userIds.map(function (uid) { return $scope.allUsersById[uid]; });
            $scope.groupEdit.apps = Client.getInstalledApps();

            $scope.groupEdit.selectedApps = Client.getInstalledApps().filter(function (app) {
                if (app.accessRestriction === null || !Array.isArray(app.accessRestriction.groups)) return false;
                return app.accessRestriction.groups.indexOf(groupInfo.id) !== -1;
            });
            angular.copy($scope.groupEdit.selectedApps, $scope.groupEdit.selectedAppsOriginal);

            $scope.groupEdit_form.$setPristine();
            $scope.groupEdit_form.$setUntouched();

            $('#groupEditModal').modal('show');
        },

        submit: function () {
            $scope.groupEdit.busy = true;
            $scope.groupEdit.error = {};

            Client.updateGroup($scope.groupEdit.groupInfo.id, $scope.groupEdit.name, function (error) {
                if (error) {
                    $scope.groupEdit.busy = false;

                    if (error.statusCode === 409) {
                        $scope.groupEdit.error.name = 'Name already taken';
                        $scope.groupEditForm.name.$setPristine();
                        $('#groupEditName').focus();
                        return;
                    } else if (error.statusCode === 400) {
                        $scope.groupEdit.error.name = error.message;
                        $scope.groupEditForm.name.$setPristine();
                        $('#groupEditName').focus();
                        return;
                    } else {
                        return console.error('Unable to edit group.', error.statusCode, error.message);
                    }
                }

                var userIds = $scope.groupEdit.selectedUsers.map(function (u) { return u.id; });

                Client.setGroupMembers($scope.groupEdit.groupInfo.id, userIds, function (error) {
                    if (error) {
                        $scope.groupEdit.busy = false;
                        return console.error('Unable to set group members.', error.statusCode, error.message);
                    }

                    // find apps where ACL has changed
                    var addedApps = $scope.groupEdit.selectedApps.filter(function (a) {
                        return !$scope.groupEdit.selectedAppsOriginal.find(function (b) { return b.id === a.id; });
                    });
                    var removedApps = $scope.groupEdit.selectedAppsOriginal.filter(function (a) {
                        return !$scope.groupEdit.selectedApps.find(function (b) { return b.id === a.id; });
                    });

                    async.eachSeries(addedApps, function (app, callback) {
                        var accessRestriction = app.accessRestriction;
                        if (!accessRestriction) accessRestriction = { users: [], groups: [] };
                        if (!Array.isArray(accessRestriction.groups)) accessRestriction.groups = [];

                        accessRestriction.groups.push($scope.groupEdit.groupInfo.id);

                        Client.configureApp(app.id, 'access_restriction', { accessRestriction: accessRestriction }, callback);
                    }, function (error) {
                        if (error) {
                            $scope.groupEdit.busy = false;
                            return console.error('Unable to set added app access.', error.statusCode, error.message);
                        }

                        async.eachSeries(removedApps, function (app, callback) {
                            var accessRestriction = app.accessRestriction;
                            if (!accessRestriction) accessRestriction = { users: [], groups: [] };
                            if (!Array.isArray(accessRestriction.groups)) accessRestriction.groups = [];

                            var deleted = accessRestriction.groups.splice(accessRestriction.groups.indexOf($scope.groupEdit.groupInfo.id), 1);

                            // if not found return early
                            if (deleted.length === 0) return callback();

                            Client.configureApp(app.id, 'access_restriction', { accessRestriction: accessRestriction }, callback);
                        }, function (error) {
                            $scope.groupEdit.busy = false;
                            if (error) return console.error('Unable to set removed app access.', error.statusCode, error.message);

                            refresh();

                            // refresh apps to reflect change
                            Client.refreshInstalledApps();

                            $('#groupEditModal').modal('hide');
                        });
                    });
                });
            });
        }
    };

    $scope.groupRemove = {
        busy: false,
        error: {},
        group: null,
        memberCount: 0,

        show: function (group) {
            $scope.groupRemove.busy = false;

            $scope.groupRemove.error = {};

            $scope.groupRemove.group = angular.copy(group);

            Client.getGroup(group.id, function (error, result) {
                if (error) return console.error('Unable to fetch group information.', error.statusCode, error.message);

                $scope.groupRemove.memberCount = result.userIds.length;

                $('#groupRemoveModal').modal('show');
            });
        },

        submit: function () {
            $scope.groupRemove.busy = true;
            $scope.groupRemove.error = {};

            Client.removeGroup($scope.groupRemove.group.id, function (error) {
                $scope.groupRemove.busy = false;

                if (error) return console.error('Unable to remove group.', error.statusCode, error.message);

                refresh();
                $('#groupRemoveModal').modal('hide');
            });
        }
    };

    $scope.isMe = function (user) {
        return user.username === Client.getUserInfo().username;
    };

    $scope.invitation = {
        busy: false,
        setupLink: '',
        user: null,

        show: function (user) {
            $scope.invitation.user = user;
            $scope.invitation.setupLink = '';
            $scope.invitation.busy = false;

            Client.createInvite(user.id, function (error, result) {
                if (error) return console.error(error);

                $scope.invitation.setupLink = result.inviteLink;

                $('#invitationModal').modal('show');
            });
        },

        email: function () {
            $scope.invitation.busy = true;

            Client.sendInvite($scope.invitation.user.id, function (error) {
                $scope.invitation.busy = false;
                if (error) return console.error(error);
                $('#invitationModal').modal('hide');
            });
        }
    };

    $scope.directoryConfig = {
        editableUserProfiles: true,
        mandatory2FA: false,
        errorMessage: '',

        loadDirectoryConfig: function () {
            Client.getDirectoryConfig(function (error, result) {
                if (error) return console.error('Unable to get directory config.', error);

                $scope.directoryConfig.editableUserProfiles = !result.lockUserProfiles;
                $scope.directoryConfig.mandatory2FA = !!result.mandatory2FA;
            });
        },

        submit: function () {
            $scope.directoryConfig.error = '';
            $scope.directoryConfig.busy = true;
            $scope.directoryConfig.success = false;

            var data = {
                lockUserProfiles: !$scope.directoryConfig.editableUserProfiles,
                mandatory2FA: $scope.directoryConfig.mandatory2FA
            };

            Client.setDirectoryConfig(data, function (error) {
                if (error) $scope.directoryConfig.errorMessage = error.message;

                $scope.directoryConfig.success = true;

                $scope.directoryConfigForm.$setUntouched();
                $scope.directoryConfigForm.$setPristine();

                $timeout(function () {
                    $scope.directoryConfig.busy = false;
                }, 3000);
            });
        }
    };

    $scope.externalLdap = {
        busy: false,
        percent: 0,
        message: '',
        errorMessage: '',
        error: {},
        taskId: 0,

        syncBusy: false,

        // fields
        provider: 'noop',
        autoCreate: false,
        url: '',
        acceptSelfSignedCerts: false,
        baseDn: '',
        filter: '',
        groupBaseDn: '',
        bindDn: '',
        bindPassword: '',
        usernameField: '',

        currentConfig: {},

        checkStatus: function () {
            Client.getLatestTaskByType('syncExternalLdap', function (error, task) {
                if (error) return console.error(error);

                if (!task) return;

                $scope.externalLdap.taskId = task.id;
                $scope.externalLdap.updateStatus();
            });
        },

        sync: function () {
            $scope.externalLdap.syncBusy = true;

            Client.startExternalLdapSync(function (error, taskId) {
                if (error) {
                    $scope.externalLdap.syncBusy = false;
                    console.error('Unable to start ldap syncer task.', error);
                    return;
                }

                $scope.externalLdap.taskId = taskId;
                $scope.externalLdap.updateStatus();
            });
        },

        updateStatus: function () {
            Client.getTask($scope.externalLdap.taskId, function (error, data) {
                if (error) return window.setTimeout($scope.externalLdap.updateStatus, 5000);

                if (!data.active) {
                    $scope.externalLdap.syncBusy = false;
                    $scope.externalLdap.message = '';
                    $scope.externalLdap.percent = 100; // indicates that 'result' is valid
                    $scope.externalLdap.errorMessage = data.success ? '' : data.error.message;

                    return refreshUsers();
                }

                $scope.externalLdap.syncBusy = true;
                $scope.externalLdap.percent = data.percent;
                $scope.externalLdap.message = data.message;
                window.setTimeout($scope.externalLdap.updateStatus, 3000);
            });
        },

        show: function () {
            $scope.externalLdap.busy = false;
            $scope.externalLdap.error = {};

            $scope.externalLdap.provider = $scope.externalLdap.currentConfig.provider;
            $scope.externalLdap.url = $scope.externalLdap.currentConfig.url;
            $scope.externalLdap.acceptSelfSignedCerts = $scope.externalLdap.currentConfig.acceptSelfSignedCerts;
            $scope.externalLdap.baseDn = $scope.externalLdap.currentConfig.baseDn;
            $scope.externalLdap.filter = $scope.externalLdap.currentConfig.filter;
            $scope.externalLdap.syncGroups = $scope.externalLdap.currentConfig.syncGroups;
            $scope.externalLdap.groupBaseDn = $scope.externalLdap.currentConfig.groupBaseDn;
            $scope.externalLdap.groupFilter = $scope.externalLdap.currentConfig.groupFilter;
            $scope.externalLdap.groupnameField = $scope.externalLdap.currentConfig.groupnameField;
            $scope.externalLdap.bindDn = $scope.externalLdap.currentConfig.bindDn;
            $scope.externalLdap.bindPassword = $scope.externalLdap.currentConfig.bindPassword;
            $scope.externalLdap.usernameField = $scope.externalLdap.currentConfig.usernameField;
            $scope.externalLdap.autoCreate = $scope.externalLdap.currentConfig.autoCreate;

            $('#externalLdapModal').modal('show');
        },

        submit: function () {
            $scope.externalLdap.busy = true;
            $scope.externalLdap.error = {};

            var config = {
                provider: $scope.externalLdap.provider
            };

            if ($scope.externalLdap.provider !== 'noop') {
                config.url = $scope.externalLdap.url;
                config.acceptSelfSignedCerts = $scope.externalLdap.acceptSelfSignedCerts;
                config.baseDn = $scope.externalLdap.baseDn;
                config.filter = $scope.externalLdap.filter;
                config.usernameField = $scope.externalLdap.usernameField;
                config.syncGroups = $scope.externalLdap.syncGroups;
                config.groupBaseDn = $scope.externalLdap.groupBaseDn;
                config.groupFilter = $scope.externalLdap.groupFilter;
                config.groupnameField = $scope.externalLdap.groupnameField;
                config.autoCreate = $scope.externalLdap.autoCreate;

                if ($scope.externalLdap.bindDn) {
                    config.bindDn = $scope.externalLdap.bindDn;
                    config.bindPassword = $scope.externalLdap.bindPassword;
                }
            }

            Client.setExternalLdapConfig(config, function (error) {
                $scope.externalLdap.busy = false;

                if (error) {
                    console.error(error);
                    if (error.statusCode === 424) {
                        if (error.code === 'SELF_SIGNED_CERT_IN_CHAIN') $scope.externalLdap.error.acceptSelfSignedCerts = true;
                        else $scope.externalLdap.error.url = true;
                    } else if (error.statusCode === 400 && error.message === 'invalid baseDn') {
                        $scope.externalLdap.error.baseDn = true;
                    } else if (error.statusCode === 400 && error.message === 'invalid filter') {
                        $scope.externalLdap.error.filter = true;
                    } else if (error.statusCode === 400 && error.message === 'invalid groupBaseDn') {
                        $scope.externalLdap.error.groupBaseDn = true;
                    } else if (error.statusCode === 400 && error.message === 'invalid groupFilter') {
                        $scope.externalLdap.error.groupFilter = true;
                    } else if (error.statusCode === 400 && error.message === 'invalid groupnameField') {
                        $scope.externalLdap.error.groupnameField = true;
                    } else if (error.statusCode === 400 && error.message === 'invalid bind credentials') {
                        $scope.externalLdap.error.credentials = true;
                    }  else if (error.statusCode === 400 && error.message === 'invalid usernameField') {
                        $scope.externalLdap.error.usernameField = true;
                    } else {
                        $scope.externalLdap.error.generic = error.message;
                    }
                } else {
                    $('#externalLdapModal').modal('hide');

                    loadExternalLdapConfig();
                }
            });
        }
    };

    function getUsers(callback) {
        var users = [];

        Client.getUsers($scope.userSearchString, $scope.currentPage, $scope.pageItems.value, function (error, results) {
            if (error) return console.error(error);

            async.eachOfLimit(results, 20, function (result, index, iteratorDone) {
                Client.getUser(result.id, function (error, user) {
                    if (error) return iteratorDone(error);

                    users[index] = user; // keep the sorting order

                    iteratorDone();
                });
            }, function (error) {
                callback(error, users);
            });
        });
    }

    function refreshUsers(showBusy) { // loads users on current page only
        if (showBusy) $scope.userRefreshBusy = true;

        getUsers(function (error, result) {
            if (error) return console.error('Unable to get user listing.', error);

            angular.copy(result, $scope.users);

            $scope.ready = true;
            $scope.userRefreshBusy = false;
        });
    }

    function refresh() {
        Client.getGroups(function (error, result) {
            if (error) return console.error('Unable to get group listing.', error);

            angular.copy(result, $scope.groups);
            $scope.groupsById = { };
            for (var i = 0; i < result.length; i++) {
                $scope.groupsById[result[i].id] = result[i];
            }

            refreshUsers(true);
        });
    }

    function loadExternalLdapConfig() {
        Client.getExternalLdapConfig(function (error, result) {
            if (error) return console.error('Unable to get external ldap config.', error);

            $scope.externalLdap.currentConfig = result;
            $scope.externalLdap.checkStatus();
        });
    }

    $scope.showNextPage = function () {
        $scope.currentPage++;
        refreshUsers();
    };

    $scope.showPrevPage = function () {
        if ($scope.currentPage > 1) $scope.currentPage--;
        else $scope.currentPage = 1;
        refreshUsers();
    };

    $scope.updateFilter = function (fresh) {
        if (fresh) $scope.currentPage = 1;
        refreshUsers();
    };

    function refreshAllUsers() { // this loads all users on Cloudron, not just current page
        Client.getUsers(function (error, results) {
            if (error) return console.error(error);

            $scope.allUsers = results;

            $scope.allUsersById = {};
            for (var i = 0; i < results.length; i++) {
                $scope.allUsersById[results[i].id] = results[i];
            }
        });
    }

    Client.onReady(refresh);
    Client.onReady(function () { if ($scope.user.isAtLeastAdmin) loadExternalLdapConfig(); });
    Client.onReady(function () { if ($scope.user.isAtLeastAdmin) $scope.directoryConfig.loadDirectoryConfig(); });
    Client.onReady(refreshAllUsers);
    Client.onReady(function () {
        // Order matters for permissions used in canEdit
        $scope.roles = [
            { id: 'user', name: $translate.instant('users.role.user'), disabled: false },
            { id: 'usermanager', name: $translate.instant('users.role.usermanager'), disabled: false },
            { id: 'admin', name: $translate.instant('users.role.admin'), disabled: !$scope.user.isAtLeastAdmin },
            { id: 'owner', name: $translate.instant('users.role.owner'), disabled: !$scope.user.isAtLeastOwner }
        ];
    });

    // setup all the dialog focus handling
    ['userAddModal', 'userRemoveModal', 'userEditModal', 'groupAddModal', 'groupEditModal', 'groupRemoveModal'].forEach(function (id) {
        $('#' + id).on('shown.bs.modal', function () {
            $(this).find("[autofocus]:first").focus();
        });
    });

    var clipboard = new Clipboard('#setupLinkButton');

    clipboard.on('success', function(e) {
        $('#setupLinkButton').tooltip({
            title: 'Copied!',
            trigger: 'manual'
        }).tooltip('show');

        $timeout(function () {  $('#setupLinkButton').tooltip('hide'); }, 2000);

        e.clearSelection();
    });

    clipboard.on('error', function(/*e*/) {
        $('#setupLinkButton').tooltip({
            title: 'Press Ctrl+C to copy',
            trigger: 'manual'
        }).tooltip('show');

        $timeout(function () {  $('#setupLinkButton').tooltip('hide'); }, 2000);
    });

    $('.modal-backdrop').remove();
}]);
