import { HttpParams } from '@angular/common/http';
import { Injectable } from '@angular/core';
import { Router, UrlSerializer } from '@angular/router';
import * as signalR from "@microsoft/signalr"
import { Subject } from 'rxjs';
import { environment } from '../../environments/environment';
import { UuidUtils } from '../utilities/uuid-utils';
import { AuthService } from './auth.service';
import { LoginUserService } from './login-user.service';


const SIGNAL_R_URL = (id: string = null) => { return `${environment.apiUrl}/${id}` }
@Injectable({
  providedIn: 'root'
})
export class SignalRService {
  ReceivedSignalRMessageSubject = new Subject<SignalRMessage>();
  signalRMessageConnSubject = new Subject<SignalRConnectionState>();
  private hubConnection: signalR.HubConnection
  constructor(
    private loginUserService: LoginUserService,
    private router: Router,
    private serializer: UrlSerializer
  ) { }

  public startWhoIsSpyConnection = () => {
    this.hubConnection = new signalR.HubConnectionBuilder()
      .withUrl(SIGNAL_R_URL('WhoIsSpyHub'))
      .withAutomaticReconnect()
      .build();

    this.hubConnection
      .start()
      .then(() => console.log('WhoIsSpyHub Connection started:' + this.hubConnection.connectionId))
      .catch(err => console.log('Error while starting connection: ' + err))

    this.hubConnection.on("ReceiveMessage", (user, message) => {
      const li = document.createElement("li");
      li.textContent = `${user}: ${message}`;
      document.getElementById("messageList").appendChild(li);
    });

  }
  public startSignalRConnection(gameRoomId: string = '') {
    this.signalRMessageConnSubject.next({ status: 'connecting' });
    if (!this.loginUserService.sessionTabId) {
      this.loginUserService.sessionTabId = UuidUtils.generate();
    }

    const tree = this.router.createUrlTree([], {
      queryParams: {
        userId: this.loginUserService.userAccess.memberId,
        userName: this.loginUserService.userAccess.firstName,
        tabId: this.loginUserService.sessionTabId,
        roomId: gameRoomId
      }
    });
    const params = new HttpParams()
      .set('userId', this.loginUserService.userAccess.memberId)
      .set('userName', this.loginUserService.userAccess.firstName)
      .set('tabId', this.loginUserService.sessionTabId)
      .set('roomId', gameRoomId);

    Object.defineProperty(WebSocket, 'OPEN', { value: 1, });
    this.hubConnection = new signalR.HubConnectionBuilder()
      .withUrl(`${SIGNAL_R_URL('GameRoomHub')}?${params.toString()}`)
      .withAutomaticReconnect()
      .build();
    this.registerHubConnectionLifecycleHandlers();
    let me = this
    this.hubConnection
      .start()
      .then(() => {
        me.setSignalRConnectionId(this.hubConnection.connectionId);
        this.signalRMessageConnSubject.next({
          status: 'connected',
          connectionId: this.hubConnection.connectionId
        });
      })
      .catch(err => {
        console.log('Error while starting connection: ' + err);
        this.signalRMessageConnSubject.next({ status: 'error', error: err });
      })
    this.hubConnection.on("ReceivedMessage", (jsonString) => {
      this.BroadcastAPIMessageReceive(JSON.parse(jsonString));
    });

  }
  public setSignalRConnectionId(connectionId: string) {

    this.loginUserService.userAccess.signalRConnectionId = connectionId;
    this.loginUserService.signalRInitialized.next(connectionId);
    console.log('GameRoomHub start connection: ' + this.hubConnection.connectionId)

  }

  private registerHubConnectionLifecycleHandlers() {
    this.hubConnection.onreconnecting(error => {
      console.warn('SignalR reconnecting...', error);
      this.signalRMessageConnSubject.next({ status: 'reconnecting', error });
    });

    this.hubConnection.onreconnected(connectionId => {
      console.log('SignalR reconnected with new connectionId', connectionId);
      this.setSignalRConnectionId(connectionId);
      this.signalRMessageConnSubject.next({ status: 'reconnected', connectionId });
    });

    this.hubConnection.onclose(error => {
      console.warn('SignalR connection closed', error);
      this.clearSignalRConnectionId();
      this.signalRMessageConnSubject.next({ status: 'closed', error });
    });
  }

  private clearSignalRConnectionId() {
    if (this.loginUserService?.userAccess) {
      this.loginUserService.userAccess.signalRConnectionId = null;
    }
  }



  BroadcastAPIMessageReceive(msg: SignalRMessage) {
    let jsonContent = null;
    if (msg.jsonValue) {
      try {
        msg.jsonValue = JSON.parse(msg.jsonValue);

      } catch (e) {
      }
    }
    this.ReceivedSignalRMessageSubject.next(msg);
  }


}
export interface SignalRMessage {
  from: SignalRClient;
  receiver: SignalRClient;
  actionType: string;
  actionName: string;
  parameters: { [key: string]: string; };
  value: any;
  jsonValue: string;
}

export interface SignalRClient {
  connectionId: string;
  name: string;
  isGroup: boolean;
}

export interface SignalRConnectionState {
  status: 'connecting' | 'connected' | 'reconnecting' | 'reconnected' | 'closed' | 'error';
  connectionId?: string;
  error?: any;
}