"use strict";

var _keys = require("babel-runtime/core-js/object/keys");

var _keys2 = _interopRequireDefault(_keys);

var _classCallCheck2 = require("babel-runtime/helpers/classCallCheck");

var _classCallCheck3 = _interopRequireDefault(_classCallCheck2);

var _createClass2 = require("babel-runtime/helpers/createClass");

var _createClass3 = _interopRequireDefault(_createClass2);

function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }

var uuid = require("uuid");
var CHANNEL_MODE = require("./enum").CHANNEL_MODE;
var tools = require("../tools");

var Channel = function () {
  function Channel(channelId, mode, enableMulticast) {
    (0, _classCallCheck3.default)(this, Channel);

    this.hubMap = {};
    this.mode = mode;
    this.id = channelId || uuid();
    this.cache = [];
    this.enableMulticast = enableMulticast;
  }

  (0, _createClass3.default)(Channel, [{
    key: "getTerminal",
    value: function getTerminal(hubId) {
      return this.hubMap[hubId];
    }
  }, {
    key: "findAll",
    value: function findAll() {
      var _this = this;

      return (0, _keys2.default)(this.hubMap).map(function (hid) {
        return {
          hubId: hid,
          terminalId: _this.hubMap[hid]
        };
      });
    }
  }, {
    key: "findOthers",
    value: function findOthers(hubId, terminalId, toHubId) {
      var _this2 = this;

      if (hubId === toHubId) {
        throw new Error("hubId must be different from toHubId");
      } else if (!this.has(hubId, terminalId) && !toHubId) {
        throw new Error("terminal [" + hubId + "." + (terminalId || "*") + "] is not in this chanel !");
      } else {
        var keys = (0, _keys2.default)(this.hubMap);
        if (keys.length > 2 && !this.enableMulticast && !toHubId) {
          // channel中有超过三个hub的时候则默认不支持多播
          return [];
        }
        return keys.filter(function (hid) {
          return hid !== hubId && (!toHubId || tools.matchHubId(toHubId, hid));
        }).map(function (hid) {
          return { hubId: hid, terminalId: _this2.hubMap[hid] };
        });
      }
    }
  }, {
    key: "pushCache",
    value: function pushCache(message) {
      this.cache.push(message);
    }
  }, {
    key: "has",
    value: function has(hubId, terminalId) {
      return this.hubMap[hubId] && (!terminalId || this.hubMap[hubId].indexOf(terminalId) >= 0);
    }
  }, {
    key: "getCache",
    value: function getCache(hubId) {
      var hit = [];
      var notHit = [];
      this.cache.forEach(function (c) {
        if (c._to.length > 0) {
          if (c._from.hubId !== hubId && (!c._to[0].hubId || tools.matchHubId(c._to[0].hubId, hubId))) {
            hit.push(c);
          } else {
            notHit.push(c);
          }
        }
      });
      if (hit.length > 0) {
        this.cache = notHit;
      }
      return hit;
    }
  }, {
    key: "join",
    value: function join(hubId, terminalId, forced) {
      // change: forced can be removed
      // cause the hubMap should be {[key:string]: string[]}
      if (this.hubMap[hubId]) {
        if (forced) {
          this.hubMap[hubId] = [terminalId];
        } else {
          if (this.hubMap[hubId].indexOf(terminalId) === -1) {
            this.hubMap[hubId].push(terminalId);
          } else {
            this.hubMap[hubId] = [terminalId];
          }
        }
      } else {
        var hubIds = (0, _keys2.default)(this.hubMap);
        if (this.mode === CHANNEL_MODE.P2P && hubIds.length >= 2) {
          throw new Error("A channel can just link two hub in p2p mode");
        }
        this.hubMap[hubId] = [terminalId];
      }
    }
  }, {
    key: "leave",
    value: function leave(hubId, terminalId) {
      if (this.has(hubId, terminalId) && Array.isArray(this.hubMap[hubId])) {
        this.cache = this.cache.filter(function (c) {
          return c.hubId !== hubId || terminalId && c.terminalId !== terminalId;
        });
        var index = this.hubMap[hubId].indexOf(terminalId);
        if (index) {
          this.hubMap[hubId].splice(index, 1);
        }
      }
    }
  }]);
  return Channel;
}();

module.exports = Channel;