var Echo = (function () {
  'use strict';

  function _typeof(obj) {
    "@babel/helpers - typeof";

    return _typeof = "function" == typeof Symbol && "symbol" == typeof Symbol.iterator ? function (obj) {
      return typeof obj;
    } : function (obj) {
      return obj && "function" == typeof Symbol && obj.constructor === Symbol && obj !== Symbol.prototype ? "symbol" : typeof obj;
    }, _typeof(obj);
  }

  function _classCallCheck(instance, Constructor) {
    if (!(instance instanceof Constructor)) {
      throw new TypeError("Cannot call a class as a function");
    }
  }

  function _defineProperties(target, props) {
    for (var i = 0; i < props.length; i++) {
      var descriptor = props[i];
      descriptor.enumerable = descriptor.enumerable || false;
      descriptor.configurable = true;
      if ("value" in descriptor) descriptor.writable = true;
      Object.defineProperty(target, descriptor.key, descriptor);
    }
  }

  function _createClass(Constructor, protoProps, staticProps) {
    if (protoProps) _defineProperties(Constructor.prototype, protoProps);
    if (staticProps) _defineProperties(Constructor, staticProps);
    Object.defineProperty(Constructor, "prototype", {
      writable: false
    });
    return Constructor;
  }

  function _extends() {
    _extends = Object.assign || function (target) {
      for (var i = 1; i < arguments.length; i++) {
        var source = arguments[i];

        for (var key in source) {
          if (Object.prototype.hasOwnProperty.call(source, key)) {
            target[key] = source[key];
          }
        }
      }

      return target;
    };

    return _extends.apply(this, arguments);
  }

  function _inherits(subClass, superClass) {
    if (typeof superClass !== "function" && superClass !== null) {
      throw new TypeError("Super expression must either be null or a function");
    }

    subClass.prototype = Object.create(superClass && superClass.prototype, {
      constructor: {
        value: subClass,
        writable: true,
        configurable: true
      }
    });
    Object.defineProperty(subClass, "prototype", {
      writable: false
    });
    if (superClass) _setPrototypeOf(subClass, superClass);
  }

  function _getPrototypeOf(o) {
    _getPrototypeOf = Object.setPrototypeOf ? Object.getPrototypeOf : function _getPrototypeOf(o) {
      return o.__proto__ || Object.getPrototypeOf(o);
    };
    return _getPrototypeOf(o);
  }

  function _setPrototypeOf(o, p) {
    _setPrototypeOf = Object.setPrototypeOf || function _setPrototypeOf(o, p) {
      o.__proto__ = p;
      return o;
    };

    return _setPrototypeOf(o, p);
  }

  function _isNativeReflectConstruct() {
    if (typeof Reflect === "undefined" || !Reflect.construct) return false;
    if (Reflect.construct.sham) return false;
    if (typeof Proxy === "function") return true;

    try {
      Boolean.prototype.valueOf.call(Reflect.construct(Boolean, [], function () {}));
      return true;
    } catch (e) {
      return false;
    }
  }

  function _assertThisInitialized(self) {
    if (self === void 0) {
      throw new ReferenceError("this hasn't been initialised - super() hasn't been called");
    }

    return self;
  }

  function _possibleConstructorReturn(self, call) {
    if (call && (typeof call === "object" || typeof call === "function")) {
      return call;
    } else if (call !== void 0) {
      throw new TypeError("Derived constructors may only return object or undefined");
    }

    return _assertThisInitialized(self);
  }

  function _createSuper(Derived) {
    var hasNativeReflectConstruct = _isNativeReflectConstruct();

    return function _createSuperInternal() {
      var Super = _getPrototypeOf(Derived),
          result;

      if (hasNativeReflectConstruct) {
        var NewTarget = _getPrototypeOf(this).constructor;

        result = Reflect.construct(Super, arguments, NewTarget);
      } else {
        result = Super.apply(this, arguments);
      }

      return _possibleConstructorReturn(this, result);
    };
  }

  /**
   * This class represents a basic channel.
   */
  var Channel = /*#__PURE__*/function () {
    function Channel() {
      _classCallCheck(this, Channel);
    }

    _createClass(Channel, [{
      key: "listenForWhisper",
      value:
      /**
       * Listen for a whisper event on the channel instance.
       */
      function listenForWhisper(event, callback) {
        return this.listen('.client-' + event, callback);
      }
      /**
       * Listen for an event on the channel instance.
       */

    }, {
      key: "notification",
      value: function notification(callback) {
        return this.listen('.Illuminate\\Notifications\\Events\\BroadcastNotificationCreated', callback);
      }
      /**
       * Stop listening for a whisper event on the channel instance.
       */

    }, {
      key: "stopListeningForWhisper",
      value: function stopListeningForWhisper(event, callback) {
        return this.stopListening('.client-' + event, callback);
      }
    }]);

    return Channel;
  }();

  /**
   * Event name formatter
   */
  var EventFormatter = /*#__PURE__*/function () {
    /**
     * Create a new class instance.
     */
    function EventFormatter(namespace) {
      _classCallCheck(this, EventFormatter);

      this.namespace = namespace; //
    }
    /**
     * Format the given event name.
     */


    _createClass(EventFormatter, [{
      key: "format",
      value: function format(event) {
        if (event.charAt(0) === '.' || event.charAt(0) === '\\') {
          return event.substr(1);
        } else if (this.namespace) {
          event = this.namespace + '.' + event;
        }

        return event.replace(/\./g, '\\');
      }
      /**
       * Set the event namespace.
       */

    }, {
      key: "setNamespace",
      value: function setNamespace(value) {
        this.namespace = value;
      }
    }]);

    return EventFormatter;
  }();

  /**
   * This class represents a Pusher channel.
   */

  var PusherChannel = /*#__PURE__*/function (_Channel) {
    _inherits(PusherChannel, _Channel);

    var _super = _createSuper(PusherChannel);

    /**
     * Create a new class instance.
     */
    function PusherChannel(pusher, name, options) {
      var _this;

      _classCallCheck(this, PusherChannel);

      _this = _super.call(this);
      _this.name = name;
      _this.pusher = pusher;
      _this.options = options;
      _this.eventFormatter = new EventFormatter(_this.options.namespace);

      _this.subscribe();

      return _this;
    }
    /**
     * Subscribe to a Pusher channel.
     */


    _createClass(PusherChannel, [{
      key: "subscribe",
      value: function subscribe() {
        this.subscription = this.pusher.subscribe(this.name);
      }
      /**
       * Unsubscribe from a Pusher channel.
       */

    }, {
      key: "unsubscribe",
      value: function unsubscribe() {
        this.pusher.unsubscribe(this.name);
      }
      /**
       * Listen for an event on the channel instance.
       */

    }, {
      key: "listen",
      value: function listen(event, callback) {
        this.on(this.eventFormatter.format(event), callback);
        return this;
      }
      /**
       * Listen for all events on the channel instance.
       */

    }, {
      key: "listenToAll",
      value: function listenToAll(callback) {
        var _this2 = this;

        this.subscription.bind_global(function (event, data) {
          if (event.startsWith('pusher:')) {
            return;
          }

          var namespace = _this2.options.namespace.replace(/\./g, '\\');

          var formattedEvent = event.startsWith(namespace) ? event.substring(namespace.length + 1) : '.' + event;
          callback(formattedEvent, data);
        });
        return this;
      }
      /**
       * Stop listening for an event on the channel instance.
       */

    }, {
      key: "stopListening",
      value: function stopListening(event, callback) {
        if (callback) {
          this.subscription.unbind(this.eventFormatter.format(event), callback);
        } else {
          this.subscription.unbind(this.eventFormatter.format(event));
        }

        return this;
      }
      /**
       * Stop listening for all events on the channel instance.
       */

    }, {
      key: "stopListeningToAll",
      value: function stopListeningToAll(callback) {
        if (callback) {
          this.subscription.unbind_global(callback);
        } else {
          this.subscription.unbind_global();
        }

        return this;
      }
      /**
       * Register a callback to be called anytime a subscription succeeds.
       */

    }, {
      key: "subscribed",
      value: function subscribed(callback) {
        this.on('pusher:subscription_succeeded', function () {
          callback();
        });
        return this;
      }
      /**
       * Register a callback to be called anytime a subscription error occurs.
       */

    }, {
      key: "error",
      value: function error(callback) {
        this.on('pusher:subscription_error', function (status) {
          callback(status);
        });
        return this;
      }
      /**
       * Bind a channel to an event.
       */

    }, {
      key: "on",
      value: function on(event, callback) {
        this.subscription.bind(event, callback);
        return this;
      }
    }]);

    return PusherChannel;
  }(Channel);

  /**
   * This class represents a Pusher private channel.
   */

  var PusherPrivateChannel = /*#__PURE__*/function (_PusherChannel) {
    _inherits(PusherPrivateChannel, _PusherChannel);

    var _super = _createSuper(PusherPrivateChannel);

    function PusherPrivateChannel() {
      _classCallCheck(this, PusherPrivateChannel);

      return _super.apply(this, arguments);
    }

    _createClass(PusherPrivateChannel, [{
      key: "whisper",
      value:
      /**
       * Send a whisper event to other clients in the channel.
       */
      function whisper(eventName, data) {
        this.pusher.channels.channels[this.name].trigger("client-".concat(eventName), data);
        return this;
      }
    }]);

    return PusherPrivateChannel;
  }(PusherChannel);

  /**
   * This class represents a Pusher private channel.
   */

  var PusherEncryptedPrivateChannel = /*#__PURE__*/function (_PusherChannel) {
    _inherits(PusherEncryptedPrivateChannel, _PusherChannel);

    var _super = _createSuper(PusherEncryptedPrivateChannel);

    function PusherEncryptedPrivateChannel() {
      _classCallCheck(this, PusherEncryptedPrivateChannel);

      return _super.apply(this, arguments);
    }

    _createClass(PusherEncryptedPrivateChannel, [{
      key: "whisper",
      value:
      /**
       * Send a whisper event to other clients in the channel.
       */
      function whisper(eventName, data) {
        this.pusher.channels.channels[this.name].trigger("client-".concat(eventName), data);
        return this;
      }
    }]);

    return PusherEncryptedPrivateChannel;
  }(PusherChannel);

  /**
   * This class represents a Pusher presence channel.
   */

  var PusherPresenceChannel = /*#__PURE__*/function (_PusherChannel) {
    _inherits(PusherPresenceChannel, _PusherChannel);

    var _super = _createSuper(PusherPresenceChannel);

    function PusherPresenceChannel() {
      _classCallCheck(this, PusherPresenceChannel);

      return _super.apply(this, arguments);
    }

    _createClass(PusherPresenceChannel, [{
      key: "here",
      value:
      /**
       * Register a callback to be called anytime the member list changes.
       */
      function here(callback) {
        this.on('pusher:subscription_succeeded', function (data) {
          callback(Object.keys(data.members).map(function (k) {
            return data.members[k];
          }));
        });
        return this;
      }
      /**
       * Listen for someone joining the channel.
       */

    }, {
      key: "joining",
      value: function joining(callback) {
        this.on('pusher:member_added', function (member) {
          callback(member.info);
        });
        return this;
      }
      /**
       * Send a whisper event to other clients in the channel.
       */

    }, {
      key: "whisper",
      value: function whisper(eventName, data) {
        this.pusher.channels.channels[this.name].trigger("client-".concat(eventName), data);
        return this;
      }
      /**
       * Listen for someone leaving the channel.
       */

    }, {
      key: "leaving",
      value: function leaving(callback) {
        this.on('pusher:member_removed', function (member) {
          callback(member.info);
        });
        return this;
      }
    }]);

    return PusherPresenceChannel;
  }(PusherChannel);

  /**
   * This class represents a Socket.io channel.
   */

  var SocketIoChannel = /*#__PURE__*/function (_Channel) {
    _inherits(SocketIoChannel, _Channel);

    var _super = _createSuper(SocketIoChannel);

    /**
     * Create a new class instance.
     */
    function SocketIoChannel(socket, name, options) {
      var _this;

      _classCallCheck(this, SocketIoChannel);

      _this = _super.call(this);
      /**
       * The event callbacks applied to the socket.
       */

      _this.events = {};
      /**
       * User supplied callbacks for events on this channel.
       */

      _this.listeners = {};
      _this.name = name;
      _this.socket = socket;
      _this.options = options;
      _this.eventFormatter = new EventFormatter(_this.options.namespace);

      _this.subscribe();

      return _this;
    }
    /**
     * Subscribe to a Socket.io channel.
     */


    _createClass(SocketIoChannel, [{
      key: "subscribe",
      value: function subscribe() {
        this.socket.emit('subscribe', {
          channel: this.name,
          auth: this.options.auth || {}
        });
      }
      /**
       * Unsubscribe from channel and ubind event callbacks.
       */

    }, {
      key: "unsubscribe",
      value: function unsubscribe() {
        this.unbind();
        this.socket.emit('unsubscribe', {
          channel: this.name,
          auth: this.options.auth || {}
        });
      }
      /**
       * Listen for an event on the channel instance.
       */

    }, {
      key: "listen",
      value: function listen(event, callback) {
        this.on(this.eventFormatter.format(event), callback);
        return this;
      }
      /**
       * Stop listening for an event on the channel instance.
       */

    }, {
      key: "stopListening",
      value: function stopListening(event, callback) {
        this.unbindEvent(this.eventFormatter.format(event), callback);
        return this;
      }
      /**
       * Register a callback to be called anytime a subscription succeeds.
       */

    }, {
      key: "subscribed",
      value: function subscribed(callback) {
        this.on('connect', function (socket) {
          callback(socket);
        });
        return this;
      }
      /**
       * Register a callback to be called anytime an error occurs.
       */

    }, {
      key: "error",
      value: function error(callback) {
        return this;
      }
      /**
       * Bind the channel's socket to an event and store the callback.
       */

    }, {
      key: "on",
      value: function on(event, callback) {
        var _this2 = this;

        this.listeners[event] = this.listeners[event] || [];

        if (!this.events[event]) {
          this.events[event] = function (channel, data) {
            if (_this2.name === channel && _this2.listeners[event]) {
              _this2.listeners[event].forEach(function (cb) {
                return cb(data);
              });
            }
          };

          this.socket.on(event, this.events[event]);
        }

        this.listeners[event].push(callback);
        return this;
      }
      /**
       * Unbind the channel's socket from all stored event callbacks.
       */

    }, {
      key: "unbind",
      value: function unbind() {
        var _this3 = this;

        Object.keys(this.events).forEach(function (event) {
          _this3.unbindEvent(event);
        });
      }
      /**
       * Unbind the listeners for the given event.
       */

    }, {
      key: "unbindEvent",
      value: function unbindEvent(event, callback) {
        this.listeners[event] = this.listeners[event] || [];

        if (callback) {
          this.listeners[event] = this.listeners[event].filter(function (cb) {
            return cb !== callback;
          });
        }

        if (!callback || this.listeners[event].length === 0) {
          if (this.events[event]) {
            this.socket.removeListener(event, this.events[event]);
            delete this.events[event];
          }

          delete this.listeners[event];
        }
      }
    }]);

    return SocketIoChannel;
  }(Channel);

  /**
   * This class represents a Socket.io private channel.
   */

  var SocketIoPrivateChannel = /*#__PURE__*/function (_SocketIoChannel) {
    _inherits(SocketIoPrivateChannel, _SocketIoChannel);

    var _super = _createSuper(SocketIoPrivateChannel);

    function SocketIoPrivateChannel() {
      _classCallCheck(this, SocketIoPrivateChannel);

      return _super.apply(this, arguments);
    }

    _createClass(SocketIoPrivateChannel, [{
      key: "whisper",
      value:
      /**
       * Send a whisper event to other clients in the channel.
       */
      function whisper(eventName, data) {
        this.socket.emit('client event', {
          channel: this.name,
          event: "client-".concat(eventName),
          data: data
        });
        return this;
      }
    }]);

    return SocketIoPrivateChannel;
  }(SocketIoChannel);

  /**
   * This class represents a Socket.io presence channel.
   */

  var SocketIoPresenceChannel = /*#__PURE__*/function (_SocketIoPrivateChann) {
    _inherits(SocketIoPresenceChannel, _SocketIoPrivateChann);

    var _super = _createSuper(SocketIoPresenceChannel);

    function SocketIoPresenceChannel() {
      _classCallCheck(this, SocketIoPresenceChannel);

      return _super.apply(this, arguments);
    }

    _createClass(SocketIoPresenceChannel, [{
      key: "here",
      value:
      /**
       * Register a callback to be called anytime the member list changes.
       */
      function here(callback) {
        this.on('presence:subscribed', function (members) {
          callback(members.map(function (m) {
            return m.user_info;
          }));
        });
        return this;
      }
      /**
       * Listen for someone joining the channel.
       */

    }, {
      key: "joining",
      value: function joining(callback) {
        this.on('presence:joining', function (member) {
          return callback(member.user_info);
        });
        return this;
      }
      /**
       * Send a whisper event to other clients in the channel.
       */

    }, {
      key: "whisper",
      value: function whisper(eventName, data) {
        this.socket.emit('client event', {
          channel: this.name,
          event: "client-".concat(eventName),
          data: data
        });
        return this;
      }
      /**
       * Listen for someone leaving the channel.
       */

    }, {
      key: "leaving",
      value: function leaving(callback) {
        this.on('presence:leaving', function (member) {
          return callback(member.user_info);
        });
        return this;
      }
    }]);

    return SocketIoPresenceChannel;
  }(SocketIoPrivateChannel);

  /**
   * This class represents a null channel.
   */

  var NullChannel = /*#__PURE__*/function (_Channel) {
    _inherits(NullChannel, _Channel);

    var _super = _createSuper(NullChannel);

    function NullChannel() {
      _classCallCheck(this, NullChannel);

      return _super.apply(this, arguments);
    }

    _createClass(NullChannel, [{
      key: "subscribe",
      value:
      /**
       * Subscribe to a channel.
       */
      function subscribe() {//
      }
      /**
       * Unsubscribe from a channel.
       */

    }, {
      key: "unsubscribe",
      value: function unsubscribe() {//
      }
      /**
       * Listen for an event on the channel instance.
       */

    }, {
      key: "listen",
      value: function listen(event, callback) {
        return this;
      }
      /**
       * Listen for all events on the channel instance.
       */

    }, {
      key: "listenToAll",
      value: function listenToAll(callback) {
        return this;
      }
      /**
       * Stop listening for an event on the channel instance.
       */

    }, {
      key: "stopListening",
      value: function stopListening(event, callback) {
        return this;
      }
      /**
       * Register a callback to be called anytime a subscription succeeds.
       */

    }, {
      key: "subscribed",
      value: function subscribed(callback) {
        return this;
      }
      /**
       * Register a callback to be called anytime an error occurs.
       */

    }, {
      key: "error",
      value: function error(callback) {
        return this;
      }
      /**
       * Bind a channel to an event.
       */

    }, {
      key: "on",
      value: function on(event, callback) {
        return this;
      }
    }]);

    return NullChannel;
  }(Channel);

  /**
   * This class represents a null private channel.
   */

  var NullPrivateChannel = /*#__PURE__*/function (_NullChannel) {
    _inherits(NullPrivateChannel, _NullChannel);

    var _super = _createSuper(NullPrivateChannel);

    function NullPrivateChannel() {
      _classCallCheck(this, NullPrivateChannel);

      return _super.apply(this, arguments);
    }

    _createClass(NullPrivateChannel, [{
      key: "whisper",
      value:
      /**
       * Send a whisper event to other clients in the channel.
       */
      function whisper(eventName, data) {
        return this;
      }
    }]);

    return NullPrivateChannel;
  }(NullChannel);

  /**
   * This class represents a null presence channel.
   */

  var NullPresenceChannel = /*#__PURE__*/function (_NullChannel) {
    _inherits(NullPresenceChannel, _NullChannel);

    var _super = _createSuper(NullPresenceChannel);

    function NullPresenceChannel() {
      _classCallCheck(this, NullPresenceChannel);

      return _super.apply(this, arguments);
    }

    _createClass(NullPresenceChannel, [{
      key: "here",
      value:
      /**
       * Register a callback to be called anytime the member list changes.
       */
      function here(callback) {
        return this;
      }
      /**
       * Listen for someone joining the channel.
       */

    }, {
      key: "joining",
      value: function joining(callback) {
        return this;
      }
      /**
       * Send a whisper event to other clients in the channel.
       */

    }, {
      key: "whisper",
      value: function whisper(eventName, data) {
        return this;
      }
      /**
       * Listen for someone leaving the channel.
       */

    }, {
      key: "leaving",
      value: function leaving(callback) {
        return this;
      }
    }]);

    return NullPresenceChannel;
  }(NullChannel);

  var Connector = /*#__PURE__*/function () {
    /**
     * Create a new class instance.
     */
    function Connector(options) {
      _classCallCheck(this, Connector);

      /**
       * Default connector options.
       */
      this._defaultOptions = {
        auth: {
          headers: {}
        },
        authEndpoint: '/broadcasting/auth',
        userAuthentication: {
          endpoint: '/broadcasting/user-auth',
          headers: {}
        },
        broadcaster: 'pusher',
        csrfToken: null,
        bearerToken: null,
        host: null,
        key: null,
        namespace: 'App.Events'
      };
      this.setOptions(options);
      this.connect();
    }
    /**
     * Merge the custom options with the defaults.
     */


    _createClass(Connector, [{
      key: "setOptions",
      value: function setOptions(options) {
        this.options = _extends(this._defaultOptions, options);
        var token = this.csrfToken();

        if (token) {
          this.options.auth.headers['X-CSRF-TOKEN'] = token;
          this.options.userAuthentication.headers['X-CSRF-TOKEN'] = token;
        }

        token = this.options.bearerToken;

        if (token) {
          this.options.auth.headers['Authorization'] = 'Bearer ' + token;
          this.options.userAuthentication.headers['Authorization'] = 'Bearer ' + token;
        }

        return options;
      }
      /**
       * Extract the CSRF token from the page.
       */

    }, {
      key: "csrfToken",
      value: function csrfToken() {
        var selector;

        if (typeof window !== 'undefined' && window['Laravel'] && window['Laravel'].csrfToken) {
          return window['Laravel'].csrfToken;
        } else if (this.options.csrfToken) {
          return this.options.csrfToken;
        } else if (typeof document !== 'undefined' && typeof document.querySelector === 'function' && (selector = document.querySelector('meta[name="csrf-token"]'))) {
          return selector.getAttribute('content');
        }

        return null;
      }
    }]);

    return Connector;
  }();

  /**
   * This class creates a connector to Pusher.
   */

  var PusherConnector = /*#__PURE__*/function (_Connector) {
    _inherits(PusherConnector, _Connector);

    var _super = _createSuper(PusherConnector);

    function PusherConnector() {
      var _this;

      _classCallCheck(this, PusherConnector);

      _this = _super.apply(this, arguments);
      /**
       * All of the subscribed channel names.
       */

      _this.channels = {};
      return _this;
    }
    /**
     * Create a fresh Pusher connection.
     */


    _createClass(PusherConnector, [{
      key: "connect",
      value: function connect() {
        if (typeof this.options.client !== 'undefined') {
          this.pusher = this.options.client;
        } else if (this.options.Pusher) {
          this.pusher = new this.options.Pusher(this.options.key, this.options);
        } else {
          this.pusher = new Pusher(this.options.key, this.options);
        }
      }
      /**
       * Sign in the user via Pusher user authentication (https://pusher.com/docs/channels/using_channels/user-authentication/).
       */

    }, {
      key: "signin",
      value: function signin() {
        this.pusher.signin();
      }
      /**
       * Listen for an event on a channel instance.
       */

    }, {
      key: "listen",
      value: function listen(name, event, callback) {
        return this.channel(name).listen(event, callback);
      }
      /**
       * Get a channel instance by name.
       */

    }, {
      key: "channel",
      value: function channel(name) {
        if (!this.channels[name]) {
          this.channels[name] = new PusherChannel(this.pusher, name, this.options);
        }

        return this.channels[name];
      }
      /**
       * Get a private channel instance by name.
       */

    }, {
      key: "privateChannel",
      value: function privateChannel(name) {
        if (!this.channels['private-' + name]) {
          this.channels['private-' + name] = new PusherPrivateChannel(this.pusher, 'private-' + name, this.options);
        }

        return this.channels['private-' + name];
      }
      /**
       * Get a private encrypted channel instance by name.
       */

    }, {
      key: "encryptedPrivateChannel",
      value: function encryptedPrivateChannel(name) {
        if (!this.channels['private-encrypted-' + name]) {
          this.channels['private-encrypted-' + name] = new PusherEncryptedPrivateChannel(this.pusher, 'private-encrypted-' + name, this.options);
        }

        return this.channels['private-encrypted-' + name];
      }
      /**
       * Get a presence channel instance by name.
       */

    }, {
      key: "presenceChannel",
      value: function presenceChannel(name) {
        if (!this.channels['presence-' + name]) {
          this.channels['presence-' + name] = new PusherPresenceChannel(this.pusher, 'presence-' + name, this.options);
        }

        return this.channels['presence-' + name];
      }
      /**
       * Leave the given channel, as well as its private and presence variants.
       */

    }, {
      key: "leave",
      value: function leave(name) {
        var _this2 = this;

        var channels = [name, 'private-' + name, 'private-encrypted-' + name, 'presence-' + name];
        channels.forEach(function (name, index) {
          _this2.leaveChannel(name);
        });
      }
      /**
       * Leave the given channel.
       */

    }, {
      key: "leaveChannel",
      value: function leaveChannel(name) {
        if (this.channels[name]) {
          this.channels[name].unsubscribe();
          delete this.channels[name];
        }
      }
      /**
       * Get the socket ID for the connection.
       */

    }, {
      key: "socketId",
      value: function socketId() {
        return this.pusher.connection.socket_id;
      }
      /**
       * Disconnect Pusher connection.
       */

    }, {
      key: "disconnect",
      value: function disconnect() {
        this.pusher.disconnect();
      }
    }]);

    return PusherConnector;
  }(Connector);

  /**
   * This class creates a connnector to a Socket.io server.
   */

  var SocketIoConnector = /*#__PURE__*/function (_Connector) {
    _inherits(SocketIoConnector, _Connector);

    var _super = _createSuper(SocketIoConnector);

    function SocketIoConnector() {
      var _this;

      _classCallCheck(this, SocketIoConnector);

      _this = _super.apply(this, arguments);
      /**
       * All of the subscribed channel names.
       */

      _this.channels = {};
      return _this;
    }
    /**
     * Create a fresh Socket.io connection.
     */


    _createClass(SocketIoConnector, [{
      key: "connect",
      value: function connect() {
        var _this2 = this;

        var io = this.getSocketIO();
        this.socket = io(this.options.host, this.options);
        this.socket.on('reconnect', function () {
          Object.values(_this2.channels).forEach(function (channel) {
            channel.subscribe();
          });
        });
        return this.socket;
      }
      /**
       * Get socket.io module from global scope or options.
       */

    }, {
      key: "getSocketIO",
      value: function getSocketIO() {
        if (typeof this.options.client !== 'undefined') {
          return this.options.client;
        }

        if (typeof io !== 'undefined') {
          return io;
        }

        throw new Error('Socket.io client not found. Should be globally available or passed via options.client');
      }
      /**
       * Listen for an event on a channel instance.
       */

    }, {
      key: "listen",
      value: function listen(name, event, callback) {
        return this.channel(name).listen(event, callback);
      }
      /**
       * Get a channel instance by name.
       */

    }, {
      key: "channel",
      value: function channel(name) {
        if (!this.channels[name]) {
          this.channels[name] = new SocketIoChannel(this.socket, name, this.options);
        }

        return this.channels[name];
      }
      /**
       * Get a private channel instance by name.
       */

    }, {
      key: "privateChannel",
      value: function privateChannel(name) {
        if (!this.channels['private-' + name]) {
          this.channels['private-' + name] = new SocketIoPrivateChannel(this.socket, 'private-' + name, this.options);
        }

        return this.channels['private-' + name];
      }
      /**
       * Get a presence channel instance by name.
       */

    }, {
      key: "presenceChannel",
      value: function presenceChannel(name) {
        if (!this.channels['presence-' + name]) {
          this.channels['presence-' + name] = new SocketIoPresenceChannel(this.socket, 'presence-' + name, this.options);
        }

        return this.channels['presence-' + name];
      }
      /**
       * Leave the given channel, as well as its private and presence variants.
       */

    }, {
      key: "leave",
      value: function leave(name) {
        var _this3 = this;

        var channels = [name, 'private-' + name, 'presence-' + name];
        channels.forEach(function (name) {
          _this3.leaveChannel(name);
        });
      }
      /**
       * Leave the given channel.
       */

    }, {
      key: "leaveChannel",
      value: function leaveChannel(name) {
        if (this.channels[name]) {
          this.channels[name].unsubscribe();
          delete this.channels[name];
        }
      }
      /**
       * Get the socket ID for the connection.
       */

    }, {
      key: "socketId",
      value: function socketId() {
        return this.socket.id;
      }
      /**
       * Disconnect Socketio connection.
       */

    }, {
      key: "disconnect",
      value: function disconnect() {
        this.socket.disconnect();
      }
    }]);

    return SocketIoConnector;
  }(Connector);

  /**
   * This class creates a null connector.
   */

  var NullConnector = /*#__PURE__*/function (_Connector) {
    _inherits(NullConnector, _Connector);

    var _super = _createSuper(NullConnector);

    function NullConnector() {
      var _this;

      _classCallCheck(this, NullConnector);

      _this = _super.apply(this, arguments);
      /**
       * All of the subscribed channel names.
       */

      _this.channels = {};
      return _this;
    }
    /**
     * Create a fresh connection.
     */


    _createClass(NullConnector, [{
      key: "connect",
      value: function connect() {//
      }
      /**
       * Listen for an event on a channel instance.
       */

    }, {
      key: "listen",
      value: function listen(name, event, callback) {
        return new NullChannel();
      }
      /**
       * Get a channel instance by name.
       */

    }, {
      key: "channel",
      value: function channel(name) {
        return new NullChannel();
      }
      /**
       * Get a private channel instance by name.
       */

    }, {
      key: "privateChannel",
      value: function privateChannel(name) {
        return new NullPrivateChannel();
      }
      /**
       * Get a private encrypted channel instance by name.
       */

    }, {
      key: "encryptedPrivateChannel",
      value: function encryptedPrivateChannel(name) {
        return new NullPrivateChannel();
      }
      /**
       * Get a presence channel instance by name.
       */

    }, {
      key: "presenceChannel",
      value: function presenceChannel(name) {
        return new NullPresenceChannel();
      }
      /**
       * Leave the given channel, as well as its private and presence variants.
       */

    }, {
      key: "leave",
      value: function leave(name) {//
      }
      /**
       * Leave the given channel.
       */

    }, {
      key: "leaveChannel",
      value: function leaveChannel(name) {//
      }
      /**
       * Get the socket ID for the connection.
       */

    }, {
      key: "socketId",
      value: function socketId() {
        return 'fake-socket-id';
      }
      /**
       * Disconnect the connection.
       */

    }, {
      key: "disconnect",
      value: function disconnect() {//
      }
    }]);

    return NullConnector;
  }(Connector);

  /**
   * This class is the primary API for interacting with broadcasting.
   */

  var Echo = /*#__PURE__*/function () {
    /**
     * Create a new class instance.
     */
    function Echo(options) {
      _classCallCheck(this, Echo);

      this.options = options;
      this.connect();

      if (!this.options.withoutInterceptors) {
        this.registerInterceptors();
      }
    }
    /**
     * Get a channel instance by name.
     */


    _createClass(Echo, [{
      key: "channel",
      value: function channel(_channel) {
        return this.connector.channel(_channel);
      }
      /**
       * Create a new connection.
       */

    }, {
      key: "connect",
      value: function connect() {
        if (this.options.broadcaster == 'pusher') {
          this.connector = new PusherConnector(this.options);
        } else if (this.options.broadcaster == 'socket.io') {
          this.connector = new SocketIoConnector(this.options);
        } else if (this.options.broadcaster == 'null') {
          this.connector = new NullConnector(this.options);
        } else if (typeof this.options.broadcaster == 'function') {
          this.connector = new this.options.broadcaster(this.options);
        }
      }
      /**
       * Disconnect from the Echo server.
       */

    }, {
      key: "disconnect",
      value: function disconnect() {
        this.connector.disconnect();
      }
      /**
       * Get a presence channel instance by name.
       */

    }, {
      key: "join",
      value: function join(channel) {
        return this.connector.presenceChannel(channel);
      }
      /**
       * Leave the given channel, as well as its private and presence variants.
       */

    }, {
      key: "leave",
      value: function leave(channel) {
        this.connector.leave(channel);
      }
      /**
       * Leave the given channel.
       */

    }, {
      key: "leaveChannel",
      value: function leaveChannel(channel) {
        this.connector.leaveChannel(channel);
      }
      /**
       * Leave all channels.
       */

    }, {
      key: "leaveAllChannels",
      value: function leaveAllChannels() {
        for (var channel in this.connector.channels) {
          this.leaveChannel(channel);
        }
      }
      /**
       * Listen for an event on a channel instance.
       */

    }, {
      key: "listen",
      value: function listen(channel, event, callback) {
        return this.connector.listen(channel, event, callback);
      }
      /**
       * Get a private channel instance by name.
       */

    }, {
      key: "private",
      value: function _private(channel) {
        return this.connector.privateChannel(channel);
      }
      /**
       * Get a private encrypted channel instance by name.
       */

    }, {
      key: "encryptedPrivate",
      value: function encryptedPrivate(channel) {
        return this.connector.encryptedPrivateChannel(channel);
      }
      /**
       * Get the Socket ID for the connection.
       */

    }, {
      key: "socketId",
      value: function socketId() {
        return this.connector.socketId();
      }
      /**
       * Register 3rd party request interceptiors. These are used to automatically
       * send a connections socket id to a Laravel app with a X-Socket-Id header.
       */

    }, {
      key: "registerInterceptors",
      value: function registerInterceptors() {
        if (typeof Vue === 'function' && Vue.http) {
          this.registerVueRequestInterceptor();
        }

        if (typeof axios === 'function') {
          this.registerAxiosRequestInterceptor();
        }

        if (typeof jQuery === 'function') {
          this.registerjQueryAjaxSetup();
        }

        if ((typeof Turbo === "undefined" ? "undefined" : _typeof(Turbo)) === 'object') {
          this.registerTurboRequestInterceptor();
        }
      }
      /**
       * Register a Vue HTTP interceptor to add the X-Socket-ID header.
       */

    }, {
      key: "registerVueRequestInterceptor",
      value: function registerVueRequestInterceptor() {
        var _this = this;

        Vue.http.interceptors.push(function (request, next) {
          if (_this.socketId()) {
            request.headers.set('X-Socket-ID', _this.socketId());
          }

          next();
        });
      }
      /**
       * Register an Axios HTTP interceptor to add the X-Socket-ID header.
       */

    }, {
      key: "registerAxiosRequestInterceptor",
      value: function registerAxiosRequestInterceptor() {
        var _this2 = this;

        axios.interceptors.request.use(function (config) {
          if (_this2.socketId()) {
            config.headers['X-Socket-Id'] = _this2.socketId();
          }

          return config;
        });
      }
      /**
       * Register jQuery AjaxPrefilter to add the X-Socket-ID header.
       */

    }, {
      key: "registerjQueryAjaxSetup",
      value: function registerjQueryAjaxSetup() {
        var _this3 = this;

        if (typeof jQuery.ajax != 'undefined') {
          jQuery.ajaxPrefilter(function (options, originalOptions, xhr) {
            if (_this3.socketId()) {
              xhr.setRequestHeader('X-Socket-Id', _this3.socketId());
            }
          });
        }
      }
      /**
       * Register the Turbo Request interceptor to add the X-Socket-ID header.
       */

    }, {
      key: "registerTurboRequestInterceptor",
      value: function registerTurboRequestInterceptor() {
        var _this4 = this;

        document.addEventListener('turbo:before-fetch-request', function (event) {
          event.detail.fetchOptions.headers['X-Socket-Id'] = _this4.socketId();
        });
      }
    }]);

    return Echo;
  }();

  return Echo;

})();
