text: 'use strict';
  
  Object.defineProperty(exports, "__esModule", {
    value: true
  });
  exports.default = undefined;
  
  var _getIterator2 = require('babel-runtime/core-js/get-iterator');
  
  var _getIterator3 = _interopRequireDefault(_getIterator2);
  
  var _keys = require('babel-runtime/core-js/object/keys');
  
  var _keys2 = _interopRequireDefault(_keys);
  
  var _promise = require('babel-runtime/core-js/promise');
  
  var _promise2 = _interopRequireDefault(_promise);
  
  var _stringify = require('babel-runtime/core-js/json/stringify');
  
  var _stringify2 = _interopRequireDefault(_stringify);
  
  var _getPrototypeOf = require('babel-runtime/core-js/object/get-prototype-of');
  
  var _getPrototypeOf2 = _interopRequireDefault(_getPrototypeOf);
  
  var _classCallCheck2 = require('babel-runtime/helpers/classCallCheck');
  
  var _classCallCheck3 = _interopRequireDefault(_classCallCheck2);
  
  var _possibleConstructorReturn2 = require('babel-runtime/helpers/possibleConstructorReturn');
  
  var _possibleConstructorReturn3 = _interopRequireDefault(_possibleConstructorReturn2);
  
  var _inherits2 = require('babel-runtime/helpers/inherits');
  
  var _inherits3 = _interopRequireDefault(_inherits2);
  
  var _webexCore = require('@webex/webex-core');
  
  var _loggerProxy = require('../common/logs/logger-proxy');
  
  var _loggerProxy2 = _interopRequireDefault(_loggerProxy);
  
  var _peerConnectionManager = require('../peer-connection-manager');
  
  var _peerConnectionManager2 = _interopRequireDefault(_peerConnectionManager);
  
  var _util = require('../media/util');
  
  var _util2 = _interopRequireDefault(_util);
  
  var _constants = require('../constants');
  
  var _request = require('./request');
  
  var _request2 = _interopRequireDefault(_request);
  
  function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
  
  /**
   * @class Reachability
   * @export
   */
  
  /*!
   * Copyright (c) 2015-2019 Cisco Systems, Inc. See LICENSE file.
   */
  
  /* globals window */
  var Reachability = function (_StatelessWebexPlugin) {
    (0, _inherits3.default)(Reachability, _StatelessWebexPlugin);
  
    function Reachability(attrs, options) {
      (0, _classCallCheck3.default)(this, Reachability);
  
      /**
       * internal request object for the server
       * @instance
       * @type {Array}
       * @private
       * @memberof Reachability
       */
      var _this = (0, _possibleConstructorReturn3.default)(this, (Reachability.__proto__ || (0, _getPrototypeOf2.default)(Reachability)).call(this, {}, options));
  
      _this.namespace = _constants.MEETINGS;
  
      _this.setup = function () {
        _this.processedClusterResults = [];
        _this.peerConnectionMap = {};
      };
  
      _this.gatherReachability = function () {
        _this.setup();
        // Reset reachability result to empty to ensure no stale data
        try {
          window.localStorage.setItem(_constants.REACHABILITY.localStorage, (0, _stringify2.default)({}));
  
          // Get clusters from Orpheus
          return _this.reachabilityRequest.getClusters().then(function (clusters) {
            return (
              // Perform Reachability Check
              _this.performReachabilityCheck(clusters).then(function (response) {
                window.localStorage.setItem(_constants.REACHABILITY.localStorage, (0, _stringify2.default)(response));
  
                return response;
              })
            );
          }).catch(function (error) {
            _loggerProxy2.default.logger.error('Reachability->gatherReachability#Error in calling getClusters(): ' + error);
  
            return {};
          });
        } catch (error) {
          _loggerProxy2.default.logger.error('Reachability->gatherReachability#Error in accessing LocalStorage: ' + error);
  
          return {};
        }
      };
  
      _this.performReachabilityCheck = function (clusterList) {
        if (!clusterList || !clusterList.length) {
          return _promise2.default.resolve({});
        }
  
        var localSDPList = [];
  
        return new _promise2.default(function (resolve) {
          _this.getLocalSDPForClusters(clusterList).then(function (localSDPData) {
            if (!localSDPData || !(0, _keys2.default)(localSDPData).length || !localSDPData.localSDPList || !localSDPData.peerConnection) {
              // TODO: handle the error condition properly and try retry
              _loggerProxy2.default.logger.info('Reachability->performReachabilityCheck#Local SDP is empty or has missing elements..returning');
              resolve({});
            }
  
            _this.peerConnectionMap = localSDPData.peerConnection;
            localSDPList = localSDPData.localSDPList;
  
            _this.setRemoteOfferForEachCluster(localSDPList).then(function (response) {
              resolve(response);
            });
          }).catch(function (error) {
            _loggerProxy2.default.logger.error('Reachability->performReachabilityCheck#Error in getLocalSDPForClusters: ' + error);
            resolve({});
          });
        });
      };
  
      _this.setRemoteOfferForEachCluster = function (localSDPList) {
        var iceResult = {};
  
        return new _promise2.default(function (resolve) {
          _this.reachabilityRequest.remoteSDPForClusters(localSDPList).then(function (remoteSDPResponse) {
            var remoteSDPList = remoteSDPResponse.answers;
  
            if (!remoteSDPList || !remoteSDPList.length) {
              _loggerProxy2.default.logger.info('Reachability->setRemoteOfferForEachCluster#Remote SDP is empty.');
              _this.cleanUpPeerConnections(_this.peerConnectionMap);
              resolve({});
            }
            remoteSDPList.forEach(function (remoteSdp) {
              var jsonObj = remoteSdp;
              var clusterId = jsonObj.clusterId;
  
  
              if (jsonObj && jsonObj.sdp) {
                var pc = _this.peerConnectionMap[clusterId];
  
                _this.setIceCallBackHandlers(pc).then(function (iceStatsResult) {
                  iceStatsResult.clusterId = clusterId;
                  _this.processedClusterResults.push(iceStatsResult.clusterId);
                  iceResult[iceStatsResult.clusterId] = {
                    start: iceStatsResult.iceStats.start,
                    stop: iceStatsResult.iceStats.stop
                  };
                  if (_this.processedClusterResults.length === remoteSDPList.length) {
                    var reachabilityResult = _this.parseIceResultToReachabilityResult(iceResult);
  
                    _loggerProxy2.default.logger.info('Reachability->setRemoteOfferForEachCluster#Returning reachability result' + (0, _stringify2.default)(reachabilityResult));
                    resolve(reachabilityResult);
                  }
                }).catch(function (error) {
                  _loggerProxy2.default.logger.error('Reachability->setRemoteOfferForEachCluster#Error in setIceCallBackHandlers(): ' + error);
                  _this.cleanUpPeerConnections(_this.peerConnectionMap);
                  resolve({});
                });
                _peerConnectionManager2.default.setRemoteSessionDetails(pc, _constants.ANSWER, jsonObj.sdp);
              } else {
                _loggerProxy2.default.logger.error('Reachability->setRemoteOfferForEachCluster# Error in getting remote sdp.');
                _this.processedClusterResults.push(clusterId);
                if (_this.processedClusterResults.length === remoteSDPList.length) {
                  _this.cleanUpPeerConnections(_this.peerConnectionMap);
                  resolve({});
                }
              }
            });
          }).catch(function (error) {
            _loggerProxy2.default.logger.error('Reachability->setRemoteOfferForEachCluster#Error in remoteSDPForClusters!:' + error);
            _this.cleanUpPeerConnections(_this.peerConnectionMap);
            resolve({});
          });
        });
      };
  
      _this.getLocalSDPForClusters = function (clusterList) {
        var localSDPData = {};
        var localSDPList = [];
        var peerConnectionMap = {};
  
        return new _promise2.default(function (resolve, reject) {
          clusterList.forEach(function (cluster) {
            var clusterId = cluster;
  
            _peerConnectionManager2.default.createOffer(_util2.default.createPeerConnection()).then(function (peerConnection) {
              peerConnectionMap[clusterId] = peerConnection;
  
              var localSDP = {
                sdp: peerConnection.sdp,
                clusterId: clusterId
              };
  
              localSDPList.push(localSDP);
  
              if (localSDPList.length === clusterList.length) {
                localSDPData.peerConnection = peerConnectionMap;
                localSDPData.localSDPList = localSDPList;
                resolve(localSDPData);
              }
            }).catch(function (error) {
              _loggerProxy2.default.logger.error('Reachability->getLocalSDPForClusters#Error in getLocalSDP : ' + error);
              reject(error);
            });
          });
        });
      };
  
      _this.parseIceResultToReachabilityResult = function (iceResult) {
        if (!iceResult || !(0, _keys2.default)(iceResult).length) {
          return {};
        }
        var result = {};
  
        var _iteratorNormalCompletion = true;
        var _didIteratorError = false;
        var _iteratorError = undefined;
  
        try {
          for (var _iterator = (0, _getIterator3.default)((0, _keys2.default)(iceResult)), _step; !(_iteratorNormalCompletion = (_step = _iterator.next()).done); _iteratorNormalCompletion = true) {
            var clusterId = _step.value;
  
            var reachability = {};
  
            if (iceResult[clusterId].start > 0 && iceResult[clusterId].stop > 0) {
              var latency = iceResult[clusterId].stop - iceResult[clusterId].start;
  
              reachability = {
                reachable: true,
                latencyInMilliseconds: latency
              };
            } else {
              reachability = { reachable: false };
            }
            result[clusterId] = { udp: reachability };
          }
        } catch (err) {
          _didIteratorError = true;
          _iteratorError = err;
        } finally {
          try {
            if (!_iteratorNormalCompletion && _iterator.return) {
              _iterator.return();
            }
          } finally {
            if (_didIteratorError) {
              throw _iteratorError;
            }
          }
        }
  
        return result;
      };
  
      _this.cleanUpPeerConnections = function (peerConnectionMap) {
        var _iteratorNormalCompletion2 = true;
        var _didIteratorError2 = false;
        var _iteratorError2 = undefined;
  
        try {
          for (var _iterator2 = (0, _getIterator3.default)((0, _keys2.default)(peerConnectionMap)), _step2; !(_iteratorNormalCompletion2 = (_step2 = _iterator2.next()).done); _iteratorNormalCompletion2 = true) {
            var key = _step2.value;
  
            var pc = peerConnectionMap[key];
  
            if (pc) {
              _loggerProxy2.default.logger.info('Reachability->cleanUpPeerConnections#Cleaning up peer connection created for cluster : ' + key);
              pc.close();
            }
          }
        } catch (err) {
          _didIteratorError2 = true;
          _iteratorError2 = err;
        } finally {
          try {
            if (!_iteratorNormalCompletion2 && _iterator2.return) {
              _iterator2.return();
            }
          } finally {
            if (_didIteratorError2) {
              throw _iteratorError2;
            }
          }
        }
      };
  
      _this.setIceCallBackHandlers = function (pc) {
        var timeout = null;
        var iceStats = { start: 0, stop: 0 };
  
        return new _promise2.default(function (resolve) {
          function iceComplete(isSuccessful, timeout, iceStats) {
            if (isSuccessful) {
              if (timeout) {
                window.clearTimeout(timeout);
                timeout = undefined;
              }
            }
            pc.close();
            resolve({ iceStats: iceStats });
          }
  
          timeout = window.setTimeout(function () {
            _loggerProxy2.default.logger.warn('Reachability->iceCallBackHandler#' + _this.clusterId + ' ice handler timed out.');
            iceComplete(false, timeout, iceStats);
          }, 5000);
  
          pc.oniceconnectionstatechange = function () {
            if (pc) {
              if (pc.iceConnectionState === _constants.ICE_STATE.CHECKING) {
                iceStats.start = Date.now();
              }
              if (pc.iceConnectionState === _constants.ICE_STATE.CONNECTED) {
                iceStats.stop = Date.now();
                iceComplete(true, timeout, iceStats);
              }
              if (pc.iceConnectionState === _constants.ICE_STATE.FAILED) {
                iceComplete(false, timeout, iceStats);
              }
            }
          };
        });
      };
  
      _this.getClusters = function () {
        return _this.reachabilityRequest.getClusters();
      };
  
      _this.reachabilityRequest = new _request2.default({}, options);
      return _this;
    }
  
    /**
     * utility function
     * @returns {undefined}
     * @private
     * @memberof Reachability
     */
  
  
    /**
     * fetches reachability data
     * @returns {Object} reachability data
     * @public
     * @memberof Reachability
     */
  
  
    /**
     * fetches reachability data
     * @param {object} clusterList
     * @returns {object} reachability check results
     * @private
     * @memberof Reachability
     */
  
  
    /**
     * sets remote offer for each clusters
     * @param {object} localSDPList local SDP generated
     * @returns {object} reachability check results
     * @private
     * @memberof Reachability
     */
  
  
    /**
     * creates offer and generates localSDP
     * @param {object} clusterList cluster List
     * @returns {object} localSDPData
     * @private
     * @memberof Reachability
     */
  
  
    /**
     * Calculates time to establish connection
     * @param {object} iceResult iceResults
     * @returns {object} result
     * @private
     * @memberof Reachability
     */
  
  
    /**
     * cleans all the peerconnection
     * @param {object} peerConnectionMap peerconnectionList
     * @returns {object} localSDPData
     * @private
     * @memberof Reachability
     */
  
  
    /**
     * sets the success callback for peerconnection
     * @param {object} pc peerconnection
     * @returns {object} iceState
     * @private
     * @memberof Reachability
     */
  
  
    /**
     * proxy to the server request for clusters
     * @returns {Promise}
     * @private
     * @memberof Reachability
     */
  
  
    return Reachability;
  }(_webexCore.StatelessWebexPlugin);
  
  exports.default = Reachability;
  //# sourceMappingURL=index.js.map
  