"use strict";

Object.defineProperty(exports, "__esModule", {
  value: true
});
exports.wireToTabEvents = wireToTabEvents;
exports.wireToStandardEvents = wireToStandardEvents;
exports.eventBus = exports.default = void 0;

var _events = require("events");

var _command = require("../models/command");

var _tab = require("../webapp/tab");

/*
 * Copyright 2017 IBM Corporation
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 * http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

/* eslint-disable no-dupe-class-members */
const eventChannelUnsafe = new _events.EventEmitter();
eventChannelUnsafe.setMaxListeners(100);
var _default = eventChannelUnsafe;
exports.default = _default;

class EventBusBase {
  constructor() {
    const eventBus = new _events.EventEmitter();
    eventBus.setMaxListeners(100);
    this.eventBus = eventBus;
  }

}

class WriteEventBus extends EventBusBase {
  emit(channel, args) {
    return this.eventBus.emit(channel, args);
  }

  emitCommandEvent(which, event) {
    this.eventBus.emit(`/command/${which}`, event);

    if (event.execType !== _command.ExecType.Nested) {
      this.eventBus.emit(`/command/${which}/fromuser`, event);
      this.eventBus.emit(`/command/${which}/fromuser/${event.tab.uuid}`, event);
      const primary = (0, _tab.getPrimaryTabId)(event.tab);

      if (event.tab.uuid !== primary) {
        this.eventBus.emit(`/command/${which}/fromuser/${primary}`, event);
      }

      this.eventBus.emit(`/command/${which}/fromuser/${primary}/type/${event.execType}`, event);
    }
  }

  emitCommandStart(event) {
    this.emitCommandEvent('start', event);
  }

  emitCommandComplete(event) {
    this.emitCommandEvent('complete', event);

    if (event.execType !== _command.ExecType.Nested) {
      this.eventBus.emit(`/command/complete/fromuser/${event.responseType}`, event);
      this.eventBus.emit(`/command/complete/fromuser/${event.responseType}/${event.tab.uuid}`, event);
      const primary = (0, _tab.getPrimaryTabId)(event.tab);

      if (primary !== event.tab.uuid) {
        this.eventBus.emit(`/command/complete/fromuser/${event.responseType}/${primary}`, event);
      }
    }
  }

  emitWithTabId(channel, tabId, tab) {
    this.eventBus.emit(`${channel}/${tabId}`, tabId, tab);
  }

}

class ReadEventBus extends WriteEventBus {
  on(channel, listener) {
    return this.eventBus.on(channel, listener);
  }

  onCommand(which, splitId, splitHandler, tabId, tabHandler = splitHandler) {
    this.eventBus.on(`/command/${which}/fromuser/${splitId}`, splitHandler);

    if (tabId) {
      this.eventBus.on(`/command/${which}/fromuser/${tabId}/type/${_command.ExecType.ClickHandler}`, tabHandler);
    }
  }

  offCommand(which, splitId, splitHandler, tabId, tabHandler = splitHandler) {
    this.eventBus.off(`/command/${which}/fromuser/${splitId}`, splitHandler);

    if (tabId) {
      this.eventBus.off(`/command/${which}/fromuser/${tabId}/type/${_command.ExecType.ClickHandler}`, tabHandler);
    }
  }

  onAnyCommandStart(handler) {
    this.eventBus.on('/command/start/fromuser', handler);
  }

  offAnyCommandStart(handler) {
    this.eventBus.on('/command/start/fromuser', handler);
  }

  onAnyCommandComplete(handler) {
    this.eventBus.on('/command/complete/fromuser', handler);
  }

  offAnyCommandComplete(handler) {
    this.eventBus.on('/command/complete/fromuser', handler);
  }

  onCommandStart(splitId, splitHandler, tabId, tabHandler = splitHandler) {
    this.onCommand('start', splitId, splitHandler, tabId, tabHandler);
  }

  onceCommandStarts(tabId, handler) {
    this.eventBus.once(`/command/start/fromuser/${tabId}`, handler);
  }

  onResponseType(responseType, splitId, splitHandler, tabId, tabHandler = splitHandler) {
    this.eventBus.on(`/command/complete/fromuser/${responseType}/${splitId}`, splitHandler);

    if (tabId) {
      this.eventBus.on(`/command/complete/fromuser/${responseType}/${tabId}`, tabHandler);
    }
  }

  offResponseType(responseType, splitId, splitHandler, tabId, tabHandler = splitHandler) {
    this.eventBus.off(`/command/complete/fromuser/${responseType}/${splitId}`, splitHandler);

    if (tabId) {
      this.eventBus.off(`/command/complete/fromuser/${responseType}/${tabId}`, tabHandler);
    }
  }

  onScalarResponse(splitId, splitHandler, tabId, tabHandler = splitHandler) {
    this.onResponseType('ScalarResponse', splitId, splitHandler, tabId, tabHandler);
  }

  offScalarResponse(splitId, splitHandler, tabId, tabHandler = splitHandler) {
    this.offResponseType('ScalarResponse', splitId, splitHandler, tabId, tabHandler);
  }

  onMultiModalResponse(tabId, handler) {
    this.onResponseType('MultiModalResponse', tabId, handler);
  }

  offMultiModalResponse(tabId, handler) {
    this.offResponseType('MultiModalResponse', tabId, handler);
  }

  onNavResponse(tabId, handler) {
    this.onResponseType('NavResponse', tabId, handler);
  }

  offNavResponse(tabId, handler) {
    this.offResponseType('NavResponse', tabId, handler);
  }

  onCommandComplete(splitId, splitHandler, tabId, tabHandler = splitHandler) {
    this.onCommand('complete', splitId, splitHandler, tabId, tabHandler);
  }

  offCommandStart(splitId, splitHandler, tabId, tabHandler = splitHandler) {
    this.offCommand('start', splitId, splitHandler, tabId, tabHandler);
  }

  offCommandComplete(splitId, splitHandler, tabId, tabHandler = splitHandler) {
    this.offCommand('complete', splitId, splitHandler, tabId, tabHandler);
  }

  onWithTabId(channel, tabId, listener) {
    this.eventBus.on(`${channel}/${tabId}`, listener);
  }

  offWithTabId(channel, tabId, listener) {
    this.eventBus.off(`${channel}/${tabId}`, listener);
  }

  onceWithTabId(channel, tabId, listener) {
    this.eventBus.once(`${channel}/${tabId}`, listener);
  }

  once(channel, listener) {
    return this.eventBus.once(channel, listener);
  }

}

class EventBus extends ReadEventBus {}

const eventBus = new EventBus();
/**
 * Hook an event listener up to tab events.
 *
 */

exports.eventBus = eventBus;

function wireToTabEvents(listener) {
  eventBus.on('/tab/new', listener);
  eventBus.on('/tab/switch/request', listener);
}
/**
 * Hook an event listener up to the family of standard user
 * interaction events.
 *
 */


function wireToStandardEvents(listener) {
  wireToTabEvents(listener);
  eventBus.onAnyCommandComplete(() => listener());
}