import { Injectable } from '@angular/core';
import {Observable, Subject, Subscriber} from 'rxjs';
import {AppConfig} from './app.config';
import {WsLoginEventModel} from './models/websocket/ws.login.event.model';



@Injectable()
export class WebSocketService extends Subject<string>{

  private connected = false;
  private sessionId = '';
  private socketId = '';
  public ws: WebSocket;
  private readonly url: string;
  public LoginEvent: Subject<WsLoginEventModel>;
  public assignSocketIdEvent: Subject<string>;

  // cannot have session as service, as session use us as building block
  constructor(private config: AppConfig) {
    super();
    this.url = config.apiWsUrl;
    this.startWebsocket();
    this.LoginEvent = new Subject<WsLoginEventModel>();
    this.assignSocketIdEvent = new Subject<string>();
  }

  private startWebsocket(): void {
    // console.log('starting websocket now..', this.url);
    this.ws = new WebSocket(this.url);
    this.ws.onopen = this.onOpen.bind(this);
    this.ws.onmessage = this.onMessage.bind(this);
    this.ws.onerror = this.onError.bind(this);
    this.ws.onclose = this.onClose.bind(this);
  }

  public onOpen(): void {
    this.connected = true;
    if ( this.sessionId !== '' ){
      this.registerSessionId( this.sessionId);
    }
  }

  public set SessionId( sid: string ) {
    if ( this.sessionId !== sid ){
      this.registerSessionId(sid);
    }
    this.sessionId = sid;
  }

  private registerSessionId(sid: string): void {
    const msg = {
      t: 'register-session',
      session: sid,
    };
    this.Send(JSON.stringify(msg));
  }

  public Send(msg: string): void {
    if ( !this.connected ) {
      return;
    }
    try {
      this.ws.send(msg);
    }catch (e){
      this.connected = false;
    }
  }

  public onMessage(event): void{
    this.connected = true;
    super.next(event.data);
    try {
      const e = JSON.parse(event.data);
      if ( e.T === 'login' || e.T === 'logout' ){
        this.LoginEvent.next(new WsLoginEventModel(e));
      }
      if (e.T === 'assign-socketId') {
        this.socketId = e.socketId;
        this.assignSocketIdEvent.next(e.socketId);
      }
    }catch (e) {
      console.log(e);
    }
  }

  public onError(event): void{
    this.connected = false;
    console.log('on error ', event);
  }

  public onClose(event): void{
    this.connected = false;
    console.log('websocket closed.. reconnect in 1s ..', event);
    setTimeout(() => { this.startWebsocket(); } , 1000);
  }

}
