// (C) Copyright 2020 Hewlett-Packard Enterprise Company, L.P.
/**
 * @type {UserSettingsEditView}
 */
define(['hp/core/Localizer',
        'fs/presenter/users/UsersPresenter',
        'fs/view/users/UsersViewUtil',
        'hp/model/Session',
        'hp/core/Notifications',
        'text!fsPages/users/user_settings_edit.html',
        'hp/view/DialogView',
        'hp/view/FormStateView',
        'hp/core/HelpMenu',
        'jquery',
        'hp/lib/jquery.hpEllipsis'],
function(localizer, presenter, UsersViewUtil, session, Notifications, userSelfEdit, DialogView, FormStateView, helpMenu) {"use strict";

    var UserSettingsEditView = (function() {

        var FORM = '#fs-user-settingsedit-form',
            CANCEL = "#fs-usersettings-edit-cancel",
            ERROR = '#fs-usersettings-edit-error',
            NAME = '#fs-usersettings-loginname',
            FULLNAME = '#fs-usersettings-fullname',
            CURRENT_PASSWD = '#fs-usersettings-currentpasswd',
            NEW_PASSWD = '#fs-usersettings-newpasswd',
            NEW_PASSWD_HELP = '#fs-usersettings-newpasswd-help',
            CONFIRM_PASSWD = '#fs-usersettings-confirmpasswd',
            EMAIL = '#fs-usersettings-email',
            OFFICE_PHONE = '#fs-usersettings-officephone',
            MOBILE_PHONE = '#fs-usersettings-mobilephone',
            ROLES_LIST = '#fs-usersettings-roles-list',
            HEADER = '#fs-usersettings-edit-header',
            FULLNAME_OPTIONAL = '#fs-usersettings-fullname-optional',
            EMAIL_OPTIONAL = '#fs-usersettings-email-optional',
            OFFICEPHONE_OPTIONAL = '#fs-usersettings-officephone-optional',
            MOBILEPHONE_OPTIONAL = '#fs-usersettings-mobilephone-optional';

        /**
         * Constructor
         * Show a dialog
         * @param {args} Object with properties as follows:
         *
         *    contents: contents of dialog
         *    ok: the function called when the user clicks ok.
         *    cancel: the function called when the user clicks cancel.
         */
        function UserSettingsEditView() {

            var initialized = false;
            var validator;
            // prevent double click
            var isSubmitted;
            var firstRoleTemplate = null, roleTemplate = null;
            var dialog;
            var formStateView;
            var userSelfEditHtml = $(userSelfEdit);
            var taskName;
            var numberOfClicks = 0;
            var COUNT = '#hp-form-changes-control .hp-count';
            var changeCount = 0;


            /**
             * @private
             */
            function reset() {
                $(NEW_PASSWD).val("");
                $(FULLNAME).val("");
                $(CURRENT_PASSWD).val("");
                $(CONFIRM_PASSWD).val("");
                $(EMAIL).val("");
                $(OFFICE_PHONE).val("");
                $(MOBILE_PHONE).val("");
                validator.resetForm();
                formStateView.reset();
                numberOfClicks = 0;
                isSubmitted = false;
                changeCount = 0;
            }

            function onUserModifiedSuccess(user) {
                var alertMsg = localizer.getString('fs.users.edit.success', [ user.userName ]);
                reset();
                var notif = {
                    summary : localizer.getString('fs.users.edit.update'),
                    sourceName : user.userName,
                    sourceUri : "rest/users/"+user.userName,
                    uri : taskName,
                    changing : false,
                    status : "ok",
                    details : alertMsg
                };
                //If we are on the users show page, and we are looking at details of
                //the user we are editing - when the dialog is closed, the details must
                //refresh. Happens only for administrator.
                if (window.location.hash.indexOf('#/user') != -1 &&
                    presenter.getSelectedUser().userName.toLowerCase() === session.getUser().toLowerCase()){
                    //window.location = '#/user/show';
                    presenter.getUser(user.userName);
                }
                //removeEvents();
                Notifications.add(notif, true);
                $(CANCEL).trigger('click');
            }

            /**
             * @private
             */
            function onUserModifiedError(errorMessage) {
              var modifyMsg = localizer.getString('fs.users.edit.error',[$(NAME).val()]);
              var errorMsg = localizer.formatRestError(modifyMsg,
                      errorMessage);
                formStateView.setMessage({summary: modifyMsg, status: 'error',
                    errorMessage: errorMessage});
                var notif = {
                    summary : localizer.getString('fs.users.edit.update'),
                    sourceName : $(NAME).val(),
                    sourceUri : "rest/users/"+$(NAME).val(),
                    uri : taskName,
                    changing : false,
                    status : "error",
                    details : errorMsg
                };
                Notifications.add(notif, true);
                isSubmitted = false;
            }

            /**
             * @private
             */
            function onEditUserClick() {
                if ($(FORM).valid() && isSubmitted == false) {
                  numberOfClicks = numberOfClicks + 1;
                    isSubmitted = true;
                    var alertMsg = localizer.getString('fs.users.edit.editMsg', [ $(NAME).val() ]);
                    formStateView.setMessage({summary:alertMsg, status:'info', changing : true});
                    if(numberOfClicks == 1){
                        taskName = $(NAME).val() + '-editUserTask-' + (new Date()).getTime();
                    }
                    var userEditProgress = {
                        summary : localizer.getString('fs.users.edit.update'),
                        sourceName : $(NAME).val(),
                        sourceUri : "rest/users/"+$(NAME).val(),
                        uri : taskName,
                        changing : true,
                        status : "info",
                        details : alertMsg
                    };
                    Notifications.add(userEditProgress, false);
                    var roles = [];
                    presenter.modifyUser($(NAME).val(), $(FULLNAME).val(),
                            $(CURRENT_PASSWD).val(), $(NEW_PASSWD).val(), roles,
                            $(EMAIL).val(), $(OFFICE_PHONE).val(),
                            $(MOBILE_PHONE).val(), false, "self");
                }
                return false;
            }

            function userChanged(user) {
                reset();
                $(ERROR).hide();
                $(NAME).val(user.userName);
                $(FULLNAME).val(user.fullName);
                $(EMAIL).val(user.emailAddress);
                $(OFFICE_PHONE).val(user.officePhone);
                $(MOBILE_PHONE).val(user.mobilePhone);
            }


            /**
             * @private
             */
            function userRolesError(errorMessage) {
                var roleMsg = localizer.getString('fs.users.show.roleserror');
                formStateView.setMessage({summary: roleMsg, status: 'error',
                    errorMessage: errorMessage});
            }

            /**
             * @private
             */
             function updateRoles(retrievedRoles) {

                 var retrievedRolesList = (retrievedRoles.hasOwnProperty('members') ?
                         retrievedRoles.members : retrievedRoles);
                 var rolesList = $(ROLES_LIST);
                 $(rolesList).empty();
                 $.each(retrievedRolesList, function(index, role) {
                     var roleValue = role.roleName ? role.roleName : 'noname';
                     var roleDisplay = UsersViewUtil.getLocalizedRoleDisplay(roleValue);
                     var label = $('<label/>');
                     label.html(roleDisplay);
                     $(ROLES_LIST).append(label);
                     if (index !== retrievedRolesList.length - 1){
                         $(ROLES_LIST).append($('<br/>'));
                     }
                 });


             }

             /**
             * @private
             */
             function myUserChangedSuccess(user) {
               userChanged(user);
             }

             /**
             * @private
             */
             function myUserChangedError(errorMessage) {
                var userMsg = localizer.getString('fs.users.show.error');
                formStateView.setMessage({summary: userMsg, status: 'error',
                    errorMessage: errorMessage});
             }


             function getProductConfigSuccess(productConfigs){
                 UsersViewUtil.setProductConfigs(productConfigs);
                 UsersViewUtil.checkRequired(FULLNAME_OPTIONAL,EMAIL_OPTIONAL,MOBILEPHONE_OPTIONAL,OFFICEPHONE_OPTIONAL);
                 var passwordArgs = [];
                 passwordArgs[0] = function(){return UsersViewUtil.getPropertyValue(
                         UsersViewUtil.configs[UsersViewUtil.PASSWORD_MINLENGTH],
                         UsersViewUtil.MIN_PASSWORD_LENGTH);};
                 $(NEW_PASSWD_HELP).text(localizer.getString(
                     "fs.users.validations.passwordHintDynamic", passwordArgs));
             }

             function getProductConfigError(errorInfo){
                 UsersViewUtil.setProductConfigs({});
             }

             function onEditUserCancelClick(){
                 isSubmitted = true;
                 formStateView.reset();
                 removeEvents();
             }


            function initForm() {
                isSubmitted = false;

                validator = $(FORM, userSelfEditHtml).validate({
                    rules : {
                       fullname : {
                           required :  function(){return UsersViewUtil.getPropertyValue(
                                    UsersViewUtil.configs[UsersViewUtil.FULLNAME_REQUIRED],false);} ,
                           cicUserSettingsFullNameCheck : FULLNAME,
                           minlength :  function(){return UsersViewUtil.getPropertyValue(
                                    UsersViewUtil.configs[UsersViewUtil.FULLNAME_MINLENGTH], UsersViewUtil.MIN_NAME_LENGTH);},
                           maxlength : function(){return UsersViewUtil.getPropertyValue(
                                    UsersViewUtil.configs[UsersViewUtil.FULLNAME_MAXLENGTH],UsersViewUtil.MAX_NAME_LENGTH);}
                         },
                        email : {
                            required :  function(){return UsersViewUtil.getPropertyValue(
                                    UsersViewUtil.configs[UsersViewUtil.EMAIL_REQUIRED],false);} ,
                            email : EMAIL,
                            maxlength :  function(){return UsersViewUtil.getPropertyValue(
                                    UsersViewUtil.configs[UsersViewUtil.EMAIL_MAXLENGTH],UsersViewUtil.MAX_EMAIL_LENGTH);}
                        },
                        currentpasswd : {
                            cicUserSettingsEditCheckPasswdString : CURRENT_PASSWD,
                            cicUserSettingsEditCheckCurrPass : CURRENT_PASSWD,
                            maxlength :  function(){return UsersViewUtil.getPropertyValue(
                                    UsersViewUtil.configs[UsersViewUtil.PASSWORD_MAXLENGTH],UsersViewUtil.MAX_PASSWORD_LENGTH);}
                        },
                        newpasswd : {
                            cicUserSettingsEditCheckPasswdString : NEW_PASSWD,
                            cicUserSettingsEditCheckPwdLength : function(){return UsersViewUtil.getPropertyValue(
                                    UsersViewUtil.configs[UsersViewUtil.PASSWORD_MINLENGTH],UsersViewUtil.MIN_PASSWORD_LENGTH);},
                            cicUserSettingsEditCheckReqd : NEW_PASSWD,
                            maxlength :  function(){return UsersViewUtil.getPropertyValue(
                                    UsersViewUtil.configs[UsersViewUtil.PASSWORD_MAXLENGTH],UsersViewUtil.MAX_PASSWORD_LENGTH);}
                        },
                        confirmpasswd : {
                            cicUserSettingsEditMatchPasswd : NEW_PASSWD
                        },
                        officephone : {
                            required :  function(){return UsersViewUtil.getPropertyValue(
                                    UsersViewUtil.configs[UsersViewUtil.OFFICE_REQUIRED],false);} ,
                            cicUserSettingsEditOfficePhoneNumCheck : OFFICE_PHONE,
                            maxlength :  function(){return UsersViewUtil.getPropertyValue(
                                    UsersViewUtil.configs[UsersViewUtil.OFFICE_MAXLENGTH],UsersViewUtil.MAX_NUMBER_LENGTH);} ,
                            minlength :  function(){return UsersViewUtil.getPropertyValue(
                                    UsersViewUtil.configs[UsersViewUtil.OFFICE_MINLENGTH],UsersViewUtil.MIN_NUMBER_LENGTH);}
                        },
                        mobilephone : {
                            required :  function(){return UsersViewUtil.getPropertyValue(
                                    UsersViewUtil.configs[UsersViewUtil.MOBILE_REQUIRED],false);} ,
                            cicUserSettingsEditMobilePhoneNumCheck : MOBILE_PHONE,
                            maxlength :  function(){return UsersViewUtil.getPropertyValue(
                                    UsersViewUtil.configs[UsersViewUtil.MOBILE_MAXLENGTH],UsersViewUtil.MAX_NUMBER_LENGTH);} ,
                            minlength :  function(){return UsersViewUtil.getPropertyValue(
                                    UsersViewUtil.configs[UsersViewUtil.MOBILE_MINLENGTH],UsersViewUtil.MIN_NUMBER_LENGTH);}
                        }
                    }
                });
            }

            function registerEvents() {
                presenter.on("userSelfChangedSuccess", myUserChangedSuccess);
                presenter.on("userChangedError", myUserChangedError);
                presenter.on("userSelfRoleChanged", updateRoles);
                presenter.on("userRolesError", userRolesError);
                presenter.on("userSelfModifiedSuccess", onUserModifiedSuccess);
                presenter.on("userModifiedError", onUserModifiedError);
                presenter.on("getProductConfigSuccess", getProductConfigSuccess);
                presenter.on("getProductConfigError", getProductConfigError);
            }

            function removeEvents() {
                presenter.off("userSelfChangedSuccess", myUserChangedSuccess);
                presenter.off("userChangedError", myUserChangedError);
                presenter.off("userSelfRoleChanged", updateRoles);
                presenter.off("userRolesError", userRolesError);
                presenter.off("userSelfModifiedSuccess", onUserModifiedSuccess);
                presenter.off("userModifiedError", onUserModifiedError);
                presenter.off("getProductConfigSuccess", getProductConfigSuccess);
                presenter.off("getProductConfigError", getProductConfigError);
            }

            function initUserEdit(){
                var currentUser = session.getUser();
                firstRoleTemplate = $('#fs-usersettings-first-role-template').detach();
                roleTemplate = $('#fs-usersettings-role-template').detach();
                initForm();
                $(HEADER).html(localizer.getString('fs.users.edit.link')+' '+currentUser);
                $(NAME).text(currentUser);
                presenter.getUser(currentUser);
                presenter.getAllUserRoles(currentUser);
                presenter.getProductConfig();
            }

            function init() {
               //because usually only first time init is called and other times load is called.
               //But in this case, the dialog is always brought up using initialize().
                if (!initialized) {
                    initialized = true;
                    formStateView = new FormStateView();
                    var args=[];
                    args[0] = UsersViewUtil.MIN_PASSWORD_LENGTH;
                    formStateView.init({form: $(FORM, userSelfEditHtml), autoTrack: true});
                    //customized help link implemented for this particular div, as default help page is improper
                    var productBook = helpMenu.getProductBook(); 
                    $('#user-settings-edit-dialog .hp-help-current').attr('href','/doc#/' + (productBook ? productBook : '') + '/user/edit/');
                    var validMatchPasswd = localizer.getString('fs.users.edit.matchpasswd');
                    var validCurrentPasswd = localizer.getString('fs.users.validations.matchcurrpasswd');
                    //var validPasswdLength = localizer.getString('fs.users.validations.checkLengthDynamic');
                    var validPhoneNum = localizer.getString('fs.users.validations.phonenumValidation');
                    var validPassword = localizer.getString('fs.users.validations.passwordValidation');
                    var validFullname = localizer.getString('fs.users.validations.fullnameValidation');
                    var fieldRequired = localizer.getString('fs.users.validations.fieldRequired');

                    // check for fullname contain letters ' . - and space
                    $.validator.addMethod("cicUserSettingsFullNameCheck",
                        function(value, element, param) {
                            var regex =  UsersViewUtil.getPropertyValue(UsersViewUtil.configs[UsersViewUtil.FULLNAME_VALID],
                                "^[a-zA-Z0-9 ._'\-]+$");
                            var isValidFullname = new RegExp(regex).test(value);
                            return (isValidFullname || value.length == 0);
                        },
                        function (){ return UsersViewUtil.getPropertyValue(
                                UsersViewUtil.configs[UsersViewUtil.FULLNAME_ERRORMSG], validFullname);
                        }
                    );

                    $.validator.addMethod("cicUserSettingsEditCheckCurrPass",
                        function(value, element, param) {
                            var result = true;
                            if (value.length == 0 &&
                                ((($(NEW_PASSWD).val() && $(NEW_PASSWD).val().length > 0)) ||
                                    ($(CONFIRM_PASSWD).val() && ($(CONFIRM_PASSWD).val().length >0)))){
                                result = false;
                            }
                            return result;
                        },
                        validCurrentPasswd);

                    $.validator.addMethod("cicUserSettingsEditCheckReqd",
                        function(value, element, param) {
                            var result = true;
                            if (value.length == 0 &&
                                ((($(CURRENT_PASSWD).val() && $(CURRENT_PASSWD).val().length > 0)) &&
                                    ($(CONFIRM_PASSWD).val() && ($(CONFIRM_PASSWD).val().length >0)))){
                                result = false;
                            }
                            return result;
                        },
                        fieldRequired);

                    $.validator.addMethod("cicUserSettingsEditMatchPasswd",
                        function(value, element, param) {
                            // bind to the blur event of the target in order to revalidate whenever the target field is updated
                            var target = $(param).unbind(".validate-equalTo")
                                .bind("blur.validate-equalTo", function() {
                                    $(element).valid();
                                });
                            return (($(NEW_PASSWD).val() && ($(NEW_PASSWD).val().length == 0))
                                || (value == target.val()));
                        },
                        validMatchPasswd);

                    //function to check length of password. Since it is optional field,
                    //user can leave the dummy value there and modify other details.
                    //If he removes the dummy characters somehow, it will still not prompt for pwd
                    $.validator.addMethod("cicUserSettingsEditCheckPwdLength",
                        function(value, element, param) {
                            args[0] = function(){return UsersViewUtil.getPropertyValue(
                                    UsersViewUtil.configs[UsersViewUtil.PASSWORD_MINLENGTH],UsersViewUtil.MIN_PASSWORD_LENGTH);};
                            return ((value.length >= param) || (value.length == 0));
                        },
                        function (){ return localizer.getString('fs.users.validations.checkLengthDynamic', args);}
                      );

                    // check for  special characters
                    jQuery.validator.addMethod("cicUserSettingsEditMobilePhoneNumCheck",
                        function(value,element, param) {
                            var regex =  UsersViewUtil.getPropertyValue(UsersViewUtil.configs[UsersViewUtil.MOBILE_VALID],
                                "^[^\"'&=<>]+$") ;
                            var isValidPh = new RegExp(regex).test(value);
                            return (value.length == 0 || isValidPh);
                        },
                        function (){ return UsersViewUtil.getPropertyValue(
                                UsersViewUtil.configs[UsersViewUtil.MOBILE_ERRORMSG], validPhoneNum);
                        }
                    );

                    // check for  special characters
                    jQuery.validator.addMethod("cicUserSettingsEditOfficePhoneNumCheck",
                        function(value,element, param) {
                            var regex =  UsersViewUtil.getPropertyValue(UsersViewUtil.configs[UsersViewUtil.OFFICE_VALID],
                                "^[^\"'&=<>]+$") ;
                            var isValidPh = new RegExp(regex).test(value);
                            return (value.length == 0 || isValidPh);
                        },
                        function (){ return UsersViewUtil.getPropertyValue(
                                UsersViewUtil.configs[UsersViewUtil.OFFICE_ERRORMSG], validPhoneNum);
                        }
                    );

                    //No special characters allowed <>;,"'&\/|+.:
                    $.validator.addMethod("cicUserSettingsEditCheckPasswdString",
                        function(value, element, param) {
                            var regex =  UsersViewUtil.getPropertyValue(UsersViewUtil.configs[UsersViewUtil.PASSWORD_VALID],
                                "^[^<>;,\"'&\\\/|+:= ]+$") ;
                            var isValidPwd = new RegExp(regex).test(value);
                            return (value.length == 0 || isValidPwd);
                        },
                        function (){ return UsersViewUtil.getPropertyValue(
                                UsersViewUtil.configs[UsersViewUtil.PASSWORD_ERRORMSG], validPassword);
                          });
                }


            }

            //to clear the validators
            function functionCheck(){
              if (initialized){
                validator.resetForm();
                formStateView.reset();
              }
            }

            //initialise the dialog
            this.initialize = function(){
                registerEvents();
                functionCheck();
                dialog = new DialogView({
                    contents:userSelfEditHtml,
                    ok : function() {
                        changeCount = $(COUNT).text();
                        if ($.trim(changeCount) == 0){
                           $(CANCEL).trigger('click');
                        }else{
                            onEditUserClick();
                        }
                        return false;
                    },
                    cancel : onEditUserCancelClick
                });
                init();
                initUserEdit();
            };
        }

        return  new UserSettingsEditView();
    }());

    return UserSettingsEditView;
});
