// (C) Copyright 2020 Hewlett-Packard Enterprise Company, L.P.
define(['fs/model/users/UserResource',
        'hp/core/EventDispatcher',
        'fs/services/users/UserService',
        'hp/services/authn',
        'hp/core/LinkTargetBuilder',
        'hp/model/Session',
        'hp/core/Localizer'],
function(resource, EventDispatcher, userService, authnService, linkTargetBuilder, session, Localizer) { "use strict";

    var UsersPresenter = (function() {

        /**
         * @constructor
         */
        function UsersPresenter() {
            var dispatcher = new EventDispatcher();

            /**
             * @public
             * @param {String} username
             * @param {String} fullname
             * @param {String} initial_passwd
             * @param {String} confirm_passwd
             * @param {String} email
             * @param {String} office_phone
             * @param {String} mobile_phone
             * @param {Object} handlers
             */
            this.addUser = function(username, fullname, initial_passwd,
                    confirm_passwd, email, office_phone, mobile_phone,
                    handlers) {
                var functionSuccess = function(data) {
                    resource.getIndexResults();
                    dispatcher.fire("userAddedSuccess", data);
                };
                var functionError = function(errorInfo) {
                    dispatcher.fire("userAddedError", errorInfo);

                };
                var user = {
                        userName : jQuery.trim(username),
                        fullName : jQuery.trim(fullname),
                        password : initial_passwd,
                        emailAddress : jQuery.trim(email),
                        officePhone : jQuery.trim(office_phone),
                        mobilePhone : jQuery.trim(mobile_phone),
                        enabled : true
                };
                userService.postUser(user, {
                    success : functionSuccess,
                    error : functionError
                });
            };

            /**
             * @public
             * @param {String} username
             * @param {Array (String)} userroles
             * @param {Object} handlers
             */
            this.assignUserToRoles = function(username, userroles, handlers) {
                var functionSuccess = function(data) {
                    resource.getIndexResults();
                    dispatcher.fire("assignUserToRolesSuccess", data);
                };
                var functionError = function(errorInfo) {
                    dispatcher.fire("assignUserToRolesError", errorInfo);
                };
                var role = {
                        userName : jQuery.trim(username),
                        roles : userroles
                };
                userService.rolesUser(role, {
                    success : functionSuccess,
                    error : functionError
                });
            };

            /**
             * @public
             * @param {String} username
             * @param {String} fullname
             * @param {String} currentPassword - only required
             * for self password update
             * @param {String} new_passwd
             * @param {String} user_roles
             * @param {String} email
             * @param {String} office_phone
             * @param {String} mobile_phone
             * @param {String} replace
             */

            this.modifyUser = function(username, fullname, current_passwd, new_passwd,
                    user_roles, email, office_phone, mobile_phone, replace, caller) {
                //to be passed into modify user
                var user = {
                        userName : $.trim(username),
                        fullName : $.trim(fullname),
                        currentPassword : current_passwd?
                            $.trim(current_passwd) : null,
                        password : (new_passwd == "********")?
                            null : $.trim(new_passwd),//dummy
                        emailAddress : $.trim(email),
                        officePhone : $.trim(office_phone),
                        mobilePhone : $.trim(mobile_phone),
                        roles : user_roles,
                        enabled : true,
                        replaceRoles : replace
                };

                resource.modifyUser(user, {
                    success : function(user){
                        resource.getIndexResults();
                        var currentUser = session.getUser();
                        currentUser = (currentUser !== null && currentUser !== undefined)? currentUser.toLowerCase(): null;
                        var returnedUser = (user.userName !== null && user.userName !== undefined)? user.userName.toLowerCase(): null;
                        if(returnedUser === currentUser){
                            dispatcher.fire("userSelfModifiedSuccess", user);
                        }else{
                            dispatcher.fire("userModifiedSuccess", user);
                        }
                    },
                    error : function(errorInfo){
                        dispatcher.fire("userModifiedError", errorInfo);
                    }}
                );
            };

            /**
             * @public
             * @return True or false -true for replace roles
             * and False for additive behaviour. default-Add to existing.
             * @param {Object} newRoles
             */
            this.isReplace = function(newRoles){
                var oldRoles = resource.getRetrievedRoles();
                //put new roles into a set
                var roleSet = {};
                var replace = false;
                var rolesnew = (newRoles.hasOwnProperty('members') ?
                    newRoles.members : newRoles);
                for ( var i = 0; i < rolesnew.length; i++) {
                    if (!roleSet[rolesnew[i]]){
                        roleSet[rolesnew[i]] = true;
                  }
                }
                //now check if old roles are present in this set
                //- break if any are not present
                var rolesold = (oldRoles.hasOwnProperty('members') ?
                    oldRoles.members : oldRoles);
                for ( var j = 0; j < rolesold.length; j++) {
                    if (!roleSet[rolesold[j].roleName]){
                        replace = true;
                        break;
                    }
                }
                return replace;
            };

            /**
             * @public
             */
            this.updateIndexResults = function() {
                resource.getIndexResults();
            };

            /**
             * @public
             * @return the array of roles defined on the appliance
             */
            this.getRoles = function() {
                return resource.getRoles();
            };
            
            /**
             * @public
             * Get the list of directory groups defined on the appliance
             * @param {String} uname username of the user
             * @param {String} password of the user
             * @param {String} authDomain directory server chosen by the user
             * @param {Object} handlers with error and success.
             */
            this.getGroupList = function(uname, password, authDomain, handlers) {
            	userService.getGroupList(uname, password, authDomain, handlers);
            };
            
            /**
             * @public
             * @return Get display versions of some of the user data.
             * @param {Object} user
             */
            this.getDisplayFields = function(user) {
                var displayFields = {};
                if (user) {
                    displayFields.userName = user.userName;
                    displayFields.fullName = user.fullName;
                }
                return displayFields;
            };

            /**
             * @public
             * @return Get display versions of some of the user data in
             *         from index.
             * @param {Object} indexResult
             */
            this.getDisplayFieldsFromIndex = function(indexResult) {
                var displayFields = {};
                if (indexResult) {
                    displayFields.name = indexResult.name;
                }
                return displayFields;
            };

            /**
             * @public
             */
            this.getSelection = function() {
                return resource.getSelection();
            };

            /**
             * @public
             */
            this.getSelectedUser = function() {
                return resource.getRetrievedUser();
            };

            /**
             * @public
             */
            this.setSelectedUris = function(uris) {
                resource.setSelectedUris(uris);
            };

            this.haveUsers = function() {
                return resource.haveSome();
            };

            this.getAddLink = function () {
                var result = null;
                if (session.canPerformAction('users', 'Create')) {
                    result = linkTargetBuilder.makeLink(
                        Localizer.getString('fs.users.add.add_user'), null, 'add', 'users', 'Create');
                }
                return result;
            };
            
            function onRolesChanged(roles) {
                dispatcher.fire("rolesChanged", roles);
            }
            
            function onUserRoleChanged(roleList) {
                dispatcher.fire("userRoleChanged", roleList);
            }
            
            function onUserRolesError(errorInfo) {
                dispatcher.fire("userRolesError", errorInfo);
            }
            
            function onUserChangedSuccess(user) {
                dispatcher.fire("userChangedSuccess", user);
            }
            
            function onUserChangedError(errorInfo) {
                dispatcher.fire("userChangedError", errorInfo);
            }
            
            function onUserDeleteSuccess(userName) {
                resource.clearAllSelectedUris(true);
                dispatcher.fire("userDeleteSuccess", userName);
            }
            
            function onUserDeleteError(errorInfo) {
                dispatcher.fire("userDeleteError", errorInfo);
            }
            function onGroupDeleteSuccess(groupName) {
                resource.clearAllSelectedUris(true);
                dispatcher.fire("groupDeleteSuccess", groupName);
            }
            
            function onGroupDeleteError(errorInfo) {
                dispatcher.fire("groupDeleteError", errorInfo);
            }
            function onGroupChangedSuccess(groupInfo) {
                dispatcher.fire("groupChangedSuccess", groupInfo);
            }
            function onGroupChangedError(errorInfo) {
                dispatcher.fire("groupChangedError", errorInfo);
            }

            function onGetProductConfigSuccess(productConfigs){
              var configs = {};
              if(productConfigs.members!=null){
               for(var i=0;i < productConfigs.members.length;i++){
                     if (productConfigs.members[i].name.match(/^userconfig.*$/)){
                       configs[productConfigs.members[i].name] = productConfigs.members[i].value;
                     }
                   }
              }
              dispatcher.fire("getProductConfigSuccess", configs);
            }
            function onGetProductConfigError(errorInfo){
              dispatcher.fire("getProductConfigError", errorInfo);
            }

            /**
             * @public
             */
            this.init = function() {
                resource.on("rolesChanged", onRolesChanged);
                resource.on("userRoleChanged", onUserRoleChanged);
                resource.on("userRolesError", onUserRolesError);
                resource.on("userChangedSuccess", onUserChangedSuccess);
                resource.on("userChangedError", onUserChangedError);
                resource.on("userDeleteSuccess", onUserDeleteSuccess);
                resource.on("userDeleteError", onUserDeleteError);
                resource.on("groupDeleteSuccess", onGroupDeleteSuccess);
                resource.on("groupDeleteError", onGroupDeleteError);
                resource.on("groupChangedSuccess", onGroupChangedSuccess);
                resource.on("groupChangedError", onGroupChangedError);
            };

            /**
             * Add a listener for a specified event.
             *
             * @public
             * @param {string} eventName The name of the event.
             * @param {function(...)} callback
             */
            this.on = function(eventName, callback) {
                dispatcher.on(eventName, callback);
                // fire initial state
                switch (eventName) {
                    case 'rolesChanged':
                      dispatcher.fire('rolesChanged', resource.getRoles());
                }
            };

            /**
             * Remove a listener for the specified event.
             *
             * @public
             * @param {string} eventName The name of the event.
             * @param {function(...)} callback
             */
            this.off = function(eventName, callback) {
                dispatcher.off(eventName, callback);
            };

            /**
             * @private
             */
            function onGetGlobalSettingsSuccess(globalSettingsDto){
                dispatcher.fire("onCompleteGlobalSettings",globalSettingsDto.configuredLoginDomains);
            }

            /**
             * @private
             */
            function onGetGlobalSettingsFailure(error){
                dispatcher.fire("getGlobalSettingsError",error.errorInfo);
            }

            /**
             * Get Authentication Settings
             *
             * @public
             */
            this.getAuthnServices = function(){
                authnService.getGlobalSettings({
                    success: onGetGlobalSettingsSuccess,
                    error: onGetGlobalSettingsFailure
                });
            };

            /**
             * Get persisted roles of logged in user without making rest call again
             *
             * @public
             */
            this.getRetrievedRolesSelf = function(){
                return resource.getRetrievedRolesSelf();
            };

            /**
             * Get persisted details of logged in user without making rest call again
             *
             * @public
             */
            this.getRetrievedUserSelf = function(){
                return resource.getRetrievedUserSelf() ;
            };

            /**
             * Get details of any user
             *
             * @public
             * @param {string} userName
             * @param handlers
             */
            this.getUser = function(userName, handlers) {
                resource.getUser(userName, {
                    success: function(data){
                        var currentUser = session.getUser();
                        currentUser = (currentUser !== null && currentUser !== undefined)? currentUser.toLowerCase(): null;
                        var returnedUser = (data.userName !== null && data.userName !== undefined)? data.userName.toLowerCase(): null;
                        if(returnedUser === currentUser){
                            dispatcher.fire("userSelfChangedSuccess", data);
                        }else{
                            dispatcher.fire("userChangedSuccess", data);
                        }
                    },
                    error: function(errorInfo){
                        dispatcher.fire("userChangedError", errorInfo);
                    }}
                );
            };


            /**
             * Get roles of any user
             *
             * @public
             * @param {string} userName
             * @param handlers
             */
            this.getAllUserRoles = function(userName) {
                resource.getAllUserRoles(userName, {
                    success: function(data){
                        var currentUser = session.getUser();
                        currentUser = (currentUser != null && currentUser !== undefined)? currentUser.toLowerCase(): null;
                        userName = (userName !== null && userName !== undefined)? userName.toLowerCase(): null;
                        if(userName === currentUser){
                            dispatcher.fire("userSelfRoleChanged", data);
                        }else{
                            dispatcher.fire("userRoleChanged", data);
                        }
                    },
                    error: function(errorInfo){
                        dispatcher.fire("userRolesError", errorInfo);
                    }}
                );
            };

            /**
             * Clear resource variables
             *
             * @public
             */
            this.clear=function(){
                resource.off("rolesChanged", onRolesChanged);
                resource.off("userRoleChanged", onUserRoleChanged);
                resource.off("userRolesError", onUserRolesError);
                resource.off("userChangedSuccess", onUserChangedSuccess);
                resource.off("userChangedError", onUserChangedError);
                resource.off("userDeleteSuccess", onUserDeleteSuccess);
                resource.off("userDeleteError", onUserDeleteError);
                resource.off("groupDeleteSuccess", onGroupDeleteSuccess);
                resource.off("groupDeleteError", onGroupDeleteError);
                resource.off("groupChangedSuccess", onGroupChangedSuccess);
                resource.off("groupChangedError", onGroupChangedError);
                resource.clear();
            };

            /**
             * trigger call to get list of users logged in
             *
             * @public
             * @param {string} userName
             * @param handlers
             */
            this.usersLoggedIn = function() {
                resource.usersLoggedIn();
            };

            this.getOtherUsersLoggedInList = function() {
                return resource.getOtherUsersLoggedInList();
            };

            this.setOtherUsersLoggedInList = function(otherUsersLoggedInList) {
                resource.setOtherUsersLoggedInList(otherUsersLoggedInList);
            };


            /**
             * Get persisted roles of any user without making rest call again
             * when a user is selected on main page - show page,
             * his details(roles and user details) are got by calling REST API.
             * The same data is needed in Edit user page, so we save
             * the data in the resource to be used when Edit link is clicked.
             *
             * @public
             */
            this.getRetrievedRoles = function() {
                return resource.getRetrievedRoles();
            };

            /**
             * Get persisted details of any user without making rest call again
             *
             * @public
             */
            this.getRetrievedUser = function() {
                return resource.getRetrievedUser();
            };

            /**
             * @public
             * @param {String} username of the user
             * @param {handler} handlers
             */
             this.deleteUser = function(userName) {
                 resource.deleteUser(userName);
             };
             
             /**
              * @public
              * @param {String} uri of the directory group
              */
              this.deleteDirectoryGroup = function(uri) {
                  resource.deleteDirectoryGroup(uri);
              };

             /**
              * @public
              * @param {String} username of the user
              * @param {handler} handlers
              */
              this.selectionChange = function() {
                  resource.selectionChange(resource.getSelection());
              };

             /**
              * @public used to check if login name entered exists already
              * @param {String} username of the user
              * @param {handler} handlers
              */
             this.checkLoginNameExists = function(userName, handlers) {
                  var checkLoginNameExistsSuccess = function(doesExist) {
                      handlers.success.call(this, doesExist);
                  };
                  var checkLoginNameExistsError = function(errorInfo) {
                      handlers.error.call(this, errorInfo);
                  };

                  userService.checkLoginNameExists(userName, {
                      success : checkLoginNameExistsSuccess,
                      error : checkLoginNameExistsError
                  });
             };

            /**
             * @public - Gets list of Active Directories configured in the appliance
             * @param {handler} handlers
            */

            this.isActiveDirectoryConfigured = function (){
                var isActiveDirectoryAvailable = false;
                var activeDirectoryListSuccess = function(data) {
                    if (data.configuredLoginDomains.length > 0) {
                        isActiveDirectoryAvailable = true;
                    }
                    dispatcher.fire("activeDirectoryConfiguredSuccess", isActiveDirectoryAvailable);
                };
                var activeDirectoryListFailure = function(error) {
                    dispatcher.fire("activeDirectoryConfiguredFailure", error);
                };
                userService.activeDirectoryList({
                    success : activeDirectoryListSuccess,
                    error : activeDirectoryListFailure
                });
            };
            /**
             * @public - Returns a boolean, if Active Directories are configured in the appliance
             * @param {handler} handlers
             * @returns boolean
            */

            this.checkIfActiveDirectoryConfigured = function (handlers) {
                var activeDirectoryListSuccess = function(data) {
                    handlers.success(data.configuredLoginDomains.length > 0);
                };
                userService.activeDirectoryList({
                    success : activeDirectoryListSuccess,
                    error : handlers.error
                });
            };
            /**
             * update  Group to Role Mappings
             *
             * @param {Object}
             *             group2rolemappingsConfig
             * @param {{success:function():void,
             *            error:function(string):void}} handlers
             *            Function to call on success or error; the
             *            parameter to the error handler is an error
             *            message.
             */
           this.updateGroupToRoleMappings = function(group2rolemappingsConfig, handlers) {
                userService.updateGroupToRoleMappings(group2rolemappingsConfig, handlers );
           };

           /**
            * To retrieve values in /ci/etc/product-config.json
            *
            */
           this.getProductConfig = function(){
               resource.getProductConfig({
                   success: onGetProductConfigSuccess,
                   error: onGetProductConfigError
               });
            };

        }

        return new UsersPresenter();
    }());

    return UsersPresenter;
});
