import {
  EventSourceMixin, HomeHubBaseClass, SubscribableMixin,
} from 'src/lib/base';

export const kWebSocketMsgTypeServiceNotification = 'SERVICE_NOTIFICATION';
export const kWebSocketMsgTypeStateNotification = 'STATE_NOTIFICATION';

const Base = SubscribableMixin(
  EventSourceMixin(HomeHubBaseClass, ['start', 'stop'])
);

export class BaseConnector extends Base {
  constructor (debug, settings) {
    super(debug, settings);

    this.debug = debug;
    this.settings = settings;
  }
  logDebug (...args) {
    if (this.debug) {
      // eslint-disable-next-line no-console
      console.log(...args);
    }
  }
  start = () => {
  }
  stop = () => {
  }
}

export class HomeHubWebSocket extends BaseConnector {
  constructor (debug, settings) {
    super(debug, settings);

    this.socket = null;
    this.reconnectTimeout = null;
    this.reconnectCounter = 0;
  }
  stopReconnect () {
    if (this.reconnectTimeout) {
      window.clearTimeout(this.reconnectTimeout);
    }

    this.reconnectTimeout = null;
    this.reconnectCounter = 0;
  }
  startReconnect () {
    if (this.reconnectCounter < 30) {
      this.reconnectCounter += 1;
      this.reconnectTimeout = window.setTimeout(
        this.start, 1000
      );
    } else {
      this.stopReconnect();
      throw new Error('HomeHubWebSocket: Reconnect tries limit reached.');
    }
  }
  start = () => {
    this.socket = new WebSocket(this.settings.url, this.settings.protocols);
    this.socket.addEventListener('open', this.onSocketOpen);
    this.socket.addEventListener('close', this.onSocketClose);
    this.socket.addEventListener('message', this.onSocketMessage);
  }
  stop = () => {
    this.socket.close();
  }
  onSocketOpen = () => {
    this.logDebug('HomeHubWebSocket.onSocketOpen()', this.socket.readyState);

    this.stopReconnect();

    this.fireEvent('start');
  }
  onSocketClose = (event) => {
    this.logDebug('HomeHubWebSocket.onSocketClose()', event.code);

    this.startReconnect();

    this.fireEvent('stop');
  }
  onSocketMessage = (event) => {
    let message = null;
    try {
      message = JSON.parse(event.data);
      this.logDebug('HomeHubWebSocket.onSocketMessage()', message);
    } catch (error) {
      console.error(
        'HomeHubWebSocket.onSocketMessage() JSON Parse Error', error
      );
      return;
    }

    this.notify(message);
  }
}
