import {Injectable,} from "@angular/core";
import {Subject} from "rxjs/Subject";
import {IPushNotificationMessage} from "../models/IPushNotificationMessage";
import {ConfigService} from "./ConfigService";
import {Observable} from "rxjs/Observable";
import {Observer} from "rxjs/Observer";
import {HubConnection, HubProxy, JQueryStatic} from "../models/ISignalR";


declare var $:JQueryStatic;

export enum hubStates
{
    starting = 0,
    received = 1,
    connectionSlow = 2,
    reconnecting = 3,
    reconnected = 4,
    disconnected = 5


}

@Injectable()
export class ConnectionHubService
{
    public receivedStream:Subject<any> = new Subject<any>();
    public WhenStateChange:Subject<hubStates> = new Subject<hubStates>();
    private hub:HubProxy;
    private connection:HubConnection;


    constructor( config:ConfigService )
    {
        //$.connection.hub.url = 'http://localhost:9090/signalr';
        let url = "http://" + config.getConfig().WebApiAddress + ":" + config.getConfig().WebApiPort + "/signalr";

        $.connection.hub.url = url;
        $.connection.hub.logging = true;

        this.connection = $.hubConnection();
        this.hub = this.connection.createHubProxy('ConnectionHubService');

        //received Event
        this.connection.received(( data:any ) => this.receivedStream.next(data));

        // //lifetimeEvents
        // this.connection.starting( () => this.WhenStateChange.next( ConnectionHubStates.Starting ) );
        // this.connection.connectionSlow( () => this.WhenStateChange.next( ConnectionHubStates.ConnectionSlow ) );
        // starting: Raised before any data is sent over the connection.
        // received: Raised when any data is received on the connection. Provides the received data.
        // connectionSlow: Raised when the client detects a slow or frequently dropping connection.
        // reconnecting: Raised when the underlying transport begins reconnecting.
        // reconnected: Raised when the underlying transport has reconnected.
        // stateChanged: Raised when the connection state changes. Provides the old state and the new state (Connecting, Connected, Reconnecting, or Disconnected).
        // disconnected: Raised when the connection has disconnected.

        this.connection.starting(() => this.WhenStateChange.next(hubStates.starting));
        this.connection.received((data:any) =>
                                 {
                                     this.WhenStateChange.next(hubStates.received)
                                 });
        this.connection.connectionSlow(() => this.WhenStateChange.next(hubStates.connectionSlow));
        this.connection.reconnecting(() => this.WhenStateChange.next(hubStates.reconnecting));
        this.connection.reconnected(() => this.WhenStateChange.next(hubStates.reconnected));
        this.connection.disconnected(() =>
                                     {
                                         this.WhenStateChange.next(hubStates.disconnected);
                                         setTimeout(function ()
                                                    {
                                                        this.startConnection();
                                                    }, 5000);
                                     });
    }

    public receiveFromHost = <T>( event:string ):Observable<IPushNotificationMessage<T>> =>
    {
        return Observable.create(( observer:Observer<IPushNotificationMessage<T>> ) =>
                                 {
                                     this.hub.on("receiveNotification", ( message:IPushNotificationMessage<T> ) =>
                                     {
                                         if (message.eventName == event)
                                             observer.next(message)
                                     });
                                 });

    };


    public startConnection = ():void =>
    {
        this.connection.start().done(()=>
                                     {
                                         console.log("ConnectionHubService started")
                                     }).fail(( e )=>
                                             {
                                                 console.log("ConnectionHubService fail" + e)
                                             });
    };

    public closeConnection = ():void =>
    {
        this.connection.stop(true, true);
    };


    public setUsuarioId = ( id:string ):void =>
    {
        this.connection.qs = {'userId': id};
    }


}