import { BehaviorSubject, Observable } from 'rxjs';
import { Injectable } from '@angular/core';
import { Location } from '@angular/common';
import { WebSocket } from './web-socket';
import { Window } from 'app/services/window';

export const enum AuthState {
    LoggedIn,
    LoggedOut,
}

@Injectable()
export class User {
    private _id: number = null;
    private _jwtToken: string = null;
    private _lastRoute: string = '/';
    private _loggedIn: boolean = false;
    private _firstName: string = null;

    private _authBehavior: BehaviorSubject<AuthState> = new BehaviorSubject(AuthState.LoggedOut);
    private _authState: AuthState = AuthState.LoggedOut;
    private _authChange: Observable<AuthState>;

    constructor(private _window: Window, private _location: Location, private _socket: WebSocket) {
        // Lets get JWT from localstorage
        if (this._window.localStorage.get('jwt-token')) {
            this._jwtToken = <string>this._window.localStorage.get('jwt-token');
        }
        this._authChange = this._authBehavior.asObservable();
    }

    public get lastRoute(): string {
        return this._lastRoute;
    }

    public set lastRoute(route: string) {
        this._lastRoute = route;
    }

    // eslint-disable-next-line @typescript-eslint/member-ordering
    public get jwtToken(): string {
        return this._jwtToken;
    }

    // eslint-disable-next-line @typescript-eslint/member-ordering
    public get authChange(): Observable<AuthState> {
        return this._authChange;
    }

    // eslint-disable-next-line @typescript-eslint/member-ordering
    public get loggedIn(): boolean {
        return this._loggedIn;
    }

    // eslint-disable-next-line @typescript-eslint/member-ordering
    public get firstName(): string {
        return this._firstName;
    }

    // eslint-disable-next-line @typescript-eslint/member-ordering
    public get id(): number {
        return this._id;
    }

    public login(jwt: string, id: number, firstName: string): void {
        // Login the user by saving some data in the browser
        this._id = id;
        this._loggedIn = true;
        this._window.localStorage.set('jwt-token', jwt);
        this._jwtToken = jwt;
        this._firstName = firstName;
        // Since we are loggin in we can assume that we will want to redirect to the last route
        this._authState = AuthState.LoggedIn;
        this._authBehavior.next(this._authState);
        this._socket.init(this._jwtToken);
    }

    public logout(): void {
        // Change state
        this._authState = AuthState.LoggedOut;
        this._authBehavior.next(this._authState);
        // Since we are loggin out we can redirect the to the base url
        this._lastRoute = '/';
        // Don't use the router as we don't actually want navigate - just to update the path
        this._location.go(this._lastRoute);
        // Logout the user by clearing all data
        this._loggedIn = false;
        this._firstName = null;
        this._id = null;
        this._window.localStorage.remove('jwt-token');
        this._jwtToken = null;
        this._socket.disconnect();
    }
}
