// (C) Copyright 2020 Hewlett-Packard Enterprise Company, L.P.
define([ 'hp/model/Session', 'hp/services/authn', 'hp/services/authz', 'hp/services/lum', 'hp/model/Login',
        'hp/core/EventDispatcher' ], function(session, authnService, authzService, lumService, loginModel, EventDispatcher) {
    "use strict";

    var LoginPresenter = (function() {

        var dispatcher = new EventDispatcher();

        var PASSWORD_CHANGE_REQUIRED = 'PASSWORD_CHANGE_REQUIRED';

        /**
         * @class Singleton class containing presentation logic for the
         *        Login page.
         * @type {LoginPresenter}
         */
        function LoginPresenter() {

            /**
             * Translates a JavaScript Date into an ISO 8601 formatted
             * date/time string.
             *
             * @param {Date}
             *            d The date to translate.
             * @return {string} The formatted date.
             */
            // https://developer.mozilla.org/en/JavaScript/Reference/Global_Objects/Date#Example:_ISO_8601_formatted_dates
            function toISODateString(d) {
                function pad(n) {
                    return n < 10 ? '0' + n : n;
                }
                return d.getUTCFullYear() +
                '-' + pad(d.getUTCMonth() + 1) +
                '-' + pad(d.getUTCDate()) +
                'T' + pad(d.getUTCHours()) + ':' +
                pad(d.getUTCMinutes()) +
                ':' + pad(d.getUTCSeconds()) + 'Z';
            }

            /**
             * Handles the success of the login attempt by saving the
             * session information, retrieving the user's
             * authorizations, and calling the caller's success handler.
             *
             * @param {{sessionID:string}}
             *            loginSessionIdDto The DTO from the server with
             *            the session ID and other information.
             * @param {string}
             *            username The user who logged in.
             * @param {{success:function():void,
             *            error:function(string):void}} handlers The
             *            caller's success and error handler functions.
             */
            function onLoginSuccess(loginSessionIdDto, username, selectedAuthService, handlers) {
                loginModel.setInitialPasswordInfo(null);
                session.saveToken(loginSessionIdDto.sessionID);
                session.saveUser(username);
                session.saveLoginTime(toISODateString(new Date()));
                session.saveAuthService(selectedAuthService);
                authzService.getAll({
                    success : function(authorizations) {
                        session.saveAuthorizations(authorizations.members);
                        handlers.success();
                    },
                    error : function(errorInfo) {
                        session.eraseAll();
                        handlers.error(errorInfo.errorMessage);
                    }
                });
            }

            /**
             * Handle an error coming back from the login request.
             *
             * @param {Object}
             *            errorInfo Error information from the server
             * @param {success:function():void,
             *            error:function(string):void,
             *            passwordChange:function():void}} handlers The
             *            caller's success, error, and password change
             *            handler functions.
             */
            function onLoginError(errorInfo, handlers) {
                if (PASSWORD_CHANGE_REQUIRED == errorInfo.errorCode) {
                    // The user needs to reset his password.
                    handlers.passwordChange();
                    return;
                }
                handlers.error(errorInfo);
            }

            /*
             * Success event handler
             */
            function onGetGlobalSettingsSuccess(globalSettingsDto) {
                var allowLocalLoginDto = {
                    "allowLocalLogin" : globalSettingsDto.allowLocalLogin
                };
                loginModel.setAllowLocalLogin(allowLocalLoginDto);
                loginModel.setDefaultProvider(globalSettingsDto.defaultLoginDomain);
                loginModel.setProviderInfos(globalSettingsDto.configuredLoginDomains);
                dispatcher.fire('getGlobalSettingsComplete');
            }

            function onGetGlobalSettingsError(errorInfo) {
                loginModel.setAllowLocalLogin(null);
                loginModel.setDefaultProvider(null);
                loginModel.setProviderInfos(null);
                var failureMessage = "Error"; // localizer.getString('settings.authn.failed_get_global_settings');
                dispatcher.fire('getGlobalSettingsError', {
                    "errorInfo" : errorInfo,
                    "failureMessage" : failureMessage
                });
            }

            /*
             * Call the authentication service to load settings
             */
            function loadGlobalSettings() {
                authnService.getGlobalSettings({
                    success : onGetGlobalSettingsSuccess,
                    error : onGetGlobalSettingsError
                });
            }

            /**
             * Log the user in.
             *
             * @param {string}
             *            username The username to log in with.
             * @param {string}
             *            password The password to log in with.
             * @param {string}
             *            authnProvider The authentication provider.
             * @param {{success:function():void,
             *            error:function(string):void,
             *            passwordChange:function():void}} handlers
             *            Functions to call on success, error, or
             *            initial password change; the parameter to the
             *            error handler is an error message.
             */
            this.login = function(username, password, authnProvider, handlers) {
                loginModel.setInitialPasswordInfo({
                    username : username,
                    password : password
                });
                authnService.login(username, password, authnProvider, {
                    success : function(loginSessionIdDto) {
                        onLoginSuccess(loginSessionIdDto, username, authnProvider, handlers);
                    },
                    error : function(errorInfo) {
                        onLoginError(errorInfo, handlers);
                    }
                });
            };

            /*
             * Public function to load settings
             */
            this.loadProvidersInfo = function() {
                loadGlobalSettings();
            };

            /*
             * Event register
             */
            this.on = function(eventName, callback) {
                dispatcher.on(eventName, callback);
            };

            /*
             * Event unregister
             */
            this.off = function(eventName, callback) {
                dispatcher.off(eventName, callback);
            };

            /**
             * Set the user's initial password and then log the user in.
             *
             * @param {string}
             *            password The new password to set.
             * @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.setInitialPassword = function(password, handlers) {
                var presenter = this;
                lumService.changePassword(loginModel.getInitialPasswordInfo().username, loginModel.getInitialPasswordInfo().password, password, {
                    success : function() {
                        presenter.login(loginModel.getInitialPasswordInfo().username, password, "LOCAL", handlers);
                    },
                    error : function(errorInfo) {
                        handlers.error(errorInfo);
                    }
                });
            };

            /*
             * Get global settings for local user
             */
            this.getAllowLocalUser = function() {
                return loginModel.getAllowLocalLogin();
            };

            this.getDefaultProvider = function() {
                return loginModel.getDefaultProvider();
            };

            this.getProviderInfos = function() {
                return loginModel.getProviderInfos();
            };

            /**
             * Returns the user's username, during an initial password
             * change.
             *
             * @return {string} Username.
             */
            this.getUsername = function() {
                return loginModel.getInitialPasswordInfo() ? loginModel.getInitialPasswordInfo().username : null;
            };

        }

        return new LoginPresenter();
    }());

    return LoginPresenter;
});
