import {Injectable} from '@angular/core';
import {Headers, Http, RequestOptions} from '@angular/http';
import 'rxjs/add/operator/map';
import 'rxjs/add/operator/share';
import {ToastsManager} from 'ng2-toastr/ng2-toastr';
import {Constants} from '../constants';
import {Router} from '@angular/router';

@Injectable()
export class HttpService {

    private accessTokken: string;
    private headers;
    private options;
    private api = Constants.API_URL;
    private sendAuthMsg;

    constructor(private http: Http,
                private toastr: ToastsManager,
                private router: Router) {
        this.sendAuthMsg = true;
    }

    setTokken(value) {
        this.accessTokken = value;
    }

    createHeader() {
        if (this.accessTokken) {
            this.headers = new Headers({'Content-Type': 'application/json'});
            this.headers.append('Authorization', this.accessTokken);
            this.options = new RequestOptions({headers: this.headers});
        }
        else {
            this.headers = new Headers({'Content-Type': 'application/json'});
            this.options = new RequestOptions({headers: this.headers});
        }
        return this.options;
    }

    sendUnAuthorizedMessage(message) {
        message = message || 'You need to login first.';
        this.sendAuthMsg = false;
        this.toastr.error(message, null, {showCloseButton: true});
        setTimeout(() => {
            this.sendAuthMsg = true;
        }, 5000);
    }

    showError(error, showErrors) {
        switch (error.status) {
            case 401:
                if (showErrors.e401 != false) {
                    if (this.sendAuthMsg) {
                        const body = error.json();
                        const errorMsg = body.message || 'You need to login first';
                        this.sendUnAuthorizedMessage(errorMsg);
                    }
                    this.router.navigate(['/']);
                }
                break;
            case 400:
                if (showErrors.e400 != false) {
                    const body = error.json();
                    const errorMsg = body.message || 'There seems to be some error.';
                    this.toastr.error(errorMsg, null, {showCloseButton: true});
                }
                break;
            case 500:
                if (showErrors.e500 != false) {
                    this.toastr.error('We are unable to process your request.', null, {showCloseButton: true});
                }
                break;
            case 404:
                if (showErrors.e404 != false) {
                    this.toastr.error('API resource does not exist', null, {showCloseButton: true});
                }
                break;
            case 422:
                if (showErrors.e422 != false) {
                    let errorMsg;
                    const body = error.json();
                    errorMsg = body.message;
                    this.toastr.error(errorMsg, 'Oops!', {showCloseButton: true});
                }
                break;
        }
    }

    post(method, value, showErrors = {}) {

        const url = this.api + method;
        const observable = this.http.post(url, value, this.createHeader()).map((response) => {
            return response.json();
        }).share();


        observable.subscribe(
            data => {},
            error => {
                this.showError(error, showErrors);
            }
        );

        return observable;
    }

    get(method, value = '', showErrors = {}) {
        const url = this.api + method + value;
        const observable = this.http.get(url, this.createHeader()).map((response) => {
            return response.json();
        }).share();


        observable.subscribe(
            data => {
            },
            error => {
                this.showError(error, showErrors);
            }
        );

        return observable;
    }

    delete(method, value = '', showErrors = {}) {
        const url = this.api + method + value;
        const observable = this.http.delete(url, this.createHeader()).map((response) => {
            return response.json();
        }).share();


        observable.subscribe(
            data => {
            },
            error => {
                this.showError(error, showErrors);
            }
        );

        return observable;
    }

    put(method, value, showErrors = {}) {
        const url = this.api + method;
        const observable = this.http.put(url, value, this.createHeader()).map((response) => {
            return response.json();
        }).share();


        observable.subscribe(
            data => {
            },
            error => {
                this.showError(error, showErrors);
            }
        );

        return observable;
    }
}
