import { Injectable } from '@angular/core';
import { Headers, Http, RequestOptions, Response } from '@angular/http';

import { Observable } from 'rxjs/Observable';
import { Subject } from 'rxjs/Subject';

import 'rxjs/add/observable/throw';
import 'rxjs/add/operator/catch';
import 'rxjs/add/operator/map';

import { IApiError, IApiResponseError, IApiResponseSuccess, isApiResponseError } from './apiresponse.model';
import { IToken } from './token.model';

import { IUserCredentials } from '../user/user.model';

import { LdiStorage } from '../storage';

let TOKEN_API_URL: string = `${SETTINGS.API_URL}/token/${SETTINGS.API_IDENTIFIER}`;

@Injectable()
export class TokenService {
    public authorizationChanged: Observable<boolean>;
    private authorizationChangeSource = new Subject<boolean>();
    constructor(private http: Http) {
        console.log('token service ctor');
        this.authorizationChanged = this.authorizationChangeSource.asObservable();
    }
    get authorizationToken(): IToken {
        return LdiStorage.Token;
    }

    get authorization(): string {
        return this.authorizationToken == null ? '' : `Bearer ${this.authorizationToken.token}`;
    }

    get authorizationHeaders(): Headers {
        return new Headers({ Authorization: this.authorization });
    }

    apiConsumerToken(): Observable<IToken> {
        if (this.authorizationToken) {
            return Observable.of(this.authorizationToken);
        }

        const headers: Headers = new Headers({ 'Content-Type': 'application/json' });
        const requestOptions: RequestOptions = new RequestOptions({ headers });

        return this.http.get(TOKEN_API_URL, requestOptions)
            .map((response: Response) => {
                const data: IApiResponseError | IApiResponseSuccess<IToken> = response.json();
                if (isApiResponseError(data)) {
                    throw data.error;
                    // return Observable.throw(data.error);
                }
                // this.authorizationToken = data.result;
                // LdiStorage.SaveToken(this.authorizationToken);
                LdiStorage.SaveToken(data.result);
                return data.result;
            }).catch(this.handleError);
    }

    apiUserToken(userCredentials: IUserCredentials): Observable<IToken> {
        if (this.authorizationToken && this.authorizationToken.isUser) {
            return Observable.of(this.authorizationToken);
        }

        const headers: Headers = new Headers({ 'Content-Type': 'application/json' });
        const requestOptions: RequestOptions = new RequestOptions({ headers });
        return this.http.post(TOKEN_API_URL,
            userCredentials || { userName: null, password: null }, requestOptions)
            .map((response: Response) => {
                const data: IApiResponseError | IApiResponseSuccess<IToken> = response.json();
                if (isApiResponseError(data)) {
                    throw data.error;
                }
                // this.authorizationToken = data.result;
                // this.authorizationToken.isLogin = true;
                // LdiStorage.SaveToken(this.authorizationToken);
                LdiStorage.SaveToken(data.result);
                this.authorizationChangeSource.next(true);
                return data.result;
            }).catch(this.handleError);
    }

    get isLogin(): boolean {
        return this.authorizationToken && this.authorizationToken.isUser;
    }
    public releaseToken(): void {
        LdiStorage.Clear();
        this.authorizationChangeSource.next(false);
    }
    private handleError(error: IApiError): Observable<IToken> {
        return Observable.throw(error);
    }
}
