/**
 * This program has been developed by students from the bachelor Computer Science at
 * Utrecht University within the Software Project course.
 * © Copyright Utrecht University (Department of Information and Computing Sciences)
 */

import Broker from '../broker';
import BackendMessageReceiver from './BackendMessageReceiver';

/** The websockethandler creates a websocket and wait for messages send to the socket. */
export class WebSocketHandler implements BackendMessageReceiver {
  private webSocket: WebSocket | undefined;
  private url: string;
  private connected: boolean;
  private token: string | undefined;

  /** @param domain The domain to make the websocket connection with. */
  public constructor(domain: string) {
    this.url = domain;
    this.connected = false;
  }

  public useToken(token: string): WebSocketHandler {
    this.token = token;
    return this;
  }

  /**
   * Create a websocket to the given URL.
   * @param {string} URL is the URL to which the websocket connection is opened.
   */
  public connect(onOpen: () => void): void {
    // If there already is already a current websocket connection, close it first.
    if (this.webSocket) this.close();

    this.webSocket = new WebSocket(this.url + (!!this.token ? `?jwt=${encodeURIComponent(this.token)}` : ''));
    this.webSocket.onopen = () => onOpen();
    this.webSocket.onmessage = this.onWebSocketMessage;
    this.webSocket.onerror = this.onError;
    this.webSocket.onclose = this.onClose;

    this.connected = true;
  }

  /** Closes the current websocket connection. */
  public close = (): void => {
    if (this.webSocket) this.webSocket.close();
    this.connected = false;
  };

  /** @returns A boolean which indicates if there currently is a socket connection. */
  public isConnected = (): boolean => {
    return this.connected;
  };

  /**
   * Websocket connection close event handler.
   * @param {any} event Contains the event data.
   */
  private onClose(event: any): void {
    console.log(event.data);
  }

  /**
   * Websocket connection message event handler. Called if a new message is received through the socket.
   * @param {any} event Contains the event data.
   */
  public onWebSocketMessage = (event: MessageEvent<any>) => {
    let data = JSON.parse(event.data);
    Broker.instance().publish(data.value, data.type);
  };

  /**
   * Websocket connection error event handler.
   * @param {any} event contains the event data.
   */
  private onError(event: any): void {
    console.error(event);
  }
}