/**
 * Created by jd on 21/01/2016.
 */
import { Injectable } from "@angular/core";
import { Http , Headers , Response , RequestOptions } from "@angular/http";
import { Observable } from "rxjs/Observable";
import { ConfigService } from "./ConfigService";
import 'rxjs/add/operator/map';
import { Observer } from "rxjs/Rx";

@Injectable()
export class WebApiService
{

    private _apiAddress:String = "http://localhost:8787/";
    private _urlParameter:string = "";
    private _data:Object = null;
    private _resource:string = "";
    private _method:string = "GET";
    private _canSendToken:boolean = true;
    private _contentType:string = "application/json; charset=utf-8";

    constructor( private http:Http , private config:ConfigService )
    {
        this._apiAddress = "http://" + config.getConfig().WebApiAddress + ":" + config.getConfig().WebApiPort + "/";
    }

    public setApiAddress = ( newAddress:string ) =>
    {
        this._apiAddress = newAddress;
    };

    public Content = ( data:Object ):WebApiService =>
    {
        this._data = data;
        return this;
    };
    public Resource = ( resource:string ):WebApiService =>
    {
        this._resource = resource;
        return this;
    };

    public ContentType = ( contentType:string ):WebApiService=>
    {
        this._contentType = contentType;
        return this;
    };

    public Method = ( method:string ):WebApiService=>
    {
        this._method = method;
        return this;
    };

    public CanSendToken = ( canSendToken:boolean ):WebApiService =>
    {
        this._canSendToken = canSendToken;
        return this;
    };

    public Parameters = ( parameters:Object ):WebApiService =>
    {

        Object.keys( parameters ).map( ( key ) =>
        {
            if ( !parameters.hasOwnProperty( key ) ) return;

            this._resource = this._resource.replace( "{" + key + "}" , parameters[ key ].toString() );
        } );

        return this;
    };

    public Execute = <T>():Observable<T> =>
    {
        var observable = Observable.create( ( observer:Observer<T> ) =>
        {
            var requestOption = new RequestOptions();
            requestOption.method = this._method;
            requestOption.url = this._apiAddress + this._resource;

            var header = new Headers();
            header.append( "Content-Type" , this._contentType );
            header.append( "Charset" , "utf-8" );
            header.append( "Accept" , "application/json" );

            if ( this._canSendToken )
            {
                var tokenString = localStorage.getItem( "token" ).token;
                header.append( "Authorization" , "Bearer " + tokenString );
            }
            requestOption.headers = header;


            if ( this._data != null && typeof this._data != 'string' )
                requestOption.body = JSON.stringify( this._data );

            //clean
            this._data = null;

            this.http.request( this._apiAddress + this._resource , requestOption )
                .map( res =>
                {
                    // If request fails, throw an Error that will be caught
                    if ( res.status < 200 || res.status >= 300 )
                    {
                        throw new Error( 'This request has failed ' + res.status );
                    }
                    // If everything went fine, return the response
                    else
                    {
                        observer.next( <T>res.json() );
                        observer.complete();
                    }
                } ).subscribe();

        } );

        return observable;

    };

}
