import ngModule from '../module';
import UserError from 'core/lib/user-error';

/**
 * Authentication service.
 *
 * @property {Boolean} loggedIn Whether the user is currently logged
 */
export default class Auth {
    constructor($http, $q, $state, $transitions, $window, vnToken, vnModules, aclService) {
        Object.assign(this, {
            $http,
            $q,
            $state,
            $transitions,
            $window,
            vnToken,
            vnModules,
            aclService,
            loggedIn: false
        });
    }

    initialize() {
        let criteria = {
            to: state => state.name != 'login'
        };
        this.$transitions.onStart(criteria, transition => {
            if (this.loggedIn)
                return true;

            let redirectToLogin = () => {
                return transition.router.stateService.target('login', {
                    continue: this.$window.location.hash
                });
            };

            if (this.vnToken.token) {
                return this.loadAcls()
                    .then(() => true)
                    .catch(redirectToLogin);
            } else
                return redirectToLogin();
        });
    }

    login(user, password, remember) {
        if (!user) {
            let err = new UserError('Please enter your username');
            err.code = 'EmptyLogin';
            return this.$q.reject(err);
        }

        let params = {
            user,
            password: password || undefined
        };

        return this.$http.post('Accounts/login', params).then(
            json => this.onLoginOk(json, remember));
    }

    onLoginOk(json, remember) {
        this.vnToken.set(json.data.token, remember);

        return this.loadAcls().then(() => {
            let continueHash = this.$state.params.continue;
            if (continueHash)
                this.$window.location = continueHash;
            else
                this.$state.go('home');
        });
    }

    logout() {
        let promise = this.$http.post('Accounts/logout', null, {
            headers: {Authorization: this.vnToken.token}
        }).catch(() => {});

        this.vnToken.unset();
        this.loggedIn = false;
        this.vnModules.reset();
        this.aclService.reset();
        this.$state.go('login');

        return promise;
    }

    loadAcls() {
        return this.aclService.load()
            .then(() => {
                this.loggedIn = true;
                this.vnModules.reset();
            })
            .catch(err => {
                this.vnToken.unset();
                throw err;
            });
    }
}
Auth.$inject = ['$http', '$q', '$state', '$transitions', '$window', 'vnToken', 'vnModules', 'aclService'];

ngModule.service('vnAuth', Auth);