import {Injectable} from '@angular/core';
import {HttpService} from '../app-services/http.service';
import {LocalStoreService} from '../app-services/local-store.service';
import {Observable} from 'rxjs/Observable';
import {Subject} from 'rxjs/Subject';
import {ToastsManager} from 'ng2-toastr';
import {Constants} from '../constants';
import {PermissionsService} from './permissions.service';

@Injectable()
export class UserService {

    public id;
    public user_name;
    public user_mail;
    public contact;
    public user_desig;
    public user_region;
    public user_terms;
    public attempt;
    public user_role;
    public avatar;
    public tooltip;
    public token;
    public token_expire;

    public CHANGE_REQUESTED = 1;
    public PASSWORD_EXPIRED = 2;
    public PASSWORD_STRENGTH = 3;

    private passwordValidations = [
        {message: 'be at least 8 characters', rule: /^.{8}/},
        {message: 'be at most 255 characters', rule: /^.{0,255}$/},
        {message: 'contain at least one lowercase letter', rule: /[a-z]/},
        {message: 'contain at least one uppercase letter', rule: /[A-Z]/},
        {message: 'contain at least one number', rule: /[0-9]/}
    ];

    private LOGIN = 'api-users/dologin';
    private VERIFY = 'api-users/verifytoken';
    private FORGOT = 'user/send-password';
    private UPDATE_PASSWORD = 'api-users/new-password';
    private ALIVE = 'api-users/alive';
    private LOGOUT = 'api-users/logout';

    private password;
    private keepAliveTime = 160;
    private pollingIntervalId;
    private emitSessionDestroyed = new Subject<any>();
    onSessionDestroyed = this.emitSessionDestroyed.asObservable();

    constructor(private http: HttpService,
                private localStoreService: LocalStoreService,
                private toaster: ToastsManager,
                private permissions: PermissionsService) {
    }


    isAuthenticated($checkFromServer = false) {
        if (this.id) {
            return true;
        }
    }

    validatePassword(password) {
        let valid = true;
        let message = 'Password must ';
        this.passwordValidations.forEach(data => {
            if (data.rule.test(password) === false) {
                valid = false;
                message += data.message + ', ';
            }
        });
        message = message.substr(0, message.length - 2);
        message += '.';

        return {
            valid,
            message
        };
    }

    populate(data) {
        const keys = Object.keys(data);
        keys.forEach(key => {
            this[key] = data[key];
        });
    }

    sendPassword(email_address) {
        const postData = {
            email_address
        };
        const promise = this.http.post(this.FORGOT, postData);
        return promise;
    }

    updatePassword(token, password) {
        const postData = {
            password,
            token
        };
        return this.http.post(this.UPDATE_PASSWORD, postData);
    }

    alive() {
        const showErrors = {
            e401: false,
        };
        return this.http.get(this.ALIVE, '', showErrors).subscribe(data => {
            if (data.active === false) {
                this.emitSessionDestroyed.next('Session Destroyed');
                if (this.pollingIntervalId) {
                    clearInterval(this.pollingIntervalId);
                }
            }
        }, er => {
            this.emitSessionDestroyed.next('Session Destroyed');
            if (this.pollingIntervalId) {
                clearInterval(this.pollingIntervalId);
            }
        });
    }

    startAlivePolling() {
        this.pollingIntervalId = setInterval(() => {
            this.alive();
        }, this.keepAliveTime * 1000);
    }

    login(username, password) {
        const postData = {
            username,
            password
        };
        const showErrors = {
            e401: true
        };
        const promise = this.http.post(this.LOGIN, postData, showErrors);
        promise.subscribe(data => {
            this.http.setTokken(data.access_token);
            this.populate(data.user);
            this.localStoreService.set('access_token', data.access_token);
            this.postLoginSteps();
        }, error => {

        });

        return promise;
    }

    logout() {
        const data = {
            e401: false
        };
        if (this.pollingIntervalId) {
            clearInterval(this.pollingIntervalId);
        }
        this.permissions.setUserRole(null);
        return this.http.get(this.LOGOUT, '', data);
    }

    tryAutoLogin() {
        return new Observable(observer => {
            const access_token = this.localStoreService.get('access_token');
            if (access_token) {
                const showErrors = {
                    e401: false
                };
                this.http.setTokken(access_token);
                this.http.get(this.VERIFY, '', showErrors).subscribe(data => {
                    if (data.verified) {
                        this.populate(data.user);
                        observer.next(data.user);
                        observer.complete();
                        this.postLoginSteps();
                    } else {
                        this.localStoreService.remove('access_token');
                        observer.error('Unable to veryfy access_token');
                    }
                }, err => {
                    this.localStoreService.remove('access_token');
                    observer.error('Unable to veryfy access_token');
                });
            } else {
                observer.error('No access_token found');
            }
        });
    }

    postLoginSteps() {
        this.startAlivePolling();
        this.permissions.setUserRole(this.user_role);
        this.permissions.getUserPermissions();
    }
}
