
import Ws from "@adonisjs/websocket-client";
import UserChannelService from './user.channel.service';
import { EventEmitter } from 'events';
import CallManager from "./call.manager";
let singleton: WebSocketService = null;
enum EEvents {
  NEW_CONNECTION,
  CONNECTION_ONLINE,
  CONNECTION_OFFLINE,
  INCOMING_CALL,
}
export default class WebSocketService {
  static Events = EEvents;
  private emitter;
  readonly callManager: CallManager;

  private constructor(private ws, private userChannelService: UserChannelService) {
    this.emitter = new EventEmitter();
    this.userChannelService.on('new:connection', this.onUserNewConnection.bind(this));
    this.userChannelService.on('connection:online', this.onUserConnectionOnline.bind(this));
    this.userChannelService.on('connection:offline', this.onUserConnectionOffline.bind(this));
    this.userChannelService.on('call:incoming', this.onIncomingCall.bind(this));
    this.callManager = new CallManager(this);
  }


  on(event: EEvents, callback: Function) {
    this.emitter.on(event, callback);
  }
  removeListener(event: EEvents, callback) {
    this.emitter.removeListener(event, callback);
  }
  subscribe(channel) {
    const subscription = this.ws.subscribe(channel);
    console.log(subscription);
    return subscription;
  }
  private onIncomingCall(data) {
    this.emitter.emit(EEvents.INCOMING_CALL, data);
  }
  private onUserNewConnection(data) {
    this.emitter.emit(EEvents.NEW_CONNECTION, data);
  }

  private onUserConnectionOnline(data) {
    this.emitter.emit(EEvents.CONNECTION_ONLINE, data);
  }

  private onUserConnectionOffline(data) {
    this.emitter.emit(EEvents.CONNECTION_OFFLINE, data);
  }

  static getInstance(): Promise<WebSocketService> {
    return new Promise((resolve, reject) => {
      // resolve();
      // return;
      if (singleton) return resolve(singleton);

      const ws = Ws('', { path: 'connect' });
      ws.connect();

      ws.on('open', async () => {
        const userChannelService = await UserChannelService.getInstance(ws);
        const success = await userChannelService.connect();
        console.log('Connected to user socket:', success);
        singleton = new WebSocketService(ws, userChannelService);
        resolve(singleton);
      });
      ws.on('error', (error) => {
        console.log(error)
        reject(new Error('Failed to connect'));
      })
      ws.on('close', _ => {
        console.log('Socket Closed');
      });
    });
  }
}
