﻿"use strict";

// Auth service to perform authentication
app.factory("authService", ["$rootScope", "$q", "$injector", "localStorageService", "ngAuthSettings", "$http", "$location", function ($rootScope, $q, $injector, localStorageService, ngAuthSettings, $http, $location) {

    //var serviceBase = ngAuthSettings.apiServiceBaseUri; 
    var $http;
    var authServiceFactory = {};
    var tokenPath = "/oauth2/token";

    var _getSecureApiBaseUri = function () {
        // We're using a function here to make sure the app startup initializes, if we use a scope var we may not have the initialized value yet
        return ($rootScope.secureApiBaseUri);
    };
    var _authentication = {
        isAuth: false,
        userName: "",
        useRefreshTokens: true
    };
    var _updateLastLogin = function (username) {
        $http = $http || $injector.get("$http");

        $http.post("/api/account/updateLastLogin/1".format(_getSecureApiBaseUri()), { Username: username });
    };

    var _validateCredentials = function (credentials) {
        var deferred = $q.defer();

        var postData = { Username: credentials.username, Password: credentials.password };
        $http = $http || $injector.get("$http");
        $http.post(_getSecureApiBaseUri() + "/account/validateCredentials/1", postData)
            .success(function (response) {
                deferred.resolve(response);
            })
            .error(function (err, status) {
                _logOut();
                deferred.reject(err);
            });

        return (deferred.promise);
    };

    var _validateCredentialsAndGenerateAccessCode = function (credentials) {
        var deferred = $q.defer();

        var postData = { Username: credentials.username, Password: credentials.password };
        $http = $http || $injector.get("$http");
        $http.post(_getSecureApiBaseUri() + "/account/validateCredentialsAndGenerateAccessCode/1", postData)
            .success(function (response) {
                deferred.resolve(response);
            })
            .error(function (err, status) {
                _logOut();
                deferred.reject(err);
            });

        return (deferred.promise);
    };

    var _login = function (loginData) {
        var data = "grant_type=password&username=" + loginData.userName.replace(/\+/g, '%2B') + "&password=" + encodeURIComponent(loginData.password);

        if (loginData.useRefreshTokens) {
            data = data + "&client_id=" + $rootScope.clientId;
        }

        var deferred = $q.defer();

        $http = $http || $injector.get("$http");
        $http.post(_getSecureApiBaseUri() + tokenPath, data, { headers: { "Content-Type": "application/x-www-form-urlencoded" } }).success(function (response) {
            if (loginData.useRefreshTokens) {
                localStorageService.set(ngAuthSettings.authDataKey,
                    {
                        token: response.access_token,
                        userName: loginData.userName,
                        refreshToken: response.refresh_token,
                        useRefreshTokens: true,
                        homeUrl: response['redirect_url']
                    });
            }
            else {
                localStorageService.set(ngAuthSettings.authDataKey, {
                    token: response.access_token,
                    userName: loginData.userName,
                    refreshToken: "",
                    useRefreshTokens: false,
                    homeUrl: response['redirect_url']
                });
            }
            _authentication.isAuth = true;
            _authentication.userName = loginData.userName;
            _authentication.useRefreshTokens = loginData.useRefreshTokens;

            // Reset all rootscope data
            $rootScope.resetRootData();

            _updateLastLogin(loginData.userName);

            $rootScope.$broadcast("logged in");

            // Resolve the promise with response from login
            deferred.resolve(response);

        }).error(function (err, status) {
            if (_authentication.isAuth) {
                _logOut();
            }
            deferred.reject(err);
        });

        console.i("returning the login promise");
        return (deferred.promise);
    };
    function _isLoggedIn() {
        return _authentication.isAuth;
    }
    var _logOut = function () {
        // Remove the auth data
        localStorageService.remove(ngAuthSettings.authDataKey);

        _authentication.isAuth = false;
        _authentication.userName = "";
        _authentication.useRefreshTokens = false;

        $location.path('/login');
    };
    var _fillAuthData = function () {
        var authData = localStorageService.get(ngAuthSettings.authDataKey);
        if (authData) {
            _authentication.isAuth = true;
            _authentication.userName = authData.userName;
            _authentication.useRefreshTokens = authData.useRefreshTokens;
        }
    };
    var _refreshToken = function () {
        var deferred = $q.defer();

        var authData = localStorageService.get(ngAuthSettings.authDataKey);
        if (authData && authData.useRefreshTokens) {

            var data = "grant_type=refresh_token&refresh_token=" + authData.refreshToken + "&client_id=" + $rootScope.clientId;

            localStorageService.remove(ngAuthSettings.authDataKey);

            $http = $http || $injector.get("$http");
            $http.post(_getSecureApiBaseUri() + tokenPath, data, { headers: { "Content-Type": "application/x-www-form-urlencoded" } }).success(function (response) {

                localStorageService.set(ngAuthSettings.authDataKey, { token: response.access_token, userName: response.userName, refreshToken: response.refresh_token, useRefreshTokens: true });
                deferred.resolve(response);

            }).error(function (err, status) {
                _logOut();
                deferred.reject(err);
            });
        } else {
            deferred.reject();
        }

        return deferred.promise;
    };
    var _getUserInfo = function () {
        $http = $http || $injector.get("$http");
        return $http.get(ngAuthSettings.apiServiceBaseUri + "/contact/").then(function (results) {
            return results;
        });
    };
    var _sendForgotPasswordEmail = function (emailAddress) {
        console.log("sending forgot password email..." + emailAddress);
        var postData = {
            EmailAddress: emailAddress
        };

        return $http.post("/api/account/", postData).then(function (results) {
            return results;
        });

    };

    var _sendResetPasswordEmail = function (emailAddress) {
        console.log("sending reset password email..." + emailAddress);
        var postData = {
            EmailAddress: emailAddress
        };

        return $http.post("/api/account/sendResetJudgePassword/1", postData).then(function (results) {
            return results;
        });
    };

    var _changePasswordByContactId = function (contactId, password) {
        console.i("changing password by contact id");

        $http = $http || $injector.get("$http");
        var data = { ContactId: contactId, Password: password };
        return $http.post("/api/account/changePasswordByContactId/1", data);
    };

    var _changePasswordByEncryptedContactId = function (encryptedContactId, password, email, token) {
        console.i("changing password by encrypted contact id");

        $http = $http || $injector.get("$http");
        var data = { EncryptedContactId: encryptedContactId, Password: password, EmailAddress: email, Token: token };
        return $http.post("/api/account/changePasswordByEncryptedContactId/1", data);
    };

    var _checkExpiredRequest = function (token, encryptedContactId) {
        console.i("checking expired request");
        $http = $http || $injector.get("$http");
        var data = { Token: token, EncryptedContactId: encryptedContactId };
        return $http.post("/api/account/checkExpiredRequest/1", data);
    };
    var _changePassword = function (username, password, oldPassword) {
        console.i("changing password");

        $http = $http || $injector.get("$http");
        var data = { Username: username, Password: password, OldPassword: oldPassword };
        return $http.post("/api/account/changePassword/1", data);
    };

    authServiceFactory.login = _login;
    authServiceFactory.isLoggedIn = _isLoggedIn;
    authServiceFactory.logOut = _logOut;
    authServiceFactory.fillAuthData = _fillAuthData;
    authServiceFactory.authentication = _authentication;
    authServiceFactory.refreshToken = _refreshToken;
    authServiceFactory.getUserInfo = _getUserInfo;
    authServiceFactory.sendForgotPasswordEmail = _sendForgotPasswordEmail;
    authServiceFactory.sendResetPasswordEmail = _sendResetPasswordEmail;
    authServiceFactory.changePasswordByContactId = _changePasswordByContactId;
    authServiceFactory.changePasswordByEncryptedContactId = _changePasswordByEncryptedContactId;
    authServiceFactory.checkExpiredRequest = _checkExpiredRequest;
    authServiceFactory.changePassword = _changePassword;
    authServiceFactory.validateCredentials = _validateCredentials;
    authServiceFactory.validateCredentialsAndGenerateAccessCode = _validateCredentialsAndGenerateAccessCode;

    return authServiceFactory;
}]);