UNPKG

kepler.gl.geoiq

Version:

kepler.gl is a webgl based application to visualize large scale location data in the browser

2,339 lines 240 kB
"use strict";

var _interopRequireDefault = require("@babel/runtime/helpers/interopRequireDefault");

var _typeof3 = require("@babel/runtime/helpers/typeof");

Object.defineProperty(exports, "__esModule", {
  value: true
});
exports.INITIAL_VIS_STATE = exports.DEFAULT_EDITOR = void 0;
exports.addDefaultLayers = addDefaultLayers;
exports.addDefaultTooltips = addDefaultTooltips;
exports.addWidgetUpdater = exports.addLayerUpdater = exports.addFilterUpdater = void 0;
exports.apiCallData = apiCallData;
exports.defaultAnimationConfig = void 0;
exports.deleteFeatureUpdater = deleteFeatureUpdater;
exports.enlargeFilterUpdater = void 0;
exports.interactionConfigChangeUpdater = interactionConfigChangeUpdater;
exports.layerColorUIChangeUpdater = exports.layerClickUpdater = void 0;
exports.layerConfigChangeUpdater = layerConfigChangeUpdater;
exports.layerHoverUpdater = void 0;
exports.layerTextLabelChangeUpdater = layerTextLabelChangeUpdater;
exports.layerTypeChangeUpdater = layerTypeChangeUpdater;
exports.layerVisConfigChangeUpdater = layerVisConfigChangeUpdater;
exports.layerVisualChannelChangeUpdater = layerVisualChannelChangeUpdater;
exports.loadFilesUpdater = exports.loadFilesErrUpdater = exports.loadEDLinkData = void 0;
exports.loadURLUpdater = loadURLUpdater;
exports.setEditorModeUpdater = exports.resetMapConfigUpdater = exports.reorderWidgetUpdater = exports.reorderLayerUpdater = exports.removeWidgetUpdater = exports.removeLayerUpdater = exports.removeFilterUpdater = exports.removeDatasetUpdater = exports.receiveMapConfigUpdater = exports.mouseMoveUpdater = exports.mapClickUpdater = void 0;
exports.setFeaturesUpdater = setFeaturesUpdater;
exports.setFilterAPIUpdater = setFilterAPIUpdater;
exports.setFilterPlotUpdater = void 0;
exports.setFilterUpdater = setFilterUpdater;
exports.setPolygonFilterLayerUpdater = setPolygonFilterLayerUpdater;
exports.showDatasetTableUpdater = exports.setSelectedFeatureUpdater = void 0;
exports.toggleEditorVisibility = toggleEditorVisibility;
exports.toggleSplitMapUpdater = exports.toggleLayerForMapUpdater = exports.toggleFilterAnimationUpdater = void 0;
exports.updateAllLayerDomainData = updateAllLayerDomainData;
exports.updateAnimationDomain = updateAnimationDomain;
exports.updateAnimationTimeUpdater = void 0;
exports.updateDatasetInfo = updateDatasetInfo;
exports.updateLayerBlendingUpdater = exports.updateLayerAnimationSpeedUpdater = exports.updateFilterAnimationSpeedUpdater = void 0;
exports.updateStateOnLayerVisibilityChange = updateStateOnLayerVisibilityChange;
exports.updateStateWithLayerDataUpdater = updateStateWithLayerDataUpdater;
exports.updateVisDataUpdater = void 0;
exports.updateWidgetAggregationData = updateWidgetAggregationData;
exports.widgetConfigChangeUpdater = widgetConfigChangeUpdater;
exports.widgetTypeChangeUpdater = widgetTypeChangeUpdater;

var _typeof2 = _interopRequireDefault(require("@babel/runtime/helpers/typeof"));

var _readOnlyError2 = _interopRequireDefault(require("@babel/runtime/helpers/readOnlyError"));

var _objectWithoutProperties2 = _interopRequireDefault(require("@babel/runtime/helpers/objectWithoutProperties"));

var _toConsumableArray2 = _interopRequireDefault(require("@babel/runtime/helpers/toConsumableArray"));

var _defineProperty2 = _interopRequireDefault(require("@babel/runtime/helpers/defineProperty"));

var _window = require("global/window");

var _tasks = _interopRequireWildcard(require("react-palm/tasks"));

var _lodash = _interopRequireDefault(require("lodash.clonedeep"));

var _lodash2 = _interopRequireDefault(require("lodash.uniq"));

var _lodash3 = _interopRequireDefault(require("lodash.get"));

var _lodash4 = _interopRequireDefault(require("lodash.xor"));

var _utils = require("../utils/utils");

var _tasks2 = require("../tasks/tasks");

var _visStateActions = require("../actions/vis-state-actions");

var _actions = require("../actions");

var _interactionUtils = require("../utils/interaction-utils");

var _filterUtils = require("../utils/filter-utils");

var _datasetUtils = require("../utils/dataset-utils");

var _layerUtils = require("../utils/layer-utils/layer-utils");

var _visStateMerger = require("./vis-state-merger");

var _simplifyGeojson = _interopRequireDefault(require("simplify-geojson"));

var _splitMapUtils = require("../utils/split-map-utils");

var _dataProcessor = require("../processors/data-processor");

var _layers = require("../layers");

var _widgets = require("../widgets");

var _fileUtils = require("../utils/file-utils");

var _layerFactory = require("../layers/layer-factory");

var _defaultSettings = require("../constants/default-settings");

function _getRequireWildcardCache(nodeInterop) { if (typeof WeakMap !== "function") return null; var cacheBabelInterop = new WeakMap(); var cacheNodeInterop = new WeakMap(); return (_getRequireWildcardCache = function _getRequireWildcardCache(nodeInterop) { return nodeInterop ? cacheNodeInterop : cacheBabelInterop; })(nodeInterop); }

function _interopRequireWildcard(obj, nodeInterop) { if (!nodeInterop && obj && obj.__esModule) { return obj; } if (obj === null || _typeof3(obj) !== "object" && typeof obj !== "function") { return { "default": obj }; } var cache = _getRequireWildcardCache(nodeInterop); if (cache && cache.has(obj)) { return cache.get(obj); } var newObj = {}; var hasPropertyDescriptor = Object.defineProperty && Object.getOwnPropertyDescriptor; for (var key in obj) { if (key !== "default" && Object.prototype.hasOwnProperty.call(obj, key)) { var desc = hasPropertyDescriptor ? Object.getOwnPropertyDescriptor(obj, key) : null; if (desc && (desc.get || desc.set)) { Object.defineProperty(newObj, key, desc); } else { newObj[key] = obj[key]; } } } newObj["default"] = obj; if (cache) { cache.set(obj, newObj); } return newObj; }

function _toPropertyKey(arg) { var key = _toPrimitive(arg, "string"); return (0, _typeof2["default"])(key) === "symbol" ? key : String(key); }

function _toPrimitive(input, hint) { if ((0, _typeof2["default"])(input) !== "object" || input === null) return input; var prim = input[Symbol.toPrimitive]; if (prim !== undefined) { var res = prim.call(input, hint || "default"); if ((0, _typeof2["default"])(res) !== "object") return res; throw new TypeError("@@toPrimitive must return a primitive value."); } return (hint === "string" ? String : Number)(input); }

function ownKeys(e, r) { var t = Object.keys(e); if (Object.getOwnPropertySymbols) { var o = Object.getOwnPropertySymbols(e); r && (o = o.filter(function (r) { return Object.getOwnPropertyDescriptor(e, r).enumerable; })), t.push.apply(t, o); } return t; }

function _objectSpread(e) { for (var r = 1; r < arguments.length; r++) { var t = null != arguments[r] ? arguments[r] : {}; r % 2 ? ownKeys(Object(t), !0).forEach(function (r) { (0, _defineProperty2["default"])(e, r, t[r]); }) : Object.getOwnPropertyDescriptors ? Object.defineProperties(e, Object.getOwnPropertyDescriptors(t)) : ownKeys(Object(t)).forEach(function (r) { Object.defineProperty(e, r, Object.getOwnPropertyDescriptor(t, r)); }); } return e; }

// react-palm
// disable capture exception for react-palm call to withTask
(0, _tasks.disableStackCapturing)();
/**
 * Updaters for `visState` reducer. Can be used in your root reducer to directly modify kepler.gl's state.
 * Read more about [Using updaters](../advanced-usage/using-updaters.md)
 *
 * @public
 * @example
 *
 * import keplerGlReducer, {visStateUpdaters} from 'kepler.gl/reducers';
 * // Root Reducer
 * const reducers = combineReducers({
 *  keplerGl: keplerGlReducer,
 *  app: appReducer
 * });
 *
 * const composedReducer = (state, action) => {
 *  switch (action.type) {
 *    case 'CLICK_BUTTON':
 *      return {
 *        ...state,
 *        keplerGl: {
 *          ...state.keplerGl,
 *          foo: {
 *             ...state.keplerGl.foo,
 *             visState: visStateUpdaters.enlargeFilterUpdater(
 *               state.keplerGl.foo.visState,
 *               {idx: 0}
 *             )
 *          }
 *        }
 *      };
 *  }
 *  return reducers(state, action);
 * };
 *
 * export default composedReducer;
 */

/* eslint-disable no-unused-vars */
// const visStateUpdaters = null;

/* eslint-enable no-unused-vars */

var defaultAnimationConfig = exports.defaultAnimationConfig = {
  domain: null,
  currentTime: null,
  speed: 1
};
var DEFAULT_EDITOR = exports.DEFAULT_EDITOR = {
  mode: _defaultSettings.EDITOR_MODES.DRAW_POLYGON,
  features: [],
  selectedFeature: null,
  visible: true
};
/**
 * Default initial `visState`
 * @memberof visStateUpdaters
 * @constant
 * @type {Object}
 * @property {Array} layers
 * @property {Array} layerData
 * @property {Array} layerToBeMerged
 * @property {Array} layerOrder
 * @property {Array} filters
 * @property {Array} filterToBeMerged
 * @property {Array} datasets
 * @property {string} editingDataset
 * @property {Object} interactionConfig
 * @property {Object} interactionToBeMerged
 * @property {string} layerBlending
 * @property {Object} hoverInfo
 * @property {Object} clicked
 * @property {Object} mousePos
 * @property {Array} splitMaps - a list of objects of layer availabilities and visibilities for each map
 * @property {Object} layerClasses
 * @property {Object} animationConfig
 * @property {Object} editor
 * @public
 */

var INITIAL_VIS_STATE = exports.INITIAL_VIS_STATE = {
  // layers
  layers: [],
  layerData: [],
  layerToBeMerged: [],
  layerOrder: [],
  // filters
  filters: [],
  filterToBeMerged: [],
  // widgets
  widgets: [],
  widgetToBeMerged: [],
  widgetOrder: [],
  // a collection of multiple dataset
  datasets: {},
  editingDataset: undefined,
  interactionConfig: (0, _interactionUtils.getDefaultInteraction)(),
  interactionToBeMerged: undefined,
  layerBlending: 'normal',
  hoverInfo: undefined,
  clicked: undefined,
  mousePos: {},
  // this is used when user split maps
  splitMaps: [// this will contain a list of objects to
    // describe the state of layer availability and visibility for each map
    // [
    //   {
    //      layers: {layer_id: true | false}
    //   }
    // ]
  ],
  //
  // defaults layer classes
  layerClasses: _layers.LayerClasses,
  // default widget classes
  widgetClasses: _widgets.WidgetClasses,
  // default animation
  // time in unix timestamp (milliseconds) (the number of seconds since the Unix Epoch)
  animationConfig: defaultAnimationConfig,
  editor: DEFAULT_EDITOR
};

function updateStateWithWidgetAndData(state, _ref) {
  var widget = _ref.widget,
      idx = _ref.idx;
  return _objectSpread(_objectSpread({}, state), {}, {
    widgets: state.widgets.map(function (wdgt, i) {
      return i === idx ? widget : wdgt;
    })
  });
}
/**
 * Called to update layer base config: dataId, label, column, isVisible
 *
 */


function widgetConfigChangeUpdater(state, action) {
  var oldWidget = action.oldWidget,
      auth = action.auth,
      project = action.project;
  var mapState = action.newConfig.mapState;
  var x = state.widgets.findIndex(function (w) {
    return w.id === oldWidget.id;
  });
  var props = Object.keys(action.newConfig);
  action.newConfig.mapState ? delete action.newConfig.mapState : null;
  var newWidget = oldWidget.updateWidgetConfig(action.newConfig); // if (newWidget.shouldCalculateAggregatedData(props)) {
  // const aggregatedData = newWidget.calculateAggregationData(
  //   newWidget,
  //   state.filters,
  //   state.datasets,
  //   mapState,
  //   auth,
  //   project
  // );
  // newWidget.updateWidgetConfg({apiCallRequest: true});
  // return updateStateWithWidgetAndData(updatedState ? updatedState : state, {
  //   widget: newWidget,
  //   x
  // });
  // }

  var newState = _objectSpread(_objectSpread({}, state), {}, {
    splitMaps: 'isVisible' in action.newConfig ? toggleWidgetFromSplitMaps(state, widget) : state.splitMaps
  });

  return updateStateWithWidgetAndData(newState, {
    widget: newWidget,
    x: x
  });
}

function widgetTypeChangeUpdater(state, action) {
  var oldWidget = action.oldWidget,
      newType = action.newType;
  var oldId = oldWidget.id;
  var idx = state.widgets.findIndex(function (w) {
    return w.id === oldId;
  });

  if (!state.widgetClasses[newType]) {
    _window.console.error("".concat(newType, " is not a valid widget type"));

    return state;
  } // get a mint widget, with new id and type
  // because deck.gl uses id to match between new and old layer.
  // If type has changed but id is the same, it will break


  var newWidget = new state.widgetClasses[newType]();
  newWidget.config.aggregatedData = null;
  newWidget.assignConfigToWidget(oldWidget.config, oldWidget.visConfigSettings);
  var newState = state;
  var widget = newWidget;
  return updateStateWithWidgetAndData(newState, {
    widget: widget,
    idx: idx
  });
}

function updateStateWithLayerAndData(state, _ref2) {
  var layerData = _ref2.layerData,
      layer = _ref2.layer,
      idx = _ref2.idx;
  return _objectSpread(_objectSpread({}, state), {}, {
    layers: state.layers.map(function (lyr, i) {
      return i === idx ? layer : lyr;
    }),
    layerData: layerData ? state.layerData.map(function (d, i) {
      return i === idx ? layerData : d;
    }) : state.layerData
  });
}

function updateStateOnLayerVisibilityChange(state, layer) {
  var newState = state;

  if (state.splitMaps.length) {
    newState = _objectSpread(_objectSpread({}, state), {}, {
      splitMaps: layer.config.isVisible ? (0, _splitMapUtils.addNewLayersToSplitMap)(state.splitMaps, layer) : (0, _splitMapUtils.removeLayerFromSplitMaps)(state.splitMaps, layer)
    });
  }

  if (layer.config.animation.enabled) {
    newState = updateAnimationDomain(state);
  }

  return newState;
}
/**
 * Update layer base config: dataId, label, column, isVisible
 * @memberof visStateUpdaters
 * @param {Object} state `visState`
 * @param {Object} action action
 * @param {Object} action.oldLayer layer to be updated
 * @param {Object} action.newConfig new config
 * @returns {Object} nextState
 */


function layerConfigChangeUpdater(state, action) {
  var oldLayer = action.oldLayer;
  var idx = state.layers.findIndex(function (l) {
    return l.id === oldLayer.id;
  });
  var props = Object.keys(action.newConfig);
  var newLayer = oldLayer.updateLayerConfig(action.newConfig);
  var layerData; // let newLayer;

  if (newLayer.shouldCalculateLayerData(props)) {
    var oldLayerData = state.layerData[idx];
    var updateLayerDataResult = (0, _layerUtils.calculateLayerData)(newLayer, state, oldLayerData, {
      sameData: true
    });
    layerData = updateLayerDataResult.layerData;
    newLayer = updateLayerDataResult.layer;
  }

  var newState = state;

  if ('isVisible' in action.newConfig) {
    newState = updateStateOnLayerVisibilityChange(state, newLayer);
  }

  return updateStateWithLayerAndData(newState, {
    layer: newLayer,
    layerData: layerData,
    idx: idx
  });
}

function addOrRemoveTextLabels(newFields, textLabel) {
  var newTextLabel = textLabel.slice();
  var currentFields = textLabel.map(function (tl) {
    return tl.field && tl.field.name;
  }).filter(function (d) {
    return d;
  });
  var addFields = newFields.filter(function (f) {
    return !currentFields.includes(f.name);
  });
  var deleteFields = currentFields.filter(function (f) {
    return !newFields.find(function (fd) {
      return fd.name === f;
    });
  }); // delete

  newTextLabel = newTextLabel.filter(function (tl) {
    return tl.field && !deleteFields.includes(tl.field.name);
  });
  newTextLabel = !newTextLabel.length ? [_layerFactory.DEFAULT_TEXT_LABEL] : newTextLabel; // add

  newTextLabel = [].concat((0, _toConsumableArray2["default"])(newTextLabel.filter(function (tl) {
    return tl.field;
  })), (0, _toConsumableArray2["default"])(addFields.map(function (af) {
    return _objectSpread(_objectSpread({}, _layerFactory.DEFAULT_TEXT_LABEL), {}, {
      field: af
    });
  })));
  return newTextLabel;
}

function updateTextLabelPropAndValue(idx, prop, value, textLabel) {
  if (!textLabel[idx].hasOwnProperty(prop)) {
    return textLabel;
  }

  var newTextLabel = textLabel.slice();

  if (prop && (value || textLabel.length === 1)) {
    newTextLabel = textLabel.map(function (tl, i) {
      return i === idx ? _objectSpread(_objectSpread({}, tl), {}, (0, _defineProperty2["default"])({}, prop, value)) : tl;
    });
  } else if (prop === 'field' && value === null && textLabel.length > 1) {
    // remove label when field value is set to null
    newTextLabel.splice(idx, 1);
  }

  return newTextLabel;
}

function layerTextLabelChangeUpdater(state, action) {
  var oldLayer = action.oldLayer,
      idx = action.idx,
      prop = action.prop,
      value = action.value;
  var textLabel = oldLayer.config.textLabel;
  var newTextLabel = textLabel.slice();

  if (!textLabel[idx] && idx === textLabel.length) {
    // if idx is set to length, add empty text label
    newTextLabel = [].concat((0, _toConsumableArray2["default"])(textLabel), [_layerFactory.DEFAULT_TEXT_LABEL]);
  }

  if (idx === 'all' && prop === 'fields') {
    newTextLabel = addOrRemoveTextLabels(value, textLabel);
  } else {
    newTextLabel = updateTextLabelPropAndValue(idx, prop, value, newTextLabel);
  } // update text label prop and value


  return layerConfigChangeUpdater(state, {
    oldLayer: oldLayer,
    newConfig: {
      textLabel: newTextLabel
    }
  });
}
/**
 * Update layer type. Previews layer config will be copied if applicable.
 * @memberof visStateUpdaters
 * @param {Object} state `visState`
 * @param {Object} action action
 * @param {Object} action.oldLayer layer to be updated
 * @param {string} action.newType new type
 * @returns {Object} nextState
 * @public
 */


function layerTypeChangeUpdater(state, action) {
  var oldLayer = action.oldLayer,
      newType = action.newType;

  if (!oldLayer) {
    return state;
  }

  var oldId = oldLayer.id;
  var idx = state.layers.findIndex(function (l) {
    return l.id === oldId;
  });

  if (!state.layerClasses[newType]) {
    _window.console.error("".concat(newType, " is not a valid layer type"));

    return state;
  } // get a mint layer, with new id and type
  // because deck.gl uses id to match between new and old layer.
  // If type has changed but id is the same, it will break


  var newLayer = new state.layerClasses[newType]();

  if (newLayer.name !== 'boundary' && newLayer.name !== 'pincode') {
    oldLayer.config.apiCallRequest = true;
  }

  newLayer.assignConfigToLayer(oldLayer.config, oldLayer.visConfigSettings);

  if (newLayer.config.dataId) {
    var dataset = state.datasets[newLayer.config.dataId];
    newLayer.updateLayerDomain(dataset);
  }

  var _calculateLayerData = (0, _layerUtils.calculateLayerData)(newLayer, state),
      layerData = _calculateLayerData.layerData,
      layer = _calculateLayerData.layer;

  var newState = updateStateWithLayerAndData(state, {
    layerData: layerData,
    layer: layer,
    idx: idx
  });

  if (layer.config.animation.enabled || oldLayer.config.animation.enabled) {
    newState = updateAnimationDomain(newState);
  } // update widgets layer id
  // if (state.widgets) {
  //   state.widgets.map(widget => {
  //     const {config} = widget;
  //     const {selectedLayer} = config;
  //     if (widget.type && selectedLayer.id === oldId) {
  //       widget.updateWidgetConfig({
  //         selectedLayer: {...selectedLayer, id: newLayer.id}
  //       });
  //     }
  //   });
  // }
  // update splitMap layer id


  if (state.splitMaps.length) {
    newState = _objectSpread(_objectSpread({}, newState), {}, {
      splitMaps: newState.splitMaps.map(function (settings) {
        var _settings$layers = settings.layers,
            oldLayerMap = _settings$layers[oldId],
            otherLayers = (0, _objectWithoutProperties2["default"])(_settings$layers, [oldId].map(_toPropertyKey));
        return oldId in settings.layers ? _objectSpread(_objectSpread({}, settings), {}, {
          layers: _objectSpread(_objectSpread({}, otherLayers), {}, (0, _defineProperty2["default"])({}, layer.id, oldLayerMap))
        }) : settings;
      })
    });
  }

  return newState;
}
/**
 * Update layer visual channel
 * @memberof visStateUpdaters
 * @param {Object} state `visState`
 * @param {Object} action action
 * @param {Object} action.oldLayer layer to be updated
 * @param {Object} action.newConfig new visual channel config
 * @param {string} action.channel channel to be updated
 * @returns {Object} nextState
 * @public
 */


function layerVisualChannelChangeUpdater(state, action) {
  var oldLayer = action.oldLayer,
      newConfig = action.newConfig,
      channel = action.channel;
  var dataset = state.datasets[oldLayer.config.dataId];
  var idx = state.layers.findIndex(function (l) {
    return l.id === oldLayer.id;
  });
  var newLayer = oldLayer.updateLayerConfig(newConfig);
  newLayer.updateLayerVisualChannel(dataset, channel);
  var oldLayerData = state.layerData[idx];

  var _calculateLayerData2 = (0, _layerUtils.calculateLayerData)(newLayer, state, oldLayerData, {
    sameData: true
  }),
      layerData = _calculateLayerData2.layerData,
      layer = _calculateLayerData2.layer; // let data = layer.axiosApiCall();
  // if (layer.type === 'boundary') {
  //   data.then(function(result) {
  //     // const testData = layer.formatLayer();
  //     var {layerData, layer} = calculateLayerDataAfterAPICall(
  //       newLayer,
  //       state,
  //       layerData,
  //       result
  //     );
  //     layerData = {
  //       ...layerData,
  //       result
  //     };
  //     newLayers[i] = layer;
  //     newLayerDatas[i] = layerData;
  //     return {
  //       ...state,
  //       layers: newLayers,
  //       layerData: newLayerDatas
  //     };
  //   });
  // }


  return updateStateWithLayerAndData(state, {
    layerData: layerData,
    layer: layer,
    idx: idx
  });
}
/**
 * Update layer `visConfig`
 * @memberof visStateUpdaters
 * @param {Object} state `visState`
 * @param {Object} action action
 * @param {Object} action.oldLayer layer to be updated
 * @param {Object} action.newVisConfig new visConfig as a key value map: e.g. `{opacity: 0.8}`
 * @returns {Object} nextState
 * @public
 */


function layerVisConfigChangeUpdater(state, action) {
  var oldLayer = action.oldLayer;
  var idx = state.layers.findIndex(function (l) {
    return l.id === oldLayer.id;
  });
  var props = Object.keys(action.newVisConfig);

  var newVisConfig = _objectSpread(_objectSpread({}, oldLayer.config.visConfig), action.newVisConfig);

  var newLayer = oldLayer.updateLayerConfig({
    visConfig: newVisConfig
  });

  if (newLayer.shouldCalculateLayerData(props)) {
    var oldLayerData = state.layerData[idx];

    var _calculateLayerData4 = (0, _layerUtils.calculateLayerData)(newLayer, state, oldLayerData, {
      sameData: true
    }),
        layerData = _calculateLayerData4.layerData,
        layer = _calculateLayerData4.layer;

    return updateStateWithLayerAndData(state, {
      layerData: layerData,
      layer: layer,
      idx: idx
    });
  }

  return updateStateWithLayerAndData(state, {
    layer: newLayer,
    idx: idx
  });
}
/* eslint-enable max-statements */

/**
 * Update `interactionConfig`
 * @memberof visStateUpdaters
 * @param {Object} state `visState`
 * @param {Object} action action
 * @param {Object} action.config new config as key value map: `{tooltip: {enabled: true}}`
 * @returns {Object} nextState
 * @public
 */


function interactionConfigChangeUpdater(state, action) {
  var config = action.config;

  var interactionConfig = _objectSpread(_objectSpread({}, state.interactionConfig), (0, _defineProperty2["default"])({}, config.id, config)); // Don't enable tooltip and brush at the same time
  // but coordinates can be shown at all time


  var contradict = ['brush', 'tooltip'];

  if (contradict.includes(config.id) && config.enabled && !state.interactionConfig[config.id].enabled) {
    // only enable one interaction at a time
    contradict.forEach(function (k) {
      if (k !== config.id) {
        interactionConfig[k] = _objectSpread(_objectSpread({}, interactionConfig[k]), {}, {
          enabled: false
        });
      }
    });
  }

  return _objectSpread(_objectSpread({}, state), {}, {
    interactionConfig: interactionConfig
  });
}
/**
 * Update filter property
 * @param {object} state
 * @param {object} action
 * @param {Number} action.idx `idx` of filter to be updated
 * @param {string} action.prop `prop` of filter, e,g, `dataId`, `name`, `value`
 * @param {*} action.value new value
 * @param {string} action.dataId
 * @param {string} action.range
 * @param {object} action.histogram
 * @returns {object} newState
 */


function setFilterAPIUpdater(state, action) {
  var dataId = action.dataId,
      prop = action.prop,
      value = action.value,
      _action$valueIndex = action.valueIndex,
      valueIndex = _action$valueIndex === void 0 ? 0 : _action$valueIndex,
      domain = action.domain,
      _action$histogram = action.histogram,
      histogram = _action$histogram === void 0 ? {} : _action$histogram,
      idx = action.idx;
  var newState = state;

  var newFilter = _objectSpread(_objectSpread({}, state.filters[idx]), {}, (0, _defineProperty2["default"])({}, prop, value));

  if (!histogram) {
    ({}), (0, _readOnlyError2["default"])("histogram");
  }

  var datasetId = newFilter.dataId[valueIndex];

  var _applyFilterApiFieldN = (0, _filterUtils.applyFilterApiFieldName)(newFilter, state.datasets[datasetId], value, valueIndex, {
    mergeDomain: false
  }, histogram, domain),
      updatedFilter = _applyFilterApiFieldN.filter;

  if (!updatedFilter) {
    return state;
  }

  newFilter = updatedFilter; // newState = newState.layers.map(l => {
  //   if (l.config.dataId === dataId) {
  //     layerConfigChangeUpdater(l, {
  //       apiCallRequest: true
  //     });
  //   }
  // });

  newState = _objectSpread(_objectSpread({}, newState), {}, {
    filters: Object.assign((0, _toConsumableArray2["default"])(state.filters), (0, _defineProperty2["default"])({}, idx, newFilter))
  });
  return newState;
}
/**
 * Update filter property
 * @memberof visStateUpdaters
 * @param {Object} state `visState`
 * @param {Object} action action
 * @param {Number} action.idx `idx` of filter to be updated
 * @param {string} action.prop `prop` of filter, e,g, `dataId`, `name`, `value`
 * @param {*} action.value new value
 * @param {string} datasetId used when updating a prop (dataId, name) that can be linked to multiple datasets
 * @returns {Object} nextState
 * @public
 */


function setFilterUpdater(state, action) {
  var idx = action.idx,
      prop = action.prop,
      value = action.value,
      _action$valueIndex2 = action.valueIndex,
      valueIndex = _action$valueIndex2 === void 0 ? 0 : _action$valueIndex2,
      mapState = action.mapState,
      auth = action.auth,
      project = action.project;
  var oldFilter = state.filters[idx];
  var newFilter = (0, _utils.set)([prop], value, oldFilter);
  var newState = state;
  var _newFilter = newFilter,
      dataId = _newFilter.dataId; // Ensuring backward compatibility

  var datasetIds = Array.isArray(dataId) ? dataId : [dataId];

  switch (prop) {
    // TODO: Next PR for UI if we update dataId, we need to consider two cases:
    // 1. dataId is empty: create a default filter
    // 2. Add a new dataset id
    case _filterUtils.FILTER_UPDATER_PROPS.dataId:
      // if trying to update filter dataId. create an empty new filter
      newFilter = (0, _filterUtils.getDefaultFilter)(dataId);
      break;

    case _filterUtils.FILTER_UPDATER_PROPS.name:
      // we are supporting the current functionality
      // TODO: Next PR for UI filter name will only update filter name but it won't have side effects
      // we are gonna use pair of datasets and fieldIdx to update the filter
      var datasetId = newFilter.dataId[valueIndex];

      var _applyFilterFieldName2 = (0, _filterUtils.applyFilterFieldName)(newFilter, state.datasets[datasetId], value, valueIndex, {
        mergeDomain: false
      }),
          updatedFilter = _applyFilterFieldName2.filter,
          newDataset = _applyFilterFieldName2.dataset;

      if (!updatedFilter) {
        return state;
      }

      newFilter = updatedFilter;
      newState = _objectSpread(_objectSpread({}, state), {}, {
        datasets: _objectSpread(_objectSpread({}, state.datasets), {}, (0, _defineProperty2["default"])({}, datasetId, newDataset))
      });
      break;

    case _filterUtils.FILTER_UPDATER_PROPS.layerId:
      // We need to update only datasetId/s if we have added/removed layers
      // - check for layerId changes (XOR works because of string values)
      // if no differences between layerIds, don't do any filtering
      var layerIdDifference = (0, _lodash4["default"])(newFilter.layerId, oldFilter.layerId);
      var layerDataIds = (0, _lodash2["default"])(layerIdDifference.map(function (lid) {
        return (0, _lodash3["default"])(state.layers.find(function (l) {
          return l.id === lid;
        }), ['config', 'dataId']);
      }).filter(function (d) {
        return d;
      })); // only filter datasetsIds

      datasetIds = layerDataIds; // Update newFilter dataIds

      var newDataIds = (0, _lodash2["default"])(newFilter.layerId.map(function (lid) {
        return (0, _lodash3["default"])(state.layers.find(function (l) {
          return l.id === lid;
        }), ['config', 'dataId']);
      }).filter(function (d) {
        return d;
      }));
      newFilter = _objectSpread(_objectSpread({}, newFilter), {}, {
        dataId: newDataIds
      }); // only filter the current dataset

      break;

    default:
      break;
  }

  var enlargedFilter = state.filters.find(function (f) {
    return f.enlarged;
  });

  if (enlargedFilter && enlargedFilter.id !== newFilter.id) {
    // there should be only one enlarged filter
    newFilter.enlarged = false;
  } // save new filters to newState


  newState = _objectSpread(_objectSpread({}, newState), {}, {
    filters: Object.assign((0, _toConsumableArray2["default"])(state.filters), (0, _defineProperty2["default"])({}, idx, newFilter))
  }); // if we are currently setting a prop that only requires to filter the current
  // dataset we will pass only the current dataset to applyFiltersToDatasets and
  // updateAllLayerDomainData otherwise we pass the all list of datasets as defined in dataId

  var datasetIdsToFilter = _filterUtils.LIMITED_FILTER_EFFECT_PROPS[prop] ? (0, _utils.toArray)(datasetIds[valueIndex]) : datasetIds; // filter data

  newState = _objectSpread(_objectSpread({}, newState), {}, {
    datasets: (0, _filterUtils.applyFiltersToDatasets)(datasetIdsToFilter, newState.datasets, newState.filters, newState.layers)
  }); // newState = updateWidgetAggregationData(newState, mapState, auth, project);
  // dataId is an array
  // pass only the dataset we need to update

  newState = updateAllLayerDomainData(newState, datasetIdsToFilter, newFilter);
  return newState;
}
/**
 * Set the property of a filter plot
 * @memberof visStateUpdaters
 * @param {Object} state `visState`
 * @param {Object} action action
 * @param {Number} action.idx
 * @param {Object} action.newProp key value mapping of new prop `{yAxis: 'histogram'}`
 * @returns {Object} nextState
 * @public
 */


var setFilterPlotUpdater = exports.setFilterPlotUpdater = function setFilterPlotUpdater(state, _ref3) {
  var idx = _ref3.idx,
      newProp = _ref3.newProp;

  var newFilter = _objectSpread(_objectSpread({}, state.filters[idx]), newProp);

  var prop = Object.keys(newProp)[0];

  if (prop === 'yAxis') {
    var plotType = (0, _filterUtils.getDefaultFilterPlotType)(newFilter);

    if (plotType) {
      newFilter = _objectSpread(_objectSpread(_objectSpread({}, newFilter), (0, _filterUtils.getFilterPlot)(_objectSpread(_objectSpread({}, newFilter), {}, {
        plotType: plotType
      }), state.datasets[newFilter.dataId].allData)), {}, {
        plotType: plotType
      });
    }
  }

  return _objectSpread(_objectSpread({}, state), {}, {
    filters: state.filters.map(function (f, i) {
      return i === idx ? newFilter : f;
    })
  });
};
/**
 * Add a new filter
 * @memberof visStateUpdaters
 * @param {Object} state `visState`
 * @param {Object} action action
 * @param {string} action.dataId dataset `id` this new filter is associated with
 * @returns {Object} nextState
 * @public
 */


var addFilterUpdater = exports.addFilterUpdater = function addFilterUpdater(state, action) {
  return !action.dataId ? state : _objectSpread(_objectSpread({}, state), {}, {
    filters: [].concat((0, _toConsumableArray2["default"])(state.filters), [(0, _filterUtils.getDefaultFilter)(action.dataId)])
  });
};
/**
 * Set layer color palette ui state
 * @memberof visStateUpdaters
 * @param {Object} state
 * @param {Object} action
 * @param {Object} action.prop
 * @param {Object} action.newConfig
 */


var layerColorUIChangeUpdater = exports.layerColorUIChangeUpdater = function layerColorUIChangeUpdater(state, _ref4) {
  var oldLayer = _ref4.oldLayer,
      prop = _ref4.prop,
      newConfig = _ref4.newConfig;
  var newLayer = oldLayer.updateLayerColorUI(prop, newConfig);
  return _objectSpread(_objectSpread({}, state), {}, {
    layers: state.layers.map(function (l) {
      return l.id === oldLayer.id ? newLayer : l;
    })
  });
};
/**
 * Start and end filter animation
 * @memberof visStateUpdaters
 * @param {Object} state `visState`
 * @param {Object} action action
 * @param {Number} action.idx idx of filter
 * @returns {Object} nextState
 * @public
 */


var toggleFilterAnimationUpdater = exports.toggleFilterAnimationUpdater = function toggleFilterAnimationUpdater(state, action) {
  return _objectSpread(_objectSpread({}, state), {}, {
    filters: state.filters.map(function (f, i) {
      return i === action.idx ? _objectSpread(_objectSpread({}, f), {}, {
        isAnimating: !f.isAnimating
      }) : f;
    })
  });
};
/**
 * Change filter animation speed
 * @memberof visStateUpdaters
 * @param {Object} state `visState`
 * @param {Object} action action
 * @param {Number} action.idx  `idx` of filter
 * @param {Number} action.speed `speed` to change it to. `speed` is a multiplier
 * @returns {Object} nextState
 * @public
 */


var updateFilterAnimationSpeedUpdater = exports.updateFilterAnimationSpeedUpdater = function updateFilterAnimationSpeedUpdater(state, action) {
  return _objectSpread(_objectSpread({}, state), {}, {
    filters: state.filters.map(function (f, i) {
      return i === action.idx ? _objectSpread(_objectSpread({}, f), {}, {
        speed: action.speed
      }) : f;
    })
  });
};
/**
 * Reset animation config current time to a specified value
 * @memberof visStateUpdaters
 * @param {Object} state `visState`
 * @param {Object} action action
 * @param {Number} action.value the value current time will be set to
 * @returns {Object} nextState
 * @public
 *
 */


var updateAnimationTimeUpdater = exports.updateAnimationTimeUpdater = function updateAnimationTimeUpdater(state, _ref5) {
  var value = _ref5.value;
  return _objectSpread(_objectSpread({}, state), {}, {
    animationConfig: _objectSpread(_objectSpread({}, state.animationConfig), {}, {
      currentTime: value
    })
  });
};
/**
 * Update animation speed with the vertical speed slider
 * @memberof visStateUpdaters
 * @param {Object} state `visState`
 * @param {Object} action action
 * @param {Number} action.speed the updated speed of the animation
 * @returns {Object} nextState
 * @public
 *
 */


var updateLayerAnimationSpeedUpdater = exports.updateLayerAnimationSpeedUpdater = function updateLayerAnimationSpeedUpdater(state, _ref6) {
  var speed = _ref6.speed;
  return _objectSpread(_objectSpread({}, state), {}, {
    animationConfig: _objectSpread(_objectSpread({}, state.animationConfig), {}, {
      speed: speed
    })
  });
};
/**
 * Show larger time filter at bottom for time playback (apply to time filter only)
 * @memberof visStateUpdaters
 * @param {Object} state `visState`
 * @param {Object} action action
 * @param {Number} action.idx index of filter to enlarge
 * @returns {Object} nextState
 * @public
 */


var enlargeFilterUpdater = exports.enlargeFilterUpdater = function enlargeFilterUpdater(state, action) {
  var isEnlarged = state.filters[action.idx].enlarged;
  return _objectSpread(_objectSpread({}, state), {}, {
    filters: state.filters.map(function (f, i) {
      f.enlarged = !isEnlarged && i === action.idx;
      return f;
    })
  });
};
/**
 * Remove a filter
 * @memberof visStateUpdaters
 * @param {Object} state `visState`
 * @param {Object} action action
 * @param {Number} action.idx index of filter to b e removed
 * @returns {Object} nextState
 * @public
 */


var removeFilterUpdater = exports.removeFilterUpdater = function removeFilterUpdater(state, action) {
  var idx = action.idx,
      mapState = action.mapState,
      auth = action.auth,
      project = action.project;
  var dataId = state.filters[idx].dataId;
  var newFilters = [].concat((0, _toConsumableArray2["default"])(state.filters.slice(0, idx)), (0, _toConsumableArray2["default"])(state.filters.slice(idx + 1, state.filters.length)));
  var filter = state.filters[idx];
  var filteredDatasets = (0, _filterUtils.applyFiltersToDatasets)(dataId, state.datasets, newFilters, state.layers);

  var newState = _objectSpread(_objectSpread({}, state), {}, {
    filters: newFilters,
    editor: _objectSpread(_objectSpread({}, state.editor), {}, {
      features: filter.type !== _filterUtils.FILTER_TYPES.polygon ? state.editor.features : state.editor.features.filter(function (f) {
        return f.id !== filter.value.id;
      }),
      selectedFeature: null
    })
  }); // call layers api to update data when a filter is removed


  var layers = newState.layers.map(function (layer) {
    if (layer.dataId === dataId) {
      layer.config.apiCallRequest === true;
    }

    return layer;
  });
  newState = _objectSpread(_objectSpread({}, newState), {}, {
    layers: layers
  });
  newState = (0, _utils.set)(['datasets'], filteredDatasets, newState);
  return updateAllLayerDomainData(newState, dataId);
};

var addWidgetUpdater = exports.addWidgetUpdater = function addWidgetUpdater(state, action) {
  var defaultDataset = Object.keys(state.datasets)[0];
  var newWidget = new _widgets.Widget(_objectSpread({
    isVisible: true,
    isConfigActive: true,
    dataId: defaultDataset
  }, action.props));
  return !defaultDataset ? state : _objectSpread(_objectSpread({}, state), {}, {
    widgets: [].concat((0, _toConsumableArray2["default"])(state.widgets), [newWidget]),
    widgetOrder: [].concat((0, _toConsumableArray2["default"])(state.widgetOrder), [state.widgetOrder.length])
  });
};

var removeWidgetUpdater = exports.removeWidgetUpdater = function removeWidgetUpdater(state, _ref7) {
  var idx = _ref7.idx;
  var widgets = state.widgets;
  return _objectSpread(_objectSpread({}, state), {}, {
    widgets: [].concat((0, _toConsumableArray2["default"])(widgets.slice(0, idx)), (0, _toConsumableArray2["default"])(widgets.slice(idx + 1, widgets.length))),
    widgetOrder: state.widgetOrder.filter(function (i) {
      return i !== idx;
    }).map(function (pid) {
      return pid > idx ? pid - 1 : pid;
    })
  });
};

var reorderWidgetUpdater = exports.reorderWidgetUpdater = function reorderWidgetUpdater(state, _ref8) {
  var order = _ref8.order;
  return _objectSpread(_objectSpread({}, state), {}, {
    widgetOrder: order
  });
};
/**
 * Add a new layer
 * @memberof visStateUpdaters
 * @param {Object} state `visState`
 * @param {Object} action action
 * @param {Object} action.props - new layer props
 * @returns {Object} nextState
 * @public
 */


var addLayerUpdater = exports.addLayerUpdater = function addLayerUpdater(state, action) {
  var defaultDataset = Object.keys(state.datasets)[0];
  var newLayer = new _layers.Layer(_objectSpread({
    isVisible: true,
    isConfigActive: true,
    dataId: defaultDataset
  }, action.props));
  return _objectSpread(_objectSpread({}, state), {}, {
    layers: [].concat((0, _toConsumableArray2["default"])(state.layers), [newLayer]),
    layerData: [].concat((0, _toConsumableArray2["default"])(state.layerData), [{}]),
    layerOrder: [].concat((0, _toConsumableArray2["default"])(state.layerOrder), [state.layerOrder.length]),
    splitMaps: (0, _splitMapUtils.addNewLayersToSplitMap)(state.splitMaps, newLayer)
  });
};
/**
 * remove layer
 * @memberof visStateUpdaters
 * @param {Object} state `visState`
 * @param {Object} action action
 * @param {Number} action.idx index of layer to b e removed
 * @returns {Object} nextState
 * @public
 */


var removeLayerUpdater = exports.removeLayerUpdater = function removeLayerUpdater(state, _ref9) {
  var idx = _ref9.idx;
  var layers = state.layers,
      layerData = state.layerData,
      clicked = state.clicked,
      hoverInfo = state.hoverInfo;
  var layerToRemove = state.layers[idx];
  var newMaps = (0, _splitMapUtils.removeLayerFromSplitMaps)(state.splitMaps, layerToRemove);

  var newState = _objectSpread(_objectSpread({}, state), {}, {
    layers: [].concat((0, _toConsumableArray2["default"])(layers.slice(0, idx)), (0, _toConsumableArray2["default"])(layers.slice(idx + 1, layers.length))),
    layerData: [].concat((0, _toConsumableArray2["default"])(layerData.slice(0, idx)), (0, _toConsumableArray2["default"])(layerData.slice(idx + 1, layerData.length))),
    layerOrder: state.layerOrder.filter(function (i) {
      return i !== idx;
    }).map(function (pid) {
      return pid > idx ? pid - 1 : pid;
    }),
    clicked: layerToRemove.isLayerHovered(clicked) ? undefined : clicked,
    hoverInfo: layerToRemove.isLayerHovered(hoverInfo) ? undefined : hoverInfo,
    splitMaps: newMaps // TODO: update filters, create helper to remove layer form filter (remove layerid and dataid) if mapped

  });

  return updateAnimationDomain(newState);
};
/**
 * Reorder layer
 * @memberof visStateUpdaters
 * @param {Object} state `visState`
 * @param {Object} action action
 * @param {Array<Number>} action.order an array of layer indexes
 * @returns {Object} nextState
 * @public
 */


var reorderLayerUpdater = exports.reorderLayerUpdater = function reorderLayerUpdater(state, _ref10) {
  var order = _ref10.order;
  return _objectSpread(_objectSpread({}, state), {}, {
    layerOrder: order
  });
};
/**
 * Remove a dataset and all layers, filters, tooltip configs that based on it
 * @memberof visStateUpdaters
 * @param {Object} state `visState`
 * @param {Object} action action
 * @param {string} action.key dataset id
 * @returns {Object} nextState
 * @public
 */


var removeDatasetUpdater = exports.removeDatasetUpdater = function removeDatasetUpdater(state, action) {
  // extract dataset key
  var datasetKey = action.key;
  var datasets = state.datasets; // check if dataset is present

  if (!datasets[datasetKey]) {
    return state;
  }
  /* eslint-disable no-unused-vars */


  var layers = state.layers,
      widgets = state.widgets,
      _state$datasets = state.datasets,
      dataset = _state$datasets[datasetKey],
      newDatasets = (0, _objectWithoutProperties2["default"])(_state$datasets, [datasetKey].map(_toPropertyKey));
  /* eslint-enable no-unused-vars */

  var indexes = layers.reduce(function (listOfIndexes, layer, index) {
    if (layer.config.dataId === datasetKey) {
      listOfIndexes.push(index);
    }

    return listOfIndexes;
  }, []);
  var widgetIndexes = widgets.reduce(function (listOfIndexes, widget, index) {
    if (widget.config.dataId === datasetKey) {
      listOfIndexes.push(index);
    }

    return listOfIndexes;
  }, []); // remove layers and datasets

  var _indexes$reduce = indexes.reduce(function (_ref11, idx) {
    var currentState = _ref11.newState,
        indexCounter = _ref11.indexCounter;
    var currentIndex = idx - indexCounter;
    currentState = removeLayerUpdater(currentState, {
      idx: currentIndex
    });
    indexCounter++;
    return {
      newState: currentState,
      indexCounter: indexCounter
    };
  }, {
    newState: _objectSpread(_objectSpread({}, state), {}, {
      datasets: newDatasets
    }),
    indexCounter: 0
  }),
      newState = _indexes$reduce.newState; // remove widgets
  // newState = {
  //   ...newState,
  //   widgets: widgetIndexes.map(idx => [
  //     ...widgets.slice(0, idx),
  //     ...widgets.slice(idx + 1, widgets.length)
  //   ])
  // };
  // const widgets = state.widgets.filter(
  //   widget => widget.config.dataId !== datasetKey
  // );


  var _widgetIndexes$reduce = widgetIndexes.reduce(function (_ref12, idx) {
    var state = _ref12.finalState,
        indexCounter = _ref12.indexCounter;
    var currentIndex = idx - indexCounter;
    state = removeWidgetUpdater(state, {
      idx: currentIndex
    });
    indexCounter++;
    return {
      finalState: state,
      indexCounter: indexCounter
    };
  }, {
    finalState: _objectSpread({}, newState),
    indexCounter: 0
  }),
      finalState = _widgetIndexes$reduce.finalState; // remove filters


  var filters = state.filters.filter(function (filter) {
    return !datasetKey.includes(filter.dataId);
  }); // update interactionConfig

  var interactionConfig = state.interactionConfig;
  var _interactionConfig = interactionConfig,
      tooltip = _interactionConfig.tooltip;

  if (tooltip) {
    var config = tooltip.config;
    /* eslint-disable no-unused-vars */

    var _config$fieldsToShow2 = config.fieldsToShow,
        fields = _config$fieldsToShow2[datasetKey],
        fieldsToShow = (0, _objectWithoutProperties2["default"])(_config$fieldsToShow2, [datasetKey].map(_toPropertyKey));
    /* eslint-enable no-unused-vars */

    interactionConfig = _objectSpread(_objectSpread({}, interactionConfig), {}, {
      tooltip: _objectSpread(_objectSpread({}, tooltip), {}, {
        config: _objectSpread(_objectSpread({}, config), {}, {
          fieldsToShow: fieldsToShow
        })
      })
    });
  }

  return _objectSpread(_objectSpread({}, finalState), {}, {
    filters: filters,
    interactionConfig: interactionConfig
  });
};
/**
 * update layer blending mode
 * @memberof visStateUpdaters
 * @param {Object} state `visState`
 * @param {Object} action action
 * @param {string} action.mode one of `additive`, `normal` and `subtractive`
 * @returns {Object} nextState
 * @public
 */


var updateLayerBlendingUpdater = exports.updateLayerBlendingUpdater = function updateLayerBlendingUpdater(state, action) {
  return _objectSpread(_objectSpread({}, state), {}, {
    layerBlending: action.mode
  });
};
/**
 * Display dataset table in a modal
 * @memberof visStateUpdaters
 * @param {Object} state `visState`
 * @param {Object} action action
 * @param {string} action.dataId dataset id to show in table
 * @returns {Object} nextState
 * @public
 */


var showDatasetTableUpdater = exports.showDatasetTableUpdater = function showDatasetTableUpdater(state, action) {
  return _objectSpread(_objectSpread({}, state), {}, {
    editingDataset: action.dataId
  });
};
/**
 * reset visState to initial State
 * @memberof visStateUpdaters
 * @param {Object} state `visState`
 * @returns {Object} nextState
 * @public
 */


var resetMapConfigUpdater = exports.resetMapConfigUpdater = function resetMapConfigUpdater(state) {
  return _objectSpread(_objectSpread(_objectSpread({}, INITIAL_VIS_STATE), state.initialState), {}, {
    initialState: state.initialState
  });
};
/**
 * Propagate `visState` reducer with a new configuration. Current config will be override.
 * @memberof visStateUpdaters
 * @param {Object} state `visState`
 * @param {Object} action action
 * @param {Object} action.payload map config to be propagated
 * @param {Object} action.payload.config map config to be propagated
 * @param {Object} action.payload.option {keepExistingConfig: true | false}
 * @returns {Object} nextState
 * @public
 */


var receiveMapConfigUpdater = exports.receiveMapConfigUpdater = function receiveMapConfigUpdater(state, _ref13) {
  var _ref13$payload = _ref13.payload,
      _ref13$payload$config = _ref13$payload.config,
      config = _ref13$payload$config === void 0 ? {} : _ref13$payload$config,
      _ref13$payload$option = _ref13$payload.options,
      options = _ref13$payload$option === void 0 ? {} : _ref13$payload$option;

  if (!config.visState) {
    return state;
  }

  var _config$visState = config.visState,
      filters = _config$visState.filters,
      layers = _config$visState.layers,
      widgets = _config$visState.widgets,
      interactionConfig = _config$visState.interactionConfig,
      layerBlending = _config$visState.layerBlending,
      splitMaps = _config$visState.splitMaps,
      animationConfig = _config$visState.animationConfig;
  var keepExistingConfig = options.keepExistingConfig; // reset config if keepExistingConfig is falsy

  var mergedState = !keepExistingConfig ? resetMapConfigUpdater(state) : state;
  mergedState = (0, _visStateMerger.mergeFilters)(mergedState, filters); // console.log('After MergeFilters', mergedState);

  mergedState = (0, _visStateMerger.mergeLayers)(mergedState, layers); // console.log('After MergeLayers', mergedState);

  mergedState = (0, _visStateMerger.mergeInteractions)(mergedState, interactionConfig);
  mergedState = (0, _visStateMerger.mergeLayerBlending)(mergedState, layerBlending);
  mergedState = (0, _visStateMerger.mergeSplitMaps)(mergedState, splitMaps);
  mergedState = (0, _visStateMerger.mergeAnimationConfig)(mergedState, animationConfig);
  mergedState = (0, _visStateMerger.mergeWidgets)(mergedState, widgets);
  return mergedState;
};
/**
 * Trigger layer hover event with hovered object
 * @memberof visStateUpdaters
 * @param {Object} state `visState`
 * @param {Object} action action
 * @param {Object} action.info Object hovered, returned by deck.gl
 * @returns {Object} nextState
 * @public
 */


var layerHoverUpdater = exports.layerHoverUpdater = function layerHoverUpdater(state, action) {
  return _objectSpread(_objectSpread({}, state), {}, {
    hoverInfo: action.info
  });
};
/**
 * Trigger layer click event with clicked object
 * @memberof visStateUpdaters
 * @param {Object} state `visState`
 * @param {Object} action action
 * @param {Object} action.info Object clicked, returned by deck.gl
 * @returns {Object} nextState
 * @public
 */


var layerClickUpdater = exports.layerClickUpdater = function layerClickUpdater(state, action) {
  return _objectSpread(_objectSpread({}, state), {}, {
    mousePos: state.interactionConfig.coordinate.enabled ? _objectSpread(_objectSpread({}, state.mousePos), {}, {
      pinned: state.mousePos.pinned ? null : (0, _lodash["default"])(state.mousePos)
    }) : state.mousePos,
    clicked: action.info && action.info.picked ? action.info : null
  });
};
/**
 * Trigger map click event, unselect clicked object
 * @memberof visStateUpdaters
 * @param {Object} state `visState`
 * @returns {Object} nextState
 * @public
 */


var mapClickUpdater = exports.mapClickUpdater = function mapClickUpdater(state) {
  return _objectSpread(_objectSpread({}, state), {}, {
    clicked: null
  });
};

var mouseMoveUpdater = exports.mouseMoveUpdater = function mouseMoveUpdater(state, _ref14) {
  var evt = _ref14.evt;

  if (Object.values(state.interactionConfig).some(function (config) {
    return config.enabled;
  })) {
    return _objectSpread(_objectSpread({}, state), {}, {
      mousePos: _objectSpread(_objectSpread({}, state.mousePos), {}, {
        mousePosition: (0, _toConsumableArray2["default"])(evt.point),
        coordinate: (0, _toConsumableArray2["default"])(evt.lngLat)
      })
    });
  }

  return state;
};
/**
 * Toggle visibility of a layer for a split map
 * @memberof visStateUpdaters
 * @param {Object} state `visState`
 * @param {Object} action action
 * @param {Number|undefined} action.payload index of the split map
 * @returns {Object} nextState
 * @public
 */


var toggleSplitMapUpdater = exports.toggleSplitMapUpdater = function toggleSplitMapUpdater(state, action) {
  return state.splitMaps && state.splitMaps.length === 0 ? _objectSpread(_objectSpread({}, state), {}, {
    // maybe we should use an array to store state for a single map as well
    // if current maps length is equal to 0 it means that we are about to split the view
    splitMaps: (0, _splitMapUtils.computeSplitMapLayers)(state.layers)
  }) : closeSpecificMapAtIndex(state, action);
};
/**
 * Toggle visibility of a layer in a split map
 * @memberof visStateUpdaters
 * @param {Object} state
 * @param {Object} action
 * @param {Number} action.mapIndex index of the split map
 * @param {string} action.layerId id of the layer
 * @returns {Object} nextState
 * @public
 */


var toggleLayerForMapUpdater = exports.toggleLayerForMapUpdater = function toggleLayerForMapUpdater(state, _ref15) {
  var mapIndex = _ref15.mapIndex,
      layerId = _ref15.layerId;
  var splitMaps = state.splitMaps;
  return _objectSpread(_objectSpread({}, state), {}, {
    splitMaps: splitMaps.map(function (sm, i) {
      return i === mapIndex ? _objectSpread(_objectSpread({}, splitMaps[i]), {}, {
        layers: _objectSpread(_objectSpread({}, splitMaps[i].layers), {}, (0, _defineProperty2["default"])({}, layerId, !splitMaps[i].layers[layerId]))
      }) : sm;
    })
  });
};
/**
 * Add new dataset to `visState`, with option to load a map config along with the datasets
 * @memberof visStateUpdaters
 * @param {Object} state `visState`
 * @param {Object} action action
 * @param {Array<Object>|Object} action.datasets - ***required** datasets can be a dataset or an array of datasets
 * Each dataset object needs to have `info` and `data` property.
 * @param {Object} action.datasets.info -info of a dataset
 * @param {string} action.datasets.info.id - id of this dataset. If config is defined, `id` should matches the `dataId` in config.
 * @param {string} action.datasets.info.label - A display name of this dataset
 * @param {Object} action.datasets.data - ***required** The data object, in a tabular format with 2 properties `fields` and `rows`
 * @param {Array<Object>} action.datasets.data.fields - ***required** Array of fields,
 * @param {string} action.datasets.data.fields.name - ***required** Name of the field,
 * @param {Array<Array>} action.datasets.data.rows - ***required** Array of rows, in a tabular format with `fields` and `rows`
 * @param {Object} action.options option object `{centerMap: true, keepExistingConfig: false}`
 * @param {Object} action.config map config
 * @returns {Object} nextState
 * @public
 */

/* eslint-disable max-statements */


var updateVisDataUpdater = exports.updateVisDataUpdater = function updateVisDataUpdater(state, action) {
  // datasets can be a single data entries or an array of multiple data entries
  var config = action.config,
      options = action.options;
  var datasets = Array.isArray(action.datasets) ? action.datasets : [action.datasets];
  var newDateEntries = datasets.reduce(function (accu, _ref16) {
    var _ref16$info = _ref16.info,
        info = _ref16$info === void 0 ? {} : _ref16$info,
        data = _ref16.data;
    return _objectSpread(_objectSpread({}, accu), (0, _datasetUtils.createNewDataEntry)({
      info: info,
      data: data
    }, state.datasets) || {});
  }, {});

  if (!Object.keys(newDateEntries).length) {
    return state;
  } // apply config if passed from action


  var previousState = config ? receiveMapConfigUpdater(state, {
    payload: {
      config: config,
      options: options
    }
  }) : state;

  var stateWithNewData = _objectSpread(_objectSpread({}, previousState), {}, {
    datasets: _objectSpread(_objectSpread({}, previousState.datasets), newDateEntries)
  }); // previously saved config before data loaded


  var _stateWithNewData$fil = stateWithNewData.filterToBeMerged,
      filterToBeMerged = _stateWithNewData$fil === void 0 ? [] : _stateWithNewData$fil,
      _stateWithNewData$lay = stateWithNewData.layerToBeMerged,
      layerToBeMerged = _stateWithNewData$lay === void 0 ? [] : _stateWithNewData$lay,
      _stateWithNewData$wid = stateWithNewData.widgetToBeMerged,
      widgetToBeMerged = _stateWithNewData$wid === void 0 ? [] : _stateWithNewData$wid,
      _stateWithNewData$int = stateWithNewData.interactionToBeMerged,
      interactionToBeMerged = _stateWithNewData$int === void 0 ? {} : _stateWithNewData$int,
      _stateWithNewData$spl = stateWithNewData.splitMapsToBeMerged,
      splitMapsToBeMerged = _stateWithNewData$spl === void 0 ? [] : _stateWithNewData$spl; // merge state with saved layers
  // make sure layers are merged first

  var mergedState = (0, _visStateMerger.mergeLayers)(stateWithNewData, layerToBeMerged); // merge state with saved filters

  mergedState = (0, _visStateMerger.mergeFilters)(mergedState, filterToBeMerged); // merge state with saved splitMaps

  mergedState = (0, _visStateMerger.mergeSplitMaps)(mergedState, splitMapsToBeMerged);
  var newLayers = mergedState.layers.filter(function (l) {
    return l.config.dataId in newDateEntries;
  });

  if (!newLayers.length) {
    // no layer merged, find defaults
    var result = addDefaultLayers(mergedState, newDateEntries); // const result = mergedState;

    mergedState = result.state;
    newLayers = result.newLayers;
  } // if (mergedState.widgets.length === state.widgets.length) {
  //   mergedState = addDefaultWidget(mergedState, newDateEntries);
  // }


  if (mergedState.splitMaps.length) {
    // if map is split, add new layers to splitMaps
    newLayers = mergedState.layers.filter(function (l) {
      return l.config.dataId in newDateEntries;
    });
    mergedState = _objectSpread(_objectSpread({}, mergedState), {}, {
      splitMaps: (0, _splitMapUtils.addNewLayersToSplitMap)(mergedState.splitMaps, newLayers)
    });
  } // console.log(mergedState);
  // merge state with saved interactions


  mergedState = (0, _visStateMerger.mergeInteractions)(mergedState, interactionToBeMerged); // merge state with saved widgets

  mergedState = (0, _visStateMerger.mergeWidgets)(mergedState, widgetToBeMerged); // if no tooltips merged add default tooltips

  Object.keys(newDateEntries).forEach(function (dataId) {
    var tooltipFields = mergedState.interactionConfig.tooltip.config.fieldsToShow[dataId];

    if (!Array.isArray(tooltipFields) || !tooltipFields.length) {
      mergedState = addDefaultTooltips(mergedState, newDateEntries[dataId]);
    }
  });
  var updatedState = updateAllLayerDomainData(mergedState, Object.keys(newDateEntries)); // register layer animation domain,
  // need to be called after layer data is calculated

  updatedState = updateAnimationDomain(updatedState);
  return updatedState;
};
/* eslint-enable max-statements */

/**
 * Hide an existing layers from custom map layer objects
 * @param state
 * @param widget
 * @returns {[*,*]} Maps of custom layer objects
 */


function toggleWidgetFromSplitMaps(state, layer) {
  // console.log('0');
  return state.splitMaps.map(function (settings) {
    var widgets = settings.widgets;

    var newWidgets = _objectSpread(_objectSpread({}, widgets), {}, (0, _defineProperty2["default"])({}, widget.id, generateLayerMetaForSplitViews(widget)));

    return _objectSpread(_objectSpread({}, settings), {}, {
      widgets: newWidgets
    });
  });
}
/**
 * When a user clicks on the specific map closing icon
 * the application will close the selected map
 * and will merge the remaining one with the global state
 * TODO: i think in the future this action should be called merge map layers with global settings
 * @param {Object} state `visState`
 * @param {Object} action action
 * @returns {Object} nextState
 */


function closeSpecificMapAtIndex(state, action) {
  // retrieve layers meta data from the remaining map that we need to keep
  var indexToRetrieve = 1 - action.payload;
  var mapLayers = state.splitMaps[indexToRetrieve].layers;
  var layers = state.layers; // update layer visibility

  var newLayers = layers.map(function (layer) {
    return !mapLayers[layer.id] && layer.config.isVisible ? layer.updateLayerConfig({
      // if layer.id is not in mapLayers, it should be inVisible
      isVisible: false
    }) : layer;
  }); // delete map

  return _objectSpread(_objectSpread({}, state), {}, {
    layers: newLayers,
    splitMaps: []
  });
}
/**
 * Trigger file loading dispatch `addDataToMap` if succeed, or `loadFilesErr` if failed
 * @memberof visStateUpdaters
 * @param {Object} state `visState`
 * @param {Object} action action
 * @param {Array<Object>} action.files array of fileblob
 * @returns {Object} nextState
 * @public
 */


var loadFilesUpdater = exports.loadFilesUpdater = function loadFilesUpdater(state, action) {
  var files = action.files;
  var filesToLoad = files.map(function (fileBlob) {
    return (0, _fileUtils.processFileToLoad)(fileBlob);
  }); // reader -> parser -> augment -> receiveVisData
  // console.log('LOAD_FILE_TASK inside loadFilesUpdater', LOAD_FILE_TASK);

  var loadFileTasks = [_tasks["default"].all(filesToLoad.map(_tasks2.LOAD_FILE_TASK)).bimap(function (results) {
    var data = results.reduce(function (f, c) {
      return {
        // using concat here because the current datasets could be an array or a single item
        datasets: f.datasets.concat(c.datasets),
        // we need to deep merge this thing unless we find a better solution
        // this case will only happen if we allow to load multiple keplergl json files
        config: _objectSpread(_objectSpread({}, f.config), c.config || {})
      };
    }, {
      datasets: [],
      config: {},
      options: {
        centerMap: true
      }
    });
    return (0, _actions.addDataToMap)(data);
  }, _visStateActions.loadFilesErr)]; // console.log('loadFileTasks inside loadFilesUpdater', loadFileTasks);

  return (0, _tasks.withTask)(state, loadFileTasks);
};
/**
 * Trigger loading file error
 * @memberof visStateUpdaters
 * @param {Object} state `visState`
 * @param {Object} action action
 * @param {*} action.error
 * @returns {Object} nextState
 * @public
 */


var loadFilesErrUpdater = exports.loadFilesErrUpdater = function loadFilesErrUpdater(state, _ref17) {
  var error = _ref17.error;
  return _objectSpread(_objectSpread({}, state), {}, {
    fileLoading: false,
    fileLoadingErr: error
  });
};
/**
 *
 * @param {object} state `visState`
 * @param {object} action action
 * @param {Text<Object>} action.URL url of mapBox vector tiles
 * @returns {Object} nextState
 * @public
 */


function loadURLUpdater(state, action) {
  var URL = action.URL,
      range = action.range;
  var newLayer;

  if (URL) {
    var dataId = (0, _utils.generateHashId)(4);
    var datasets = (0, _defineProperty2["default"])({}, dataId, {
      URL: URL,
      populationRange: range,
      fields: [// {
        //   format: '',
        //   id: '_geojson',
        //   name: '_geojson',
        //   tableFieldIndex: 1,
        //   type: 'geojson'
        // },
        // {
        //   format: '',
        //   id: 'population',
        //   name: 'Population',
        //   tableFieldIndex: 2,
        //   type: 'integer'
        // }
      ],
      id: dataId,
      externalData: true,
      color: (0, _datasetUtils.getNewDatasetColor)(state.datasets),
      label: 'population data'
    });
    state = _objectSpread(_objectSpread(_objectSpread({}, state), state.datasets), {}, {
      datasets: datasets
    });
    newLayer = new state.layerClasses.MVT({
      isVisible: true,
      isConfigActive: true,
      dataId: dataId,
      url: URL
    }); // newLayer = new state.layerClasses['mvt']();
  }

  return _objectSpread(_objectSpread({}, state), {}, {
    layers: [].concat((0, _toConsumableArray2["default"])(state.layers), [newLayer]),
    layerData: [].concat((0, _toConsumableArray2["default"])(state.layerData), [{}]),
    layerOrder: [].concat((0, _toConsumableArray2["default"])(state.layerOrder), [state.layerOrder.length]),
    splitMaps: (0, _splitMapUtils.addNewLayersToSplitMap)(state.splitMaps, newLayer)
  });
}

var loadEDLinkData = exports.loadEDLinkData = function loadEDLinkData(state, action) {
  var data = action.data,
      dataId = action.dataId,
      idx = action.idx;
  var dataset = (0, _dataProcessor.processGeojson)(data);
  var validatedData = (0, _dataProcessor.validateInputData)(dataset);

  if (!validatedData) {
    return state;
  }

  var allData = validatedData.rows;
  var fields = validatedData.fields.map(function (f, i) {
    return _objectSpread(_objectSpread({}, f), {}, {
      id: f.name,
      tableFieldIndex: i + 1
    });
  }); // const idx = state.layers.findIndex(l => l.config.dataId === dataId);

  if (state.filters.length) {
    var filters = state.filters.map(function (filter) {
      if (filter.dataId === dataId) {
        var field = dataset.fields[filter.fieldIdx];
        filter = _objectSpread(_objectSpread(_objectSpread({}, filter), getFilterProps(allData, field)), {}, {
          value: filter.value
        });
      }

      return filter;
    });
    state = _objectSpread(_objectSpread({}, state), {}, {
      filters: filters
    });
  } // filters.map(f =>{
  //   var filter = f
  //   const field = dataset.fields[f.fieldIdx]
  //   filter ={
  //     ...filter,
  //     ...getFilterProps(dataset[allData],field)
  //   }
  // })
  // dataset = {
  //   ...dataset[dataId], allData: allData,
  //   fields: fields,
  //   data: allData.slice(), filteredIndex: allData.map((_, i) => i),
  //   filteredIndexForDomain: allData.map((_, i) => i),
  //   fieldPairs: findPointFieldPairs(fields)
  // }
  // let layerData =Object.assign(state.layerData);
  // layerData[idx] = data.features;


  var stateWithNewData = _objectSpread(_objectSpread({}, state), {}, {
    datasets: _objectSpread(_objectSpread({}, state.datasets), {}, (0, _defineProperty2["default"])({}, dataId, _objectSpread(_objectSpread(_objectSpread({}, state.datasets[dataId]), {}, {
      allData: allData,
      fields: fields
    }, (0, _filterUtils.filterTileLayerData)(allData, state.filters, state.layers.filter(function (l) {
      return l.config.dataId === dataId;
    }))), {}, {
      fieldPairs: (0, _datasetUtils.findPointFieldPairs)(fields)
    }))),
    layerData: state.layerData.map(function (lyrData, i) {
      return i === idx ? [data.features] : lyrData;
    })
  });

  return stateWithNewData;
};
/**
 * helper function to update All layer domain and layer data of state
 *
 * @param {object} state
 * @param {string} datasets
 * @returns {object} state
 */


function addDefaultLayers(state, datasets) {
  var defaultLayers = Object.values(datasets).reduce(function (accu, dataset) {
    return [].concat((0, _toConsumableArray2["default"])(accu), (0, _toConsumableArray2["default"])((0, _layerUtils.findDefaultLayer)(dataset, state.layerClasses) || []));
  }, []);
  return {
    state: _objectSpread(_objectSpread({}, state), {}, {
      layers: [].concat((0, _toConsumableArray2["default"])(state.layers), (0, _toConsumableArray2["default"])(defaultLayers)),
      layerOrder: [].concat((0, _toConsumableArray2["default"])(defaultLayers.map(function (_, i) {
        return state.layers.length + i;
      })), (0, _toConsumableArray2["default"])(state.layerOrder))
    }),
    newLayers: defaultLayers
  };
}
/**
 * helper function to update All layer domain and layer data of state
 *
 * @param {object} state
 * @param {string} datasets
 * @returns {object} state
 */
// export function addDefaultWidget(state, datasets) {
//   const defaultWidget = Object.values(datasets).reduce(
//     (accu, dataset) => [
//       ...accu,
//       ...(findDefaultLayer(dataset, state.widgetClasses) || [])
//     ],
//     []
//   );
//   return {
//     ...state,
//     widgets: [...state.widgets, ...defaultWidget],
//     layerOrder: [
//       // put new layers on top of old ones
//       ...defaultWidget.map((_, i) => state.widgets.length + i),
//       ...state.widgetOrder
//     ]
//   };
// }

/**
 * helper function to find default tooltips
 * @param {Object} state
 * @param {Object} dataset
 * @returns {Object} nextState
 */


function addDefaultTooltips(state, dataset) {
  var tooltipFields = (0, _interactionUtils.findFieldsToShow)(dataset);
  return _objectSpread(_objectSpread({}, state), {}, {
    interactionConfig: _objectSpread(_objectSpread({}, state.interactionConfig), {}, {
      tooltip: _objectSpread(_objectSpread({}, state.interactionConfig.tooltip), {}, {
        config: {
          // find default fields to show in tooltip
          fieldsToShow: _objectSpread(_objectSpread({}, state.interactionConfig.tooltip.config.fieldsToShow), tooltipFields)
        }
      })
    })
  });
}
/**
 * Helper function to update layer domains for an array of datasets
 * @param {Object} state
 * @param {Array|Array<string>} dataId dataset id or array of dataset ids
 * @param {Object} newFilter if is called by setFilter, the filter that has changed
 * @returns {Object} nextState
 */


function updateAllLayerDomainData(state, dataId, newFilter) {
  var dataIds = typeof dataId === 'string' ? [dataId] : dataId;
  var newLayers = [];
  var newLayerData = [];
  state.layers.forEach(function (oldLayer, i) {
    if (oldLayer.config.dataId && dataIds.includes(oldLayer.config.dataId)) {
      // No need to recalculate layer domain if filter has fixed domain
      var newLayer;

      if (oldLayer.type === 'boundary') {
        newLayer = newFilter && newFilter.fixedDomain ? oldLayer : oldLayer.updateLayerDomain(state.datasets[oldLayer.config.dataId], state.layerData[i], newFilter);
      } else {
        newLayer = newFilter && newFilter.fixedDomain ? oldLayer : oldLayer.updateLayerDomain(state.datasets[oldLayer.config.dataId], newFilter);
      }

      var _calculateLayerData5 = (0, _layerUtils.calculateLayerData)(newLayer, state, state.layerData[i]),
          layerData = _calculateLayerData5.layerData,
          layer = _calculateLayerData5.layer; // console.log('LayerData', layerData);


      newLayers.push(layer);
      newLayerData.push(layerData);
    } else {
      newLayers.push(oldLayer);
      newLayerData.push(state.layerData[i]);
    }
  });

  var newState = _objectSpread(_objectSpread({}, state), {}, {
    layers: newLayers,
    layerData: newLayerData
  });

  return newState;
}

function updateAnimationDomain(state) {
  // merge all animatable layer domain and update global config
  var animatableLayers = state.layers.filter(function (l) {
    return l.config.isVisible && l.config.animation && l.config.animation.enabled && Array.isArray(l.animationDomain);
  });

  if (!animatableLayers.length) {
    return _objectSpread(_objectSpread({}, state), {}, {
      animationConfig: defaultAnimationConfig
    });
  }

  var mergedDomain = animatableLayers.reduce(function (accu, layer) {
    return [Math.min(accu[0], layer.animationDomain[0]), Math.max(accu[1], layer.animationDomain[1])];
  }, [Number(Infinity), -Infinity]);
  return _objectSpread(_objectSpread({}, state), {}, {
    animationConfig: _objectSpread(_objectSpread({}, state.animationConfig), {}, {
      currentTime: (0, _filterUtils.isInRange)(state.animationConfig.currentTime, mergedDomain) ? state.animationConfig.currentTime : mergedDomain[0],
      domain: mergedDomain
    })
  });
}
/**
 * helper function to recalculte widget aggregationData everytime layerData is updated
 *
 * @param {object} state
 * @returns {object} state
 */


function updateWidgetAggregationData(state, mapState, auth, project) {
  var widgets = state.widgets;
  var newWidgets = [];
  widgets.map(function (w) {
    var _w$calculateAggregati = w.calculateAggregationData(w, state, mapState, auth, project),
        newWidget = _w$calculateAggregati.newWidget;

    newWidgets.push(newWidget);
  });
  return _objectSpread(_objectSpread({}, state), {}, {
    widgets: newWidgets
  });
}
/**
 * helper function to update states
 *
 * @param {object} state
 * @returns {object} state
 */


function updateStateWithLayerDataUpdater(state, action) {
  var collected = action.collected;
  var newLayer = action.layer;
  var idx = state.layers.findIndex(function (l) {
    return l.id === newLayer.id;
  });

  var _calculateLayerDataAf = (0, _layerUtils.calculateLayerDataAfterAPICall)(newLayer, state, state.layerData[idx], collected, {
    sameData: true
  }),
      layerData = _calculateLayerDataAf.layerData,
      layer = _calculateLayerDataAf.layer;

  return _objectSpread(_objectSpread({}, state), {}, {
    layerData: state.layerData.map(function (lyrData, i) {
      return i === idx ? layerData : lyrData;
    })
  });
}
/**
 * helper function for async API call
 *
 * @param {object} state
 * @returns {object} data
 */


function apiCallData(state, action) {
  // console.log(state, action);
  var layer = action.layer;
  var allData = state.datasets[layer.config.dataId].allData; // console.log(allData);

  return state;
}
/**
 * update dataset last run time
 * @memberof visStateUpdaters
 * @param state
 * @param {Object} payload
 * @return {Object} nextState
 */


function updateDatasetInfo(state, action) {
  var dataId = action.dataId,
      updatedAt = action.updatedAt;

  var newState = _objectSpread(_objectSpread({}, state), {}, {
    datasets: _objectSpread(_objectSpread({}, state.datasets), {}, (0, _defineProperty2["default"])({}, dataId, _objectSpread(_objectSpread({}, state.datasets[dataId]), {}, {
      lastUpdatedAt: updatedAt
    })))
  });

  return newState;
}
/**
 * Update the status of the editor
 * @memberof visStateUpdaters
 * @param {Object} state `visState`
 * @param {string} mode to set to editor to
 * @return {Object} nextState
 */


var setEditorModeUpdater = exports.setEditorModeUpdater = function setEditorModeUpdater(state, _ref18) {
  var mode = _ref18.mode;
  return _objectSpread(_objectSpread({}, state), {}, {
    editor: _objectSpread(_objectSpread({}, state.editor), {}, {
      mode: mode,
      selectedFeature: null
    })
  });
}; // const featureToFilterValue = (feature) => ({...feature, id: feature.id});

/**
 * Update editor features
 * @memberof visStateUpdaters
 * @param {Object} state `visState`
 * @param {[Object]} features to store
 * @return {Object} nextState
 */


function setFeaturesUpdater(state, _ref19) {
  var _ref19$features = _ref19.features,
      features = _ref19$features === void 0 ? [] : _ref19$features,
      auth = _ref19.auth,
      project = _ref19.project,
      mapState = _ref19.mapState;
  var lastFeature = features.length && features[features.length - 1];

  var newState = _objectSpread(_objectSpread({}, state), {}, {
    editor: _objectSpread(_objectSpread({}, state.editor), {}, {
      // only save none filter features to editor
      features: features.filter(function (f) {
        return !(0, _filterUtils.getFilterIdInFeature)(f);
      }),
      mode: lastFeature && lastFeature.properties.isClosed ? _defaultSettings.EDITOR_MODES.EDIT : state.editor.mode
    })
  }); // Retrieve existing feature


  var selectedFeature = state.editor.selectedFeature; // If no feature is selected we can simply return since no operations

  if (!selectedFeature) {
    return newState;
  } // TODO: check if the feature has changed


  var feature = features.find(function (f) {
    return f.id === selectedFeature.id;
  }); // if feature is part of a filter

  var filterId = feature && (0, _filterUtils.getFilterIdInFeature)(feature);

  if (filterId) {
    var featureValue = (0, _filterUtils.featureToFilterValue)(feature, filterId);
    var filterIdx = state.filters.findIndex(function (fil) {
      return fil.id === filterId;
    });
    return setFilterUpdater(newState, {
      idx: filterIdx,
      prop: 'value',
      value: featureValue,
      auth: auth,
      project: project,
      mapState: mapState
    });
  }

  return newState;
}
/**
 * Set the current selected feature
 * @memberof uiStateUpdaters
 * @param {Object} state `uiState`
 * @param {[Object]} features to store
 * @return {Object} nextState
 */


var setSelectedFeatureUpdater = exports.setSelectedFeatureUpdater = function setSelectedFeatureUpdater(state, _ref20) {
  var feature = _ref20.feature;
  return _objectSpread(_objectSpread({}, state), {}, {
    editor: _objectSpread(_objectSpread({}, state.editor), {}, {
      selectedFeature: feature
    })
  });
};
/**
 * Delete existing feature from filters
 * @memberof visStateUpdaters
 * @param {Object} state `visState`
 * @param {string} selectedFeatureId feature to delete
 * @return {Object} nextState
 */


function deleteFeatureUpdater(state, _ref21) {
  var feature = _ref21.feature;

  if (!feature) {
    return state;
  }

  var newState = _objectSpread(_objectSpread({}, state), {}, {
    editor: _objectSpread(_objectSpread({}, state.editor), {}, {
      selectedFeature: null
    })
  });

  if ((0, _filterUtils.getFilterIdInFeature)(feature)) {
    var filterIdx = newState.filters.findIndex(function (f) {
      return f.id === (0, _filterUtils.getFilterIdInFeature)(feature);
    });
    return filterIdx > -1 ? removeFilterUpdater(newState, {
      idx: filterIdx
    }) : newState;
  } // modify editor object


  var newEditor = _objectSpread(_objectSpread({}, state.editor), {}, {
    features: state.editor.features.filter(function (f) {
      return f.id !== feature.id;
    }),
    selectedFeature: null
  });

  return _objectSpread(_objectSpread({}, state), {}, {
    editor: newEditor
  });
}
/**
 * Toggle feature as layer filter
 * @memberof visStateUpdaters
 * @param state
 * @param {Object} payload
 * @param {string} payload.featureId
 * @param {Object} payload.layer
 * @return {Object} nextState
 */


function setPolygonFilterLayerUpdater(state, payload) {
  var layer = payload.layer,
      feature = payload.feature,
      auth = payload.auth,
      project = payload.project,
      mapState = payload.mapState;
  var filterId = (0, _filterUtils.getFilterIdInFeature)(feature); // let newFilter = null;

  var filterIdx;
  var newLayerId = [layer.id];
  var newState = state; // If polygon filter already exists, we need to find out if the current layer is already included

  if (filterId) {
    filterIdx = state.filters.findIndex(function (f) {
      return f.id === filterId;
    });

    if (!state.filters[filterIdx]) {
      // what if filter doesn't exist?... not possible.
      // because features in the editor is passed in from filters and editors.
      // but we will move this feature back to editor just in case
      var noneFilterFeature = _objectSpread(_objectSpread({}, feature), {}, {
        properties: _objectSpread(_objectSpread({}, feature.properties), {}, {
          filterId: null
        })
      });

      return _objectSpread(_objectSpread({}, state), {}, {
        editor: _objectSpread(_objectSpread({}, state.editor), {}, {
          features: [].concat((0, _toConsumableArray2["default"])(state.editor.features), [noneFilterFeature]),
          selectedFeature: noneFilterFeature
        })
      });
    }

    var _ref23 = state.filters[filterIdx] || [],
        layerId = _ref23.layerId;

    var isLayerIncluded = layerId.includes(layer.id);
    var filter = state.filters[filterIdx];
    newLayerId = isLayerIncluded ? // if layer is included, remove it
    filter.layerId.filter(function (l) {
      return l !== layer.id;
    }) : [].concat((0, _toConsumableArray2["default"])(filter.layerId), [layer.id]);
  } else {
    // if we haven't create the polygon filter, create it
    var newFilter = (0, _filterUtils.generatePolygonFilter)([], feature);
    filterIdx = state.filters.length; // add feature, remove feature from eidtor

    newState = _objectSpread(_objectSpread({}, state), {}, {
      filters: [].concat((0, _toConsumableArray2["default"])(state.filters), [newFilter]),
      editor: _objectSpread(_objectSpread({}, state.editor), {}, {
        features: state.editor.features.filter(function (f) {
          return f.id !== feature.id;
        }),
        selectedFeature: newFilter.value
      })
    });
  }

  return setFilterUpdater(newState, {
    idx: filterIdx,
    prop: 'layerId',
    value: newLayerId,
    auth: auth,
    project: project,
    mapState: mapState
  });
}
/**
 * Update editor
 * @param {Object} state `visState`
 * @param visible
 * @return {Object} nextState
 */


function toggleEditorVisibility(state, _ref24) {
  var visible = _ref24.visible;
  return _objectSpread(_objectSpread({}, state), {}, {
    editor: _objectSpread(_objectSpread({}, state.editor), {}, {
      visible: !state.editor.visible
    })
  });
}
//# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJzb3VyY2VzIjpbIi4uLy4uL3NyYy9yZWR1Y2Vycy92aXMtc3RhdGUtdXBkYXRlcnMuanMiXSwibmFtZXMiOlsiZGVmYXVsdEFuaW1hdGlvbkNvbmZpZyIsImRvbWFpbiIsImN1cnJlbnRUaW1lIiwic3BlZWQiLCJERUZBVUxUX0VESVRPUiIsIm1vZGUiLCJFRElUT1JfTU9ERVMiLCJEUkFXX1BPTFlHT04iLCJmZWF0dXJlcyIsInNlbGVjdGVkRmVhdHVyZSIsInZpc2libGUiLCJJTklUSUFMX1ZJU19TVEFURSIsImxheWVycyIsImxheWVyRGF0YSIsImxheWVyVG9CZU1lcmdlZCIsImxheWVyT3JkZXIiLCJmaWx0ZXJzIiwiZmlsdGVyVG9CZU1lcmdlZCIsIndpZGdldHMiLCJ3aWRnZXRUb0JlTWVyZ2VkIiwid2lkZ2V0T3JkZXIiLCJkYXRhc2V0cyIsImVkaXRpbmdEYXRhc2V0IiwidW5kZWZpbmVkIiwiaW50ZXJhY3Rpb25Db25maWciLCJpbnRlcmFjdGlvblRvQmVNZXJnZWQiLCJsYXllckJsZW5kaW5nIiwiaG92ZXJJbmZvIiwiY2xpY2tlZCIsIm1vdXNlUG9zIiwic3BsaXRNYXBzIiwibGF5ZXJDbGFzc2VzIiwiTGF5ZXJDbGFzc2VzIiwid2lkZ2V0Q2xhc3NlcyIsIldpZGdldENsYXNzZXMiLCJhbmltYXRpb25Db25maWciLCJlZGl0b3IiLCJ1cGRhdGVTdGF0ZVdpdGhXaWRnZXRBbmREYXRhIiwic3RhdGUiLCJ3aWRnZXQiLCJpZHgiLCJtYXAiLCJ3ZGd0IiwiaSIsIndpZGdldENvbmZpZ0NoYW5nZVVwZGF0ZXIiLCJhY3Rpb24iLCJvbGRXaWRnZXQiLCJhdXRoIiwicHJvamVjdCIsIm1hcFN0YXRlIiwibmV3Q29uZmlnIiwieCIsImZpbmRJbmRleCIsInciLCJpZCIsInByb3BzIiwiT2JqZWN0Iiwia2V5cyIsIm5ld1dpZGdldCIsInVwZGF0ZVdpZGdldENvbmZpZyIsIm5ld1N0YXRlIiwidG9nZ2xlV2lkZ2V0RnJvbVNwbGl0TWFwcyIsIndpZGdldFR5cGVDaGFuZ2VVcGRhdGVyIiwibmV3VHlwZSIsIm9sZElkIiwiQ29uc29sZSIsImVycm9yIiwiY29uZmlnIiwiYWdncmVnYXRlZERhdGEiLCJhc3NpZ25Db25maWdUb1dpZGdldCIsInZpc0NvbmZpZ1NldHRpbmdzIiwidXBkYXRlU3RhdGVXaXRoTGF5ZXJBbmREYXRhIiwibGF5ZXIiLCJseXIiLCJkIiwidXBkYXRlU3RhdGVPbkxheWVyVmlzaWJpbGl0eUNoYW5nZSIsImxlbmd0aCIsImlzVmlzaWJsZSIsImFuaW1hdGlvbiIsImVuYWJsZWQiLCJ1cGRhdGVBbmltYXRpb25Eb21haW4iLCJsYXllckNvbmZpZ0NoYW5nZVVwZGF0ZXIiLCJvbGRMYXllciIsImwiLCJuZXdMYXllciIsInVwZGF0ZUxheWVyQ29uZmlnIiwic2hvdWxkQ2FsY3VsYXRlTGF5ZXJEYXRhIiwib2xkTGF5ZXJEYXRhIiwidXBkYXRlTGF5ZXJEYXRhUmVzdWx0Iiwic2FtZURhdGEiLCJhZGRPclJlbW92ZVRleHRMYWJlbHMiLCJuZXdGaWVsZHMiLCJ0ZXh0TGFiZWwiLCJuZXdUZXh0TGFiZWwiLCJzbGljZSIsImN1cnJlbnRGaWVsZHMiLCJ0bCIsImZpZWxkIiwibmFtZSIsImZpbHRlciIsImFkZEZpZWxkcyIsImYiLCJpbmNsdWRlcyIsImRlbGV0ZUZpZWxkcyIsImZpbmQiLCJmZCIsIkRFRkFVTFRfVEVYVF9MQUJFTCIsImFmIiwidXBkYXRlVGV4dExhYmVsUHJvcEFuZFZhbHVlIiwicHJvcCIsInZhbHVlIiwiaGFzT3duUHJvcGVydHkiLCJzcGxpY2UiLCJsYXllclRleHRMYWJlbENoYW5nZVVwZGF0ZXIiLCJsYXllclR5cGVDaGFuZ2VVcGRhdGVyIiwiYXBpQ2FsbFJlcXVlc3QiLCJhc3NpZ25Db25maWdUb0xheWVyIiwiZGF0YUlkIiwiZGF0YXNldCIsInVwZGF0ZUxheWVyRG9tYWluIiwic2V0dGluZ3MiLCJvbGRMYXllck1hcCIsIm90aGVyTGF5ZXJzIiwibGF5ZXJWaXN1YWxDaGFubmVsQ2hhbmdlVXBkYXRlciIsImNoYW5uZWwiLCJ1cGRhdGVMYXllclZpc3VhbENoYW5uZWwiLCJsYXllclZpc0NvbmZpZ0NoYW5nZVVwZGF0ZXIiLCJuZXdWaXNDb25maWciLCJ2aXNDb25maWciLCJpbnRlcmFjdGlvbkNvbmZpZ0NoYW5nZVVwZGF0ZXIiLCJjb250cmFkaWN0IiwiZm9yRWFjaCIsImsiLCJzZXRGaWx0ZXJBUElVcGRhdGVyIiwidmFsdWVJbmRleCIsImhpc3RvZ3JhbSIsIm5ld0ZpbHRlciIsImRhdGFzZXRJZCIsIm1lcmdlRG9tYWluIiwidXBkYXRlZEZpbHRlciIsImFzc2lnbiIsInNldEZpbHRlclVwZGF0ZXIiLCJvbGRGaWx0ZXIiLCJkYXRhc2V0SWRzIiwiQXJyYXkiLCJpc0FycmF5IiwiRklMVEVSX1VQREFURVJfUFJPUFMiLCJuZXdEYXRhc2V0IiwibGF5ZXJJZCIsImxheWVySWREaWZmZXJlbmNlIiwibGF5ZXJEYXRhSWRzIiwibGlkIiwibmV3RGF0YUlkcyIsImVubGFyZ2VkRmlsdGVyIiwiZW5sYXJnZWQiLCJkYXRhc2V0SWRzVG9GaWx0ZXIiLCJMSU1JVEVEX0ZJTFRFUl9FRkZFQ1RfUFJPUFMiLCJ1cGRhdGVBbGxMYXllckRvbWFpbkRhdGEiLCJzZXRGaWx0ZXJQbG90VXBkYXRlciIsIm5ld1Byb3AiLCJwbG90VHlwZSIsImFsbERhdGEiLCJhZGRGaWx0ZXJVcGRhdGVyIiwibGF5ZXJDb2xvclVJQ2hhbmdlVXBkYXRlciIsInVwZGF0ZUxheWVyQ29sb3JVSSIsInRvZ2dsZUZpbHRlckFuaW1hdGlvblVwZGF0ZXIiLCJpc0FuaW1hdGluZyIsInVwZGF0ZUZpbHRlckFuaW1hdGlvblNwZWVkVXBkYXRlciIsInVwZGF0ZUFuaW1hdGlvblRpbWVVcGRhdGVyIiwidXBkYXRlTGF5ZXJBbmltYXRpb25TcGVlZFVwZGF0ZXIiLCJlbmxhcmdlRmlsdGVyVXBkYXRlciIsImlzRW5sYXJnZWQiLCJyZW1vdmVGaWx0ZXJVcGRhdGVyIiwibmV3RmlsdGVycyIsImZpbHRlcmVkRGF0YXNldHMiLCJ0eXBlIiwiRklMVEVSX1RZUEVTIiwicG9seWdvbiIsImFkZFdpZGdldFVwZGF0ZXIiLCJkZWZhdWx0RGF0YXNldCIsIldpZGdldCIsImlzQ29uZmlnQWN0aXZlIiwicmVtb3ZlV2lkZ2V0VXBkYXRlciIsInBpZCIsInJlb3JkZXJXaWRnZXRVcGRhdGVyIiwib3JkZXIiLCJhZGRMYXllclVwZGF0ZXIiLCJMYXllciIsInJlbW92ZUxheWVyVXBkYXRlciIsImxheWVyVG9SZW1vdmUiLCJuZXdNYXBzIiwiaXNMYXllckhvdmVyZWQiLCJyZW9yZGVyTGF5ZXJVcGRhdGVyIiwicmVtb3ZlRGF0YXNldFVwZGF0ZXIiLCJkYXRhc2V0S2V5Iiwia2V5IiwibmV3RGF0YXNldHMiLCJpbmRleGVzIiwicmVkdWNlIiwibGlzdE9mSW5kZXhlcyIsImluZGV4IiwicHVzaCIsIndpZGdldEluZGV4ZXMiLCJjdXJyZW50U3RhdGUiLCJpbmRleENvdW50ZXIiLCJjdXJyZW50SW5kZXgiLCJmaW5hbFN0YXRlIiwidG9vbHRpcCIsImZpZWxkc1RvU2hvdyIsImZpZWxkcyIsInVwZGF0ZUxheWVyQmxlbmRpbmdVcGRhdGVyIiwic2hvd0RhdGFzZXRUYWJsZVVwZGF0ZXIiLCJyZXNldE1hcENvbmZpZ1VwZGF0ZXIiLCJpbml0aWFsU3RhdGUiLCJyZWNlaXZlTWFwQ29uZmlnVXBkYXRlciIsInBheWxvYWQiLCJvcHRpb25zIiwidmlzU3RhdGUiLCJrZWVwRXhpc3RpbmdDb25maWciLCJtZXJnZWRTdGF0ZSIsImxheWVySG92ZXJVcGRhdGVyIiwiaW5mbyIsImxheWVyQ2xpY2tVcGRhdGVyIiwiY29vcmRpbmF0ZSIsInBpbm5lZCIsInBpY2tlZCIsIm1hcENsaWNrVXBkYXRlciIsIm1vdXNlTW92ZVVwZGF0ZXIiLCJldnQiLCJ2YWx1ZXMiLCJzb21lIiwibW91c2VQb3NpdGlvbiIsInBvaW50IiwibG5nTGF0IiwidG9nZ2xlU3BsaXRNYXBVcGRhdGVyIiwiY2xvc2VTcGVjaWZpY01hcEF0SW5kZXgiLCJ0b2dnbGVMYXllckZvck1hcFVwZGF0ZXIiLCJtYXBJbmRleCIsInNtIiwidXBkYXRlVmlzRGF0YVVwZGF0ZXIiLCJuZXdEYXRlRW50cmllcyIsImFjY3UiLCJkYXRhIiwicHJldmlvdXNTdGF0ZSIsInN0YXRlV2l0aE5ld0RhdGEiLCJzcGxpdE1hcHNUb0JlTWVyZ2VkIiwibmV3TGF5ZXJzIiwicmVzdWx0IiwiYWRkRGVmYXVsdExheWVycyIsInRvb2x0aXBGaWVsZHMiLCJhZGREZWZhdWx0VG9vbHRpcHMiLCJ1cGRhdGVkU3RhdGUiLCJuZXdXaWRnZXRzIiwiZ2VuZXJhdGVMYXllck1ldGFGb3JTcGxpdFZpZXdzIiwiaW5kZXhUb1JldHJpZXZlIiwibWFwTGF5ZXJzIiwibG9hZEZpbGVzVXBkYXRlciIsImZpbGVzIiwiZmlsZXNUb0xvYWQiLCJmaWxlQmxvYiIsImxvYWRGaWxlVGFza3MiLCJUYXNrIiwiYWxsIiwiTE9BRF9GSUxFX1RBU0siLCJiaW1hcCIsInJlc3VsdHMiLCJjIiwiY29uY2F0IiwiY2VudGVyTWFwIiwibG9hZEZpbGVzRXJyIiwibG9hZEZpbGVzRXJyVXBkYXRlciIsImZpbGVMb2FkaW5nIiwiZmlsZUxvYWRpbmdFcnIiLCJsb2FkVVJMVXBkYXRlciIsIlVSTCIsInJhbmdlIiwicG9wdWxhdGlvblJhbmdlIiwiZXh0ZXJuYWxEYXRhIiwiY29sb3IiLCJsYWJlbCIsIk1WVCIsInVybCIsImxvYWRFRExpbmtEYXRhIiwidmFsaWRhdGVkRGF0YSIsInJvd3MiLCJ0YWJsZUZpZWxkSW5kZXgiLCJmaWVsZElkeCIsImdldEZpbHRlclByb3BzIiwiZmllbGRQYWlycyIsImx5ckRhdGEiLCJkZWZhdWx0TGF5ZXJzIiwiXyIsImRhdGFJZHMiLCJuZXdMYXllckRhdGEiLCJmaXhlZERvbWFpbiIsImFuaW1hdGFibGVMYXllcnMiLCJhbmltYXRpb25Eb21haW4iLCJtZXJnZWREb21haW4iLCJNYXRoIiwibWluIiwibWF4IiwiTnVtYmVyIiwiSW5maW5pdHkiLCJ1cGRhdGVXaWRnZXRBZ2dyZWdhdGlvbkRhdGEiLCJjYWxjdWxhdGVBZ2dyZWdhdGlvbkRhdGEiLCJ1cGRhdGVTdGF0ZVdpdGhMYXllckRhdGFVcGRhdGVyIiwiY29sbGVjdGVkIiwiYXBpQ2FsbERhdGEiLCJ1cGRhdGVEYXRhc2V0SW5mbyIsInVwZGF0ZWRBdCIsImxhc3RVcGRhdGVkQXQiLCJzZXRFZGl0b3JNb2RlVXBkYXRlciIsInNldEZlYXR1cmVzVXBkYXRlciIsImxhc3RGZWF0dXJlIiwicHJvcGVydGllcyIsImlzQ2xvc2VkIiwiRURJVCIsImZlYXR1cmUiLCJmaWx0ZXJJZCIsImZlYXR1cmVWYWx1ZSIsImZpbHRlcklkeCIsImZpbCIsInNldFNlbGVjdGVkRmVhdHVyZVVwZGF0ZXIiLCJkZWxldGVGZWF0dXJlVXBkYXRlciIsIm5ld0VkaXRvciIsInNldFBvbHlnb25GaWx0ZXJMYXllclVwZGF0ZXIiLCJuZXdMYXllcklkIiwibm9uZUZpbHRlckZlYXR1cmUiLCJpc0xheWVySW5jbHVkZWQiLCJ0b2dnbGVFZGl0b3JWaXNpYmlsaXR5Il0sIm1hcHBpbmdzIjoiOzs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7O0FBb0JBOztBQUNBOztBQUNBOztBQUNBOztBQUNBOztBQUNBOztBQUNBOztBQUdBOztBQUdBOztBQUNBOztBQUdBOztBQUNBOztBQWlCQTs7QUFNQTs7QUFRQTs7QUFVQTs7QUFFQTs7QUFPQTs7QUFFQTs7QUFFQTs7QUFFQTs7QUFDQTs7QUFDQTs7Ozs7Ozs7Ozs7Ozs7QUFFQTtBQUNBO0FBQ0E7QUFFQTs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7OztBQW9DQTtBQUNBOztBQUNBOztBQUVPLElBQU1BLHNCQUFzQixvQ0FBRztBQUNwQ0MsRUFBQUEsTUFBTSxFQUFFLElBRDRCO0FBRXBDQyxFQUFBQSxXQUFXLEVBQUUsSUFGdUI7QUFHcENDLEVBQUFBLEtBQUssRUFBRTtBQUg2QixDQUEvQjtBQU1BLElBQU1DLGNBQWMsNEJBQUc7QUFDNUJDLEVBQUFBLElBQUksRUFBRUMsOEJBQWFDLFlBRFM7QUFF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Q3ZSLElBQUFBLElBQUksRUFBSkEsSUFKZ0M7QUFLaENDLElBQUFBLE9BQU8sRUFBUEEsT0FMZ0M7QUFNaENDLElBQUFBLFFBQVEsRUFBUkE7QUFOZ0MsR0FBWCxDQUF2QjtBQVFEO0FBRUQ7Ozs7Ozs7O0FBTU8sU0FBU3dSLHNCQUFULENBQWdDblMsS0FBaEMsVUFBa0Q7QUFBQSxNQUFWNUIsT0FBVSxVQUFWQSxPQUFVO0FBQ3ZELHlDQUNLNEIsS0FETDtBQUVFRixJQUFBQSxNQUFNLGtDQUNERSxLQUFLLENBQUNGLE1BREw7QUFFSjFCLE1BQUFBLE9BQU8sRUFBRSxDQUFDNEIsS0FBSyxDQUFDRixNQUFOLENBQWExQjtBQUZuQjtBQUZSO0FBT0QiLCJzb3VyY2VzQ29udGVudCI6WyIvLyBDb3B5cmlnaHQgKGMpIDIwMjMgVWJlciBUZWNobm9sb2dpZXMsIEluYy5cbi8vXG4vLyBQZXJtaXNzaW9uIGlzIGhlcmVieSBncmFudGVkLCBmcmVlIG9mIGNoYXJnZSwgdG8gYW55IHBlcnNvbiBvYnRhaW5pbmcgYSBjb3B5XG4vLyBvZiB0aGlzIHNvZnR3YXJlIGFuZCBhc3NvY2lhdGVkIGRvY3VtZW50YXRpb24gZmlsZXMgKHRoZSBcIlNvZnR3YXJlXCIpLCB0byBkZWFsXG4vLyBpbiB0aGUgU29mdHdhcmUgd2l0aG91dCByZXN0cmljdGlvbiwgaW5jbHVkaW5nIHdpdGhvdXQgbGltaXRhdGlvbiB0aGUgcmlnaHRzXG4vLyB0byB1c2UsIGNvcHksIG1vZGlmeSwgbWVyZ2UsIHB1Ymxpc2gsIGRpc3RyaWJ1dGUsIHN1YmxpY2Vuc2UsIGFuZC9vciBzZWxsXG4vLyBjb3BpZXMgb2YgdGhlIFNvZnR3YXJlLCBhbmQgdG8gcGVybWl0IHBlcnNvbnMgdG8gd2hvbSB0aGUgU29mdHdhcmUgaXNcbi8vIGZ1cm5pc2hlZCB0byBkbyBzbywgc3ViamVjdCB0byB0aGUgZm9sbG93aW5nIGNvbmRpdGlvbnM6XG4vL1xuLy8gVGhlIGFib3ZlIGNvcHlyaWdodCBub3RpY2UgYW5kIHRoaXMgcGVybWlzc2lvbiBub3RpY2Ugc2hhbGwgYmUgaW5jbHVkZWQgaW5cbi8vIGFsbCBjb3BpZXMgb3Igc3Vic3RhbnRpYWwgcG9ydGlvbnMgb2YgdGhlIFNvZnR3YXJlLlxuLy9cbi8vIFRIRSBTT0ZUV0FSRSBJUyBQUk9WSURFRCBcIkFTIElTXCIsIFdJVEhPVVQgV0FSUkFOVFkgT0YgQU5ZIEtJTkQsIEVYUFJFU1MgT1Jcbi8vIElNUExJRUQsIElOQ0xVRElORyBCVVQgTk9UIExJTUlURUQgVE8gVEhFIFdBUlJBTlRJRVMgT0YgTUVSQ0hBTlRBQklMSVRZLFxuLy8gRklUTkVTUyBGT1IgQSBQQVJUSUNVTEFSIFBVUlBPU0UgQU5EIE5PTklORlJJTkdFTUVOVC4gSU4gTk8gRVZFTlQgU0hBTEwgVEhFXG4vLyBBVVRIT1JTIE9SIENPUFlSSUdIVCBIT0xERVJTIEJFIExJQUJMRSBGT1IgQU5ZIENMQUlNLCBEQU1BR0VTIE9SIE9USEVSXG4vLyBMSUFCSUxJVFksIFdIRVRIRVIgSU4gQU4gQUNUSU9OIE9GIENPTlRSQUNULCBUT1JUIE9SIE9USEVSV0lTRSwgQVJJU0lORyBGUk9NLFxuLy8gT1VUIE9GIE9SIElOIENPTk5FQ1RJT04gV0lUSCBUSEUgU09GVFdBUkUgT1IgVEhFIFVTRSBPUiBPVEhFUiBERUFMSU5HUyBJTlxuLy8gVEhFIFNPRlRXQVJFLlxuXG5pbXBvcnQge2NvbnNvbGUgYXMgQ29uc29sZX0gZnJvbSAnZ2xvYmFsL3dpbmRvdyc7XG5pbXBvcnQgVGFzaywge2Rpc2FibGVTdGFja0NhcHR1cmluZywgd2l0aFRhc2t9IGZyb20gJ3JlYWN0LXBhbG0vdGFza3MnO1xuaW1wb3J0IGNsb25lRGVlcCBmcm9tICdsb2Rhc2guY2xvbmVkZWVwJztcbmltcG9ydCB1bmlxIGZyb20gJ2xvZGFzaC51bmlxJztcbmltcG9ydCBnZXQgZnJvbSAnbG9kYXNoLmdldCc7XG5pbXBvcnQgeG9yIGZyb20gJ2xvZGFzaC54b3InO1xuaW1wb3J0IHtzZXQsIHRvQXJyYXl9IGZyb20gJ3V0aWxzL3V0aWxzJztcblxuLy8gVGFza3NcbmltcG9ydCB7TE9BRF9GSUxFX1RBU0t9IGZyb20gJ3Rhc2tzL3Rhc2tzJztcblxuLy8gQWN0aW9uc1xuaW1wb3J0IHtsb2FkRmlsZXNFcnJ9IGZyb20gJ2FjdGlvbnMvdmlzLXN0YXRlLWFjdGlvbnMnO1xuaW1wb3J0IHthZGREYXRhVG9NYXB9IGZyb20gJ2FjdGlvbnMnO1xuXG4vLyBVdGlsc1xuaW1wb3J0IHtnZXREZWZhdWx0SW50ZXJhY3Rpb24sIGZpbmRGaWVsZHNUb1Nob3d9IGZyb20gJ3V0aWxzL2ludGVyYWN0aW9uLXV0aWxzJztcbmltcG9ydCB7XG4gIEZJTFRFUl9UWVBFUyxcbiAgRklMVEVSX1VQREFURVJfUFJPUFMsXG4gIExJTUlURURfRklMVEVSX0VGRkVDVF9QUk9QUyxcbiAgYXBwbHlGaWx0ZXJBcGlGaWVsZE5hbWUsXG4gIGFwcGx5RmlsdGVyRmllbGROYW1lLFxuICBhcHBseUZpbHRlcnNUb0RhdGFzZXRzLFxuICBnZW5lcmF0ZVBvbHlnb25GaWx0ZXIsXG4gIGdldERlZmF1bHRGaWx0ZXIsXG4gIGdldEZpbHRlclBsb3QsXG4gIGdldERlZmF1bHRGaWx0ZXJQbG90VHlwZSxcbiAgaXNJblJhbmdlLFxuICBnZXRGaWx0ZXJJZEluRmVhdHVyZSxcbiAgZmVhdHVyZVRvRmlsdGVyVmFsdWUsXG4gIHVwZGF0ZUZpbHRlckRhdGFJZFxufSBmcm9tICd1dGlscy9maWx0ZXItdXRpbHMnO1xuXG5pbXBvcnQge1xuICBjcmVhdGVOZXdEYXRhRW50cnksXG4gIGZpbmRQb2ludEZpZWxkUGFpcnMsXG4gIGdldE5ld0RhdGFzZXRDb2xvclxufSBmcm9tICd1dGlscy9kYXRhc2V0LXV0aWxzJztcblxuaW1wb3J0IHtcbiAgZmluZERlZmF1bHRMYXllcixcbiAgY2FsY3VsYXRlTGF5ZXJEYXRhLFxuICBjYWxjdWxhdGVMYXllckRhdGFBZnRlckFQSUNhbGxcbn0gZnJvbSAndXRpbHMvbGF5ZXItdXRpbHMvbGF5ZXItdXRpbHMnO1xuXG5pbXBvcnQge2ZpbHRlclRpbGVMYXllckRhdGF9IGZyb20gJ3V0aWxzL2ZpbHRlci11dGlscyc7XG5cbmltcG9ydCB7XG4gIG1lcmdlRmlsdGVycyxcbiAgbWVyZ2VMYXllcnMsXG4gIG1lcmdlSW50ZXJhY3Rpb25zLFxuICBtZXJnZUxheWVyQmxlbmRpbmcsXG4gIG1lcmdlU3BsaXRNYXBzLFxuICBtZXJnZUFuaW1hdGlvbkNvbmZpZyxcbiAgbWVyZ2VXaWRnZXRzXG59IGZyb20gJy4vdmlzLXN0YXRlLW1lcmdlcic7XG5cbmltcG9ydCBzaW1wbGlmeSBmcm9tICdzaW1wbGlmeS1nZW9qc29uJztcblxuaW1wb3J0IHtcbiAgYWRkTmV3TGF5ZXJzVG9TcGxpdE1hcCxcbiAgcmVtb3ZlTGF5ZXJGcm9tU3BsaXRNYXBzLFxuICBjb21wdXRlU3BsaXRNYXBMYXllcnNcbn0gZnJvbSAndXRpbHMvc3BsaXQtbWFwLXV0aWxzJztcbmltcG9ydCB7Z2VuZXJhdGVIYXNoSWR9IGZyb20gJ3V0aWxzL3V0aWxzJztcblxuaW1wb3J0IHtwcm9jZXNzR2VvanNvbiwgdmFsaWRhdGVJbnB1dERhdGF9IGZyb20gJ3Byb2Nlc3NvcnMvZGF0YS1wcm9jZXNzb3InO1xuXG5pbXBvcnQge0xheWVyLCBMYXllckNsYXNzZXN9IGZyb20gJ2xheWVycyc7XG5cbmltcG9ydCB7V2lkZ2V0LCBXaWRnZXRDbGFzc2VzfSBmcm9tICd3aWRnZXRzJztcblxuaW1wb3J0IHtwcm9jZXNzRmlsZVRvTG9hZH0gZnJvbSAnL3V0aWxzL2ZpbGUtdXRpbHMnO1xuaW1wb3J0IHtERUZBVUxUX1RFWFRfTEFCRUx9IGZyb20gJ2xheWVycy9sYXllci1mYWN0b3J5JztcbmltcG9ydCB7RURJVE9SX01PREVTfSBmcm9tICdjb25zdGFudHMvZGVmYXVsdC1zZXR0aW5ncyc7XG5cbi8vIHJlYWN0LXBhbG1cbi8vIGRpc2FibGUgY2FwdHVyZSBleGNlcHRpb24gZm9yIHJlYWN0LXBhbG0gY2FsbCB0byB3aXRoVGFza1xuZGlzYWJsZVN0YWNrQ2FwdHVyaW5nKCk7XG5cbi8qKlxuICogVXBkYXRlcnMgZm9yIGB2aXNTdGF0ZWAgcmVkdWNlci4gQ2FuIGJlIHVzZWQgaW4geW91ciByb290IHJlZHVjZXIgdG8gZGlyZWN0bHkgbW9kaWZ5IGtlcGxlci5nbCdzIHN0YXRlLlxuICogUmVhZCBtb3JlIGFib3V0IFtVc2luZyB1cGRhdGVyc10oLi4vYWR2YW5jZWQtdXNhZ2UvdXNpbmctdXBkYXRlcnMubWQpXG4gKlxuICogQHB1YmxpY1xuICogQGV4YW1wbGVcbiAqXG4gKiBpbXBvcnQga2VwbGVyR2xSZWR1Y2VyLCB7dmlzU3RhdGVVcGRhdGVyc30gZnJvbSAna2VwbGVyLmdsL3JlZHVjZXJzJztcbiAqIC8vIFJvb3QgUmVkdWNlclxuICogY29uc3QgcmVkdWNlcnMgPSBjb21iaW5lUmVkdWNlcnMoe1xuICogIGtlcGxlckdsOiBrZXBsZXJHbFJlZHVjZXIsXG4gKiAgYXBwOiBhcHBSZWR1Y2VyXG4gKiB9KTtcbiAqXG4gKiBjb25zdCBjb21wb3NlZFJlZHVjZXIgPSAoc3RhdGUsIGFjdGlvbikgPT4ge1xuICogIHN3aXRjaCAoYWN0aW9uLnR5cGUpIHtcbiAqICAgIGNhc2UgJ0NMSUNLX0JVVFRPTic6XG4gKiAgICAgIHJldHVybiB7XG4gKiAgICAgICAgLi4uc3RhdGUsXG4gKiAgICAgICAga2VwbGVyR2w6IHtcbiAqICAgICAgICAgIC4uLnN0YXRlLmtlcGxlckdsLFxuICogICAgICAgICAgZm9vOiB7XG4gKiAgICAgICAgICAgICAuLi5zdGF0ZS5rZXBsZXJHbC5mb28sXG4gKiAgICAgICAgICAgICB2aXNTdGF0ZTogdmlzU3RhdGVVcGRhdGVycy5lbmxhcmdlRmlsdGVyVXBkYXRlcihcbiAqICAgICAgICAgICAgICAgc3RhdGUua2VwbGVyR2wuZm9vLnZpc1N0YXRlLFxuICogICAgICAgICAgICAgICB7aWR4OiAwfVxuICogICAgICAgICAgICAgKVxuICogICAgICAgICAgfVxuICogICAgICAgIH1cbiAqICAgICAgfTtcbiAqICB9XG4gKiAgcmV0dXJuIHJlZHVjZXJzKHN0YXRlLCBhY3Rpb24pO1xuICogfTtcbiAqXG4gKiBleHBvcnQgZGVmYXVsdCBjb21wb3NlZFJlZHVjZXI7XG4gKi9cbi8qIGVzbGludC1kaXNhYmxlIG5vLXVudXNlZC12YXJzICovXG4vLyBjb25zdCB2aXNTdGF0ZVVwZGF0ZXJzID0gbnVsbDtcbi8qIGVzbGludC1lbmFibGUgbm8tdW51c2VkLXZhcnMgKi9cblxuZXhwb3J0IGNvbnN0IGRlZmF1bHRBbmltYXRpb25Db25maWcgPSB7XG4gIGRvbWFpbjogbnVsbCxcbiAgY3VycmVudFRpbWU6IG51bGwsXG4gIHNwZWVkOiAxXG59O1xuXG5leHBvcnQgY29uc3QgREVGQVVMVF9FRElUT1IgPSB7XG4gIG1vZGU6IEVESVRPUl9NT0RFUy5EUkFXX1BPTFlHT04sXG4gIGZlYXR1cmVzOiBbXSxcbiAgc2VsZWN0ZWRGZWF0dXJlOiBudWxsLFxuICB2aXNpYmxlOiB0cnVlXG59O1xuXG4vKipcbiAqIERlZmF1bHQgaW5pdGlhbCBgdmlzU3RhdGVgXG4gKiBAbWVtYmVyb2YgdmlzU3RhdGVVcGRhdGVyc1xuICogQGNvbnN0YW50XG4gKiBAdHlwZSB7T2JqZWN0fVxuICogQHByb3BlcnR5IHtBcnJheX0gbGF5ZXJzXG4gKiBAcHJvcGVydHkge0FycmF5fSBsYXllckRhdGFcbiAqIEBwcm9wZXJ0eSB7QXJyYXl9IGxheWVyVG9CZU1lcmdlZFxuICogQHByb3BlcnR5IHtBcnJheX0gbGF5ZXJPcmRlclxuICogQHByb3BlcnR5IHtBcnJheX0gZmlsdGVyc1xuICogQHByb3BlcnR5IHtBcnJheX0gZmlsdGVyVG9CZU1lcmdlZFxuICogQHByb3BlcnR5IHtBcnJheX0gZGF0YXNldHNcbiAqIEBwcm9wZXJ0eSB7c3RyaW5nfSBlZGl0aW5nRGF0YXNldFxuICogQHByb3BlcnR5IHtPYmplY3R9IGludGVyYWN0aW9uQ29uZmlnXG4gKiBAcHJvcGVydHkge09iamVjdH0gaW50ZXJhY3Rpb25Ub0JlTWVyZ2VkXG4gKiBAcHJvcGVydHkge3N0cmluZ30gbGF5ZXJCbGVuZGluZ1xuICogQHByb3BlcnR5IHtPYmplY3R9IGhvdmVySW5mb1xuICogQHByb3BlcnR5IHtPYmplY3R9IGNsaWNrZWRcbiAqIEBwcm9wZXJ0eSB7T2JqZWN0fSBtb3VzZVBvc1xuICogQHByb3BlcnR5IHtBcnJheX0gc3BsaXRNYXBzIC0gYSBsaXN0IG9mIG9iamVjdHMgb2YgbGF5ZXIgYXZhaWxhYmlsaXRpZXMgYW5kIHZpc2liaWxpdGllcyBmb3IgZWFjaCBtYXBcbiAqIEBwcm9wZXJ0eSB7T2JqZWN0fSBsYXllckNsYXNzZXNcbiAqIEBwcm9wZXJ0eSB7T2JqZWN0fSBhbmltYXRpb25Db25maWdcbiAqIEBwcm9wZXJ0eSB7T2JqZWN0fSBlZGl0b3JcbiAqIEBwdWJsaWNcbiAqL1xuZXhwb3J0IGNvbnN0IElOSVRJQUxfVklTX1NUQVRFID0ge1xuICAvLyBsYXllcnNcbiAgbGF5ZXJzOiBbXSxcbiAgbGF5ZXJEYXRhOiBbXSxcbiAgbGF5ZXJUb0JlTWVyZ2VkOiBbXSxcbiAgbGF5ZXJPcmRlcjogW10sXG5cbiAgLy8gZmlsdGVyc1xuICBmaWx0ZXJzOiBbXSxcbiAgZmlsdGVyVG9CZU1lcmdlZDogW10sXG5cbiAgLy8gd2lkZ2V0c1xuICB3aWRnZXRzOiBbXSxcbiAgd2lkZ2V0VG9CZU1lcmdlZDogW10sXG4gIHdpZGdldE9yZGVyOiBbXSxcblxuICAvLyBhIGNvbGxlY3Rpb24gb2YgbXVsdGlwbGUgZGF0YXNldFxuICBkYXRhc2V0czoge30sXG4gIGVkaXRpbmdEYXRhc2V0OiB1bmRlZmluZWQsXG5cbiAgaW50ZXJhY3Rpb25Db25maWc6IGdldERlZmF1bHRJbnRlcmFjdGlvbigpLFxuICBpbnRlcmFjdGlvblRvQmVNZXJnZWQ6IHVuZGVmaW5lZCxcblxuICBsYXllckJsZW5kaW5nOiAnbm9ybWFsJyxcbiAgaG92ZXJJbmZvOiB1bmRlZmluZWQsXG4gIGNsaWNrZWQ6IHVuZGVmaW5lZCxcbiAgbW91c2VQb3M6IHt9LFxuXG4gIC8vIHRoaXMgaXMgdXNlZCB3aGVuIHVzZXIgc3BsaXQgbWFwc1xuICBzcGxpdE1hcHM6IFtcbiAgICAvLyB0aGlzIHdpbGwgY29udGFpbiBhIGxpc3Qgb2Ygb2JqZWN0cyB0b1xuICAgIC8vIGRlc2NyaWJlIHRoZSBzdGF0ZSBvZiBsYXllciBhdmFpbGFiaWxpdHkgYW5kIHZpc2liaWxpdHkgZm9yIGVhY2ggbWFwXG4gICAgLy8gW1xuICAgIC8vICAge1xuICAgIC8vICAgICAgbGF5ZXJzOiB7bGF5ZXJfaWQ6IHRydWUgfCBmYWxzZX1cbiAgICAvLyAgIH1cbiAgICAvLyBdXG4gIF0sXG4gIC8vXG4gIC8vIGRlZmF1bHRzIGxheWVyIGNsYXNzZXNcbiAgbGF5ZXJDbGFzc2VzOiBMYXllckNsYXNzZXMsXG5cbiAgLy8gZGVmYXVsdCB3aWRnZXQgY2xhc3Nlc1xuICB3aWRnZXRDbGFzc2VzOiBXaWRnZXRDbGFzc2VzLFxuXG4gIC8vIGRlZmF1bHQgYW5pbWF0aW9uXG4gIC8vIHRpbWUgaW4gdW5peCB0aW1lc3RhbXAgKG1pbGxpc2Vjb25kcykgKHRoZSBudW1iZXIgb2Ygc2Vjb25kcyBzaW5jZSB0aGUgVW5peCBFcG9jaClcbiAgYW5pbWF0aW9uQ29uZmlnOiBkZWZhdWx0QW5pbWF0aW9uQ29uZmlnLFxuXG4gIGVkaXRvcjogREVGQVVMVF9FRElUT1Jcbn07XG5cbmZ1bmN0aW9uIHVwZGF0ZVN0YXRlV2l0aFdpZGdldEFuZERhdGEoc3RhdGUsIHt3aWRnZXQsIGlkeH0pIHtcbiAgcmV0dXJuIHtcbiAgICAuLi5zdGF0ZSxcbiAgICB3aWRnZXRzOiBzdGF0ZS53aWRnZXRzLm1hcCgod2RndCwgaSkgPT4gKGkgPT09IGlkeCA/IHdpZGdldCA6IHdkZ3QpKVxuICB9O1xufVxuXG4vKipcbiAqIENhbGxlZCB0byB1cGRhdGUgbGF5ZXIgYmFzZSBjb25maWc6IGRhdGFJZCwgbGFiZWwsIGNvbHVtbiwgaXNWaXNpYmxlXG4gKlxuICovXG5leHBvcnQgZnVuY3Rpb24gd2lkZ2V0Q29uZmlnQ2hhbmdlVXBkYXRlcihzdGF0ZSwgYWN0aW9uKSB7XG4gIGNvbnN0IHtvbGRXaWRnZXQsIGF1dGgsIHByb2plY3R9ID0gYWN0aW9uO1xuICBjb25zdCB7bWFwU3RhdGV9ID0gYWN0aW9uLm5ld0NvbmZpZztcbiAgY29uc3QgeCA9IHN0YXRlLndpZGdldHMuZmluZEluZGV4KHcgPT4gdy5pZCA9PT0gb2xkV2lkZ2V0LmlkKTtcbiAgY29uc3QgcHJvcHMgPSBPYmplY3Qua2V5cyhhY3Rpb24ubmV3Q29uZmlnKTtcbiAgYWN0aW9uLm5ld0NvbmZpZy5tYXBTdGF0ZSA/IGRlbGV0ZSBhY3Rpb24ubmV3Q29uZmlnLm1hcFN0YXRlIDogbnVsbDtcbiAgY29uc3QgbmV3V2lkZ2V0ID0gb2xkV2lkZ2V0LnVwZGF0ZVdpZGdldENvbmZpZyhhY3Rpb24ubmV3Q29uZmlnKTtcbiAgLy8gaWYgKG5ld1dpZGdldC5zaG91bGRDYWxjdWxhdGVBZ2dyZWdhdGVkRGF0YShwcm9wcykpIHtcbiAgLy8gY29uc3QgYWdncmVnYXRlZERhdGEgPSBuZXdXaWRnZXQuY2FsY3VsYXRlQWdncmVnYXRpb25EYXRhKFxuICAvLyAgIG5ld1dpZGdldCxcbiAgLy8gICBzdGF0ZS5maWx0ZXJzLFxuICAvLyAgIHN0YXRlLmRhdGFzZXRzLFxuICAvLyAgIG1hcFN0YXRlLFxuICAvLyAgIGF1dGgsXG4gIC8vICAgcHJvamVjdFxuICAvLyApO1xuXG4gIC8vIG5ld1dpZGdldC51cGRhdGVXaWRnZXRDb25mZyh7YXBpQ2FsbFJlcXVlc3Q6IHRydWV9KTtcbiAgLy8gcmV0dXJuIHVwZGF0ZVN0YXRlV2l0aFdpZGdldEFuZERhdGEodXBkYXRlZFN0YXRlID8gdXBkYXRlZFN0YXRlIDogc3RhdGUsIHtcbiAgLy8gICB3aWRnZXQ6IG5ld1dpZGdldCxcbiAgLy8gICB4XG4gIC8vIH0pO1xuICAvLyB9XG5cbiAgY29uc3QgbmV3U3RhdGUgPSB7XG4gICAgLi4uc3RhdGUsXG4gICAgc3BsaXRNYXBzOlxuICAgICAgJ2lzVmlzaWJsZScgaW4gYWN0aW9uLm5ld0NvbmZpZ1xuICAgICAgICA/IHRvZ2dsZVdpZGdldEZyb21TcGxpdE1hcHMoc3RhdGUsIHdpZGdldClcbiAgICAgICAgOiBzdGF0ZS5zcGxpdE1hcHNcbiAgfTtcbiAgcmV0dXJuIHVwZGF0ZVN0YXRlV2l0aFdpZGdldEFuZERhdGEobmV3U3RhdGUsIHt3aWRnZXQ6IG5ld1dpZGdldCwgeH0pO1xufVxuXG5leHBvcnQgZnVuY3Rpb24gd2lkZ2V0VHlwZUNoYW5nZVVwZGF0ZXIoc3RhdGUsIGFjdGlvbikge1xuICBjb25zdCB7b2xkV2lkZ2V0LCBuZXdUeXBlfSA9IGFjdGlvbjtcbiAgY29uc3Qgb2xkSWQgPSBvbGRXaWRnZXQuaWQ7XG4gIGNvbnN0IGlkeCA9IHN0YXRlLndpZGdldHMuZmluZEluZGV4KHcgPT4gdy5pZCA9PT0gb2xkSWQpO1xuICBpZiAoIXN0YXRlLndpZGdldENsYXNzZXNbbmV3VHlwZV0pIHtcbiAgICBDb25zb2xlLmVycm9yKGAke25ld1R5cGV9IGlzIG5vdCBhIHZhbGlkIHdpZGdldCB0eXBlYCk7XG4gICAgcmV0dXJuIHN0YXRlO1xuICB9XG4gIC8vIGdldCBhIG1pbnQgd2lkZ2V0LCB3aXRoIG5ldyBpZCBhbmQgdHlwZVxuICAvLyBiZWNhdXNlIGRlY2suZ2wgdXNlcyBpZCB0byBtYXRjaCBiZXR3ZWVuIG5ldyBhbmQgb2xkIGxheWVyLlxuICAvLyBJZiB0eXBlIGhhcyBjaGFuZ2VkIGJ1dCBpZCBpcyB0aGUgc2FtZSwgaXQgd2lsbCBicmVha1xuICB2YXIgbmV3V2lkZ2V0ID0gbmV3IHN0YXRlLndpZGdldENsYXNzZXNbbmV3VHlwZV0oKTtcbiAgbmV3V2lkZ2V0LmNvbmZpZy5hZ2dyZWdhdGVkRGF0YSA9IG51bGw7XG4gIG5ld1dpZGdldC5hc3NpZ25Db25maWdUb1dpZGdldChvbGRXaWRnZXQuY29uZmlnLCBvbGRXaWRnZXQudmlzQ29uZmlnU2V0dGluZ3MpO1xuXG4gIGNvbnN0IG5ld1N0YXRlID0gc3RhdGU7XG4gIGNvbnN0IHdpZGdldCA9IG5ld1dpZGdldDtcbiAgcmV0dXJuIHVwZGF0ZVN0YXRlV2l0aFdpZGdldEFuZERhdGEobmV3U3RhdGUsIHt3aWRnZXQsIGlkeH0pO1xufVxuXG5mdW5jdGlvbiB1cGRhdGVTdGF0ZVdpdGhMYXllckFuZERhdGEoc3RhdGUsIHtsYXllckRhdGEsIGxheWVyLCBpZHh9KSB7XG4gIHJldHVybiB7XG4gICAgLi4uc3RhdGUsXG4gICAgbGF5ZXJzOiBzdGF0ZS5sYXllcnMubWFwKChseXIsIGkpID0+IChpID09PSBpZHggPyBsYXllciA6IGx5cikpLFxuICAgIGxheWVyRGF0YTogbGF5ZXJEYXRhXG4gICAgICA/IHN0YXRlLmxheWVyRGF0YS5tYXAoKGQsIGkpID0+IChpID09PSBpZHggPyBsYXllckRhdGEgOiBkKSlcbiAgICAgIDogc3RhdGUubGF5ZXJEYXRhXG4gIH07XG59XG5cbmV4cG9ydCBmdW5jdGlvbiB1cGRhdGVTdGF0ZU9uTGF5ZXJWaXNpYmlsaXR5Q2hhbmdlKHN0YXRlLCBsYXllcikge1xuICBsZXQgbmV3U3RhdGUgPSBzdGF0ZTtcbiAgaWYgKHN0YXRlLnNwbGl0TWFwcy5sZW5ndGgpIHtcbiAgICBuZXdTdGF0ZSA9IHtcbiAgICAgIC4uLnN0YXRlLFxuICAgICAgc3BsaXRNYXBzOiBsYXllci5jb25maWcuaXNWaXNpYmxlXG4gICAgICAgID8gYWRkTmV3TGF5ZXJzVG9TcGxpdE1hcChzdGF0ZS5zcGxpdE1hcHMsIGxheWVyKVxuICAgICAgICA6IHJlbW92ZUxheWVyRnJvbVNwbGl0TWFwcyhzdGF0ZS5zcGxpdE1hcHMsIGxheWVyKVxuICAgIH07XG4gIH1cblxuICBpZiAobGF5ZXIuY29uZmlnLmFuaW1hdGlvbi5lbmFibGVkKSB7XG4gICAgbmV3U3RhdGUgPSB1cGRhdGVBbmltYXRpb25Eb21haW4oc3RhdGUpO1xuICB9XG5cbiAgcmV0dXJuIG5ld1N0YXRlO1xufVxuXG4vKipcbiAqIFVwZGF0ZSBsYXllciBiYXNlIGNvbmZpZzogZGF0YUlkLCBsYWJlbCwgY29sdW1uLCBpc1Zpc2libGVcbiAqIEBtZW1iZXJvZiB2aXNTdGF0ZVVwZGF0ZXJzXG4gKiBAcGFyYW0ge09iamVjdH0gc3RhdGUgYHZpc1N0YXRlYFxuICogQHBhcmFtIHtPYmplY3R9IGFjdGlvbiBhY3Rpb25cbiAqIEBwYXJhbSB7T2JqZWN0fSBhY3Rpb24ub2xkTGF5ZXIgbGF5ZXIgdG8gYmUgdXBkYXRlZFxuICogQHBhcmFtIHtPYmplY3R9IGFjdGlvbi5uZXdDb25maWcgbmV3IGNvbmZpZ1xuICogQHJldHVybnMge09iamVjdH0gbmV4dFN0YXRlXG4gKi9cbmV4cG9ydCBmdW5jdGlvbiBsYXllckNvbmZpZ0NoYW5nZVVwZGF0ZXIoc3RhdGUsIGFjdGlvbikge1xuICBjb25zdCB7b2xkTGF5ZXJ9ID0gYWN0aW9uO1xuICBjb25zdCBpZHggPSBzdGF0ZS5sYXllcnMuZmluZEluZGV4KGwgPT4gbC5pZCA9PT0gb2xkTGF5ZXIuaWQpO1xuICBjb25zdCBwcm9wcyA9IE9iamVjdC5rZXlzKGFjdGlvbi5uZXdDb25maWcpO1xuICBsZXQgbmV3TGF5ZXIgPSBvbGRMYXllci51cGRhdGVMYXllckNvbmZpZyhhY3Rpb24ubmV3Q29uZmlnKTtcblxuICBsZXQgbGF5ZXJEYXRhO1xuXG4gIC8vIGxldCBuZXdMYXllcjtcbiAgaWYgKG5ld0xheWVyLnNob3VsZENhbGN1bGF0ZUxheWVyRGF0YShwcm9wcykpIHtcbiAgICBjb25zdCBvbGRMYXllckRhdGEgPSBzdGF0ZS5sYXllckRhdGFbaWR4XTtcbiAgICBjb25zdCB1cGRhdGVMYXllckRhdGFSZXN1bHQgPSBjYWxjdWxhdGVMYXllckRhdGEoXG4gICAgICBuZXdMYXllcixcbiAgICAgIHN0YXRlLFxuICAgICAgb2xkTGF5ZXJEYXRhLFxuICAgICAge1xuICAgICAgICBzYW1lRGF0YTogdHJ1ZVxuICAgICAgfVxuICAgICk7XG5cbiAgICBsYXllckRhdGEgPSB1cGRhdGVMYXllckRhdGFSZXN1bHQubGF5ZXJEYXRhO1xuICAgIG5ld0xheWVyID0gdXBkYXRlTGF5ZXJEYXRhUmVzdWx0LmxheWVyO1xuICB9XG5cbiAgbGV0IG5ld1N0YXRlID0gc3RhdGU7XG4gIGlmICgnaXNWaXNpYmxlJyBpbiBhY3Rpb24ubmV3Q29uZmlnKSB7XG4gICAgbmV3U3RhdGUgPSB1cGRhdGVTdGF0ZU9uTGF5ZXJWaXNpYmlsaXR5Q2hhbmdlKHN0YXRlLCBuZXdMYXllcik7XG4gIH1cblxuICByZXR1cm4gdXBkYXRlU3RhdGVXaXRoTGF5ZXJBbmREYXRhKG5ld1N0YXRlLCB7XG4gICAgbGF5ZXI6IG5ld0xheWVyLFxuICAgIGxheWVyRGF0YSxcbiAgICBpZHhcbiAgfSk7XG59XG5cbmZ1bmN0aW9uIGFkZE9yUmVtb3ZlVGV4dExhYmVscyhuZXdGaWVsZHMsIHRleHRMYWJlbCkge1xuICBsZXQgbmV3VGV4dExhYmVsID0gdGV4dExhYmVsLnNsaWNlKCk7XG5cbiAgY29uc3QgY3VycmVudEZpZWxkcyA9IHRleHRMYWJlbFxuICAgIC5tYXAodGwgPT4gdGwuZmllbGQgJiYgdGwuZmllbGQubmFtZSlcbiAgICAuZmlsdGVyKGQgPT4gZCk7XG5cbiAgY29uc3QgYWRkRmllbGRzID0gbmV3RmllbGRzLmZpbHRlcihmID0+ICFjdXJyZW50RmllbGRzLmluY2x1ZGVzKGYubmFtZSkpO1xuICBjb25zdCBkZWxldGVGaWVsZHMgPSBjdXJyZW50RmllbGRzLmZpbHRlcihcbiAgICBmID0+ICFuZXdGaWVsZHMuZmluZChmZCA9PiBmZC5uYW1lID09PSBmKVxuICApO1xuXG4gIC8vIGRlbGV0ZVxuICBuZXdUZXh0TGFiZWwgPSBuZXdUZXh0TGFiZWwuZmlsdGVyKFxuICAgIHRsID0+IHRsLmZpZWxkICYmICFkZWxldGVGaWVsZHMuaW5jbHVkZXModGwuZmllbGQubmFtZSlcbiAgKTtcbiAgbmV3VGV4dExhYmVsID0gIW5ld1RleHRMYWJlbC5sZW5ndGggPyBbREVGQVVMVF9URVhUX0xBQkVMXSA6IG5ld1RleHRMYWJlbDtcblxuICAvLyBhZGRcbiAgbmV3VGV4dExhYmVsID0gW1xuICAgIC4uLm5ld1RleHRMYWJlbC5maWx0ZXIodGwgPT4gdGwuZmllbGQpLFxuICAgIC4uLmFkZEZpZWxkcy5tYXAoYWYgPT4gKHtcbiAgICAgIC4uLkRFRkFVTFRfVEVYVF9MQUJFTCxcbiAgICAgIGZpZWxkOiBhZlxuICAgIH0pKVxuICBdO1xuXG4gIHJldHVybiBuZXdUZXh0TGFiZWw7XG59XG5cbmZ1bmN0aW9uIHVwZGF0ZVRleHRMYWJlbFByb3BBbmRWYWx1ZShpZHgsIHByb3AsIHZhbHVlLCB0ZXh0TGFiZWwpIHtcbiAgaWYgKCF0ZXh0TGFiZWxbaWR4XS5oYXNPd25Qcm9wZXJ0eShwcm9wKSkge1xuICAgIHJldHVybiB0ZXh0TGFiZWw7XG4gIH1cblxuICBsZXQgbmV3VGV4dExhYmVsID0gdGV4dExhYmVsLnNsaWNlKCk7XG5cbiAgaWYgKHByb3AgJiYgKHZhbHVlIHx8IHRleHRMYWJlbC5sZW5ndGggPT09IDEpKSB7XG4gICAgbmV3VGV4dExhYmVsID0gdGV4dExhYmVsLm1hcCgodGwsIGkpID0+XG4gICAgICBpID09PSBpZHggPyB7Li4udGwsIFtwcm9wXTogdmFsdWV9IDogdGxcbiAgICApO1xuICB9IGVsc2UgaWYgKHByb3AgPT09ICdmaWVsZCcgJiYgdmFsdWUgPT09IG51bGwgJiYgdGV4dExhYmVsLmxlbmd0aCA+IDEpIHtcbiAgICAvLyByZW1vdmUgbGFiZWwgd2hlbiBmaWVsZCB2YWx1ZSBpcyBzZXQgdG8gbnVsbFxuICAgIG5ld1RleHRMYWJlbC5zcGxpY2UoaWR4LCAxKTtcbiAgfVxuXG4gIHJldHVybiBuZXdUZXh0TGFiZWw7XG59XG5cbmV4cG9ydCBmdW5jdGlvbiBsYXllclRleHRMYWJlbENoYW5nZVVwZGF0ZXIoc3RhdGUsIGFjdGlvbikge1xuICBjb25zdCB7b2xkTGF5ZXIsIGlkeCwgcHJvcCwgdmFsdWV9ID0gYWN0aW9uO1xuICBjb25zdCB7dGV4dExhYmVsfSA9IG9sZExheWVyLmNvbmZpZztcblxuICBsZXQgbmV3VGV4dExhYmVsID0gdGV4dExhYmVsLnNsaWNlKCk7XG4gIGlmICghdGV4dExhYmVsW2lkeF0gJiYgaWR4ID09PSB0ZXh0TGFiZWwubGVuZ3RoKSB7XG4gICAgLy8gaWYgaWR4IGlzIHNldCB0byBsZW5ndGgsIGFkZCBlbXB0eSB0ZXh0IGxhYmVsXG4gICAgbmV3VGV4dExhYmVsID0gWy4uLnRleHRMYWJlbCwgREVGQVVMVF9URVhUX0xBQkVMXTtcbiAgfVxuXG4gIGlmIChpZHggPT09ICdhbGwnICYmIHByb3AgPT09ICdmaWVsZHMnKSB7XG4gICAgbmV3VGV4dExhYmVsID0gYWRkT3JSZW1vdmVUZXh0TGFiZWxzKHZhbHVlLCB0ZXh0TGFiZWwpO1xuICB9IGVsc2Uge1xuICAgIG5ld1RleHRMYWJlbCA9IHVwZGF0ZVRleHRMYWJlbFByb3BBbmRWYWx1ZShpZHgsIHByb3AsIHZhbHVlLCBuZXdUZXh0TGFiZWwpO1xuICB9XG5cbiAgLy8gdXBkYXRlIHRleHQgbGFiZWwgcHJvcCBhbmQgdmFsdWVcbiAgcmV0dXJuIGxheWVyQ29uZmlnQ2hhbmdlVXBkYXRlcihzdGF0ZSwge1xuICAgIG9sZExheWVyLFxuICAgIG5ld0NvbmZpZzoge3RleHRMYWJlbDogbmV3VGV4dExhYmVsfVxuICB9KTtcbn1cblxuLyoqXG4gKiBVcGRhdGUgbGF5ZXIgdHlwZS4gUHJldmlld3MgbGF5ZXIgY29uZmlnIHdpbGwgYmUgY29waWVkIGlmIGFwcGxpY2FibGUuXG4gKiBAbWVtYmVyb2YgdmlzU3RhdGVVcGRhdGVyc1xuICogQHBhcmFtIHtPYmplY3R9IHN0YXRlIGB2aXNTdGF0ZWBcbiAqIEBwYXJhbSB7T2JqZWN0fSBhY3Rpb24gYWN0aW9uXG4gKiBAcGFyYW0ge09iamVjdH0gYWN0aW9uLm9sZExheWVyIGxheWVyIHRvIGJlIHVwZGF0ZWRcbiAqIEBwYXJhbSB7c3RyaW5nfSBhY3Rpb24ubmV3VHlwZSBuZXcgdHlwZVxuICogQHJldHVybnMge09iamVjdH0gbmV4dFN0YXRlXG4gKiBAcHVibGljXG4gKi9cbmV4cG9ydCBmdW5jdGlvbiBsYXllclR5cGVDaGFuZ2VVcGRhdGVyKHN0YXRlLCBhY3Rpb24pIHtcbiAgY29uc3Qge29sZExheWVyLCBuZXdUeXBlfSA9IGFjdGlvbjtcbiAgaWYgKCFvbGRMYXllcikge1xuICAgIHJldHVybiBzdGF0ZTtcbiAgfVxuICBjb25zdCBvbGRJZCA9IG9sZExheWVyLmlkO1xuICBjb25zdCBpZHggPSBzdGF0ZS5sYXllcnMuZmluZEluZGV4KGwgPT4gbC5pZCA9PT0gb2xkSWQpO1xuICBpZiAoIXN0YXRlLmxheWVyQ2xhc3Nlc1tuZXdUeXBlXSkge1xuICAgIENvbnNvbGUuZXJyb3IoYCR7bmV3VHlwZX0gaXMgbm90IGEgdmFsaWQgbGF5ZXIgdHlwZWApO1xuICAgIHJldHVybiBzdGF0ZTtcbiAgfVxuXG4gIC8vIGdldCBhIG1pbnQgbGF5ZXIsIHdpdGggbmV3IGlkIGFuZCB0eXBlXG4gIC8vIGJlY2F1c2UgZGVjay5nbCB1c2VzIGlkIHRvIG1hdGNoIGJldHdlZW4gbmV3IGFuZCBvbGQgbGF5ZXIuXG4gIC8vIElmIHR5cGUgaGFzIGNoYW5nZWQgYnV0IGlkIGlzIHRoZSBzYW1lLCBpdCB3aWxsIGJyZWFrXG4gIGNvbnN0IG5ld0xheWVyID0gbmV3IHN0YXRlLmxheWVyQ2xhc3Nlc1tuZXdUeXBlXSgpO1xuICBpZiAobmV3TGF5ZXIubmFtZSAhPT0gJ2JvdW5kYXJ5JyAmJiBuZXdMYXllci5uYW1lICE9PSAncGluY29kZScpIHtcbiAgICBvbGRMYXllci5jb25maWcuYXBpQ2FsbFJlcXVlc3QgPSB0cnVlO1xuICB9XG4gIG5ld0xheWVyLmFzc2lnbkNvbmZpZ1RvTGF5ZXIob2xkTGF5ZXIuY29uZmlnLCBvbGRMYXllci52aXNDb25maWdTZXR0aW5ncyk7XG5cbiAgaWYgKG5ld0xheWVyLmNvbmZpZy5kYXRhSWQpIHtcbiAgICBjb25zdCBkYXRhc2V0ID0gc3RhdGUuZGF0YXNldHNbbmV3TGF5ZXIuY29uZmlnLmRhdGFJZF07XG4gICAgbmV3TGF5ZXIudXBkYXRlTGF5ZXJEb21haW4oZGF0YXNldCk7XG4gIH1cblxuICBjb25zdCB7bGF5ZXJEYXRhLCBsYXllcn0gPSBjYWxjdWxhdGVMYXllckRhdGEobmV3TGF5ZXIsIHN0YXRlKTtcbiAgbGV0IG5ld1N0YXRlID0gdXBkYXRlU3RhdGVXaXRoTGF5ZXJBbmREYXRhKHN0YXRlLCB7bGF5ZXJEYXRhLCBsYXllciwgaWR4fSk7XG5cbiAgaWYgKGxheWVyLmNvbmZpZy5hbmltYXRpb24uZW5hYmxlZCB8fCBvbGRMYXllci5jb25maWcuYW5pbWF0aW9uLmVuYWJsZWQpIHtcbiAgICBuZXdTdGF0ZSA9IHVwZGF0ZUFuaW1hdGlvbkRvbWFpbihuZXdTdGF0ZSk7XG4gIH1cblxuICAvLyB1cGRhdGUgd2lkZ2V0cyBsYXllciBpZFxuICAvLyBpZiAoc3RhdGUud2lkZ2V0cykge1xuICAvLyAgIHN0YXRlLndpZGdldHMubWFwKHdpZGdldCA9PiB7XG4gIC8vICAgICBjb25zdCB7Y29uZmlnfSA9IHdpZGdldDtcbiAgLy8gICAgIGNvbnN0IHtzZWxlY3RlZExheWVyfSA9IGNvbmZpZztcbiAgLy8gICAgIGlmICh3aWRnZXQudHlwZSAmJiBzZWxlY3RlZExheWVyLmlkID09PSBvbGRJZCkge1xuICAvLyAgICAgICB3aWRnZXQudXBkYXRlV2lkZ2V0Q29uZmlnKHtcbiAgLy8gICAgICAgICBzZWxlY3RlZExheWVyOiB7Li4uc2VsZWN0ZWRMYXllciwgaWQ6IG5ld0xheWVyLmlkfVxuICAvLyAgICAgICB9KTtcbiAgLy8gICAgIH1cbiAgLy8gICB9KTtcbiAgLy8gfVxuXG4gIC8vIHVwZGF0ZSBzcGxpdE1hcCBsYXllciBpZFxuICBpZiAoc3RhdGUuc3BsaXRNYXBzLmxlbmd0aCkge1xuICAgIG5ld1N0YXRlID0ge1xuICAgICAgLi4ubmV3U3RhdGUsXG4gICAgICBzcGxpdE1hcHM6IG5ld1N0YXRlLnNwbGl0TWFwcy5tYXAoc2V0dGluZ3MgPT4ge1xuICAgICAgICBjb25zdCB7W29sZElkXTogb2xkTGF5ZXJNYXAsIC4uLm90aGVyTGF5ZXJzfSA9IHNldHRpbmdzLmxheWVycztcbiAgICAgICAgcmV0dXJuIG9sZElkIGluIHNldHRpbmdzLmxheWVyc1xuICAgICAgICAgID8ge1xuICAgICAgICAgICAgICAuLi5zZXR0aW5ncyxcbiAgICAgICAgICAgICAgbGF5ZXJzOiB7XG4gICAgICAgICAgICAgICAgLi4ub3RoZXJMYXllcnMsXG4gICAgICAgICAgICAgICAgW2xheWVyLmlkXTogb2xkTGF5ZXJNYXBcbiAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgfVxuICAgICAgICAgIDogc2V0dGluZ3M7XG4gICAgICB9KVxuICAgIH07XG4gIH1cblxuICByZXR1cm4gbmV3U3RhdGU7XG59XG5cbi8qKlxuICogVXBkYXRlIGxheWVyIHZpc3VhbCBjaGFubmVsXG4gKiBAbWVtYmVyb2YgdmlzU3RhdGVVcGRhdGVyc1xuICogQHBhcmFtIHtPYmplY3R9IHN0YXRlIGB2aXNTdGF0ZWBcbiAqIEBwYXJhbSB7T2JqZWN0fSBhY3Rpb24gYWN0aW9uXG4gKiBAcGFyYW0ge09iamVjdH0gYWN0aW9uLm9sZExheWVyIGxheWVyIHRvIGJlIHVwZGF0ZWRcbiAqIEBwYXJhbSB7T2JqZWN0fSBhY3Rpb24ubmV3Q29uZmlnIG5ldyB2aXN1YWwgY2hhbm5lbCBjb25maWdcbiAqIEBwYXJhbSB7c3RyaW5nfSBhY3Rpb24uY2hhbm5lbCBjaGFubmVsIHRvIGJlIHVwZGF0ZWRcbiAqIEByZXR1cm5zIHtPYmplY3R9IG5leHRTdGF0ZVxuICogQHB1YmxpY1xuICovXG5leHBvcnQgZnVuY3Rpb24gbGF5ZXJWaXN1YWxDaGFubmVsQ2hhbmdlVXBkYXRlcihzdGF0ZSwgYWN0aW9uKSB7XG4gIGNvbnN0IHtvbGRMYXllciwgbmV3Q29uZmlnLCBjaGFubmVsfSA9IGFjdGlvbjtcbiAgY29uc3QgZGF0YXNldCA9IHN0YXRlLmRhdGFzZXRzW29sZExheWVyLmNvbmZpZy5kYXRhSWRdO1xuXG4gIGNvbnN0IGlkeCA9IHN0YXRlLmxheWVycy5maW5kSW5kZXgobCA9PiBsLmlkID09PSBvbGRMYXllci5pZCk7XG4gIGNvbnN0IG5ld0xheWVyID0gb2xkTGF5ZXIudXBkYXRlTGF5ZXJDb25maWcobmV3Q29uZmlnKTtcblxuICBuZXdMYXllci51cGRhdGVMYXllclZpc3VhbENoYW5uZWwoZGF0YXNldCwgY2hhbm5lbCk7XG5cbiAgY29uc3Qgb2xkTGF5ZXJEYXRhID0gc3RhdGUubGF5ZXJEYXRhW2lkeF07XG4gIGNvbnN0IHtsYXllckRhdGEsIGxheWVyfSA9IGNhbGN1bGF0ZUxheWVyRGF0YShuZXdMYXllciwgc3RhdGUsIG9sZExheWVyRGF0YSwge1xuICAgIHNhbWVEYXRhOiB0cnVlXG4gIH0pO1xuICAvLyBsZXQgZGF0YSA9IGxheWVyLmF4aW9zQXBpQ2FsbCgpO1xuICAvLyBpZiAobGF5ZXIudHlwZSA9PT0gJ2JvdW5kYXJ5Jykge1xuICAvLyAgIGRhdGEudGhlbihmdW5jdGlvbihyZXN1bHQpIHtcbiAgLy8gICAgIC8vIGNvbnN0IHRlc3REYXRhID0gbGF5ZXIuZm9ybWF0TGF5ZXIoKTtcbiAgLy8gICAgIHZhciB7bGF5ZXJEYXRhLCBsYXllcn0gPSBjYWxjdWxhdGVMYXllckRhdGFBZnRlckFQSUNhbGwoXG4gIC8vICAgICAgIG5ld0xheWVyLFxuICAvLyAgICAgICBzdGF0ZSxcbiAgLy8gICAgICAgbGF5ZXJEYXRhLFxuICAvLyAgICAgICByZXN1bHRcbiAgLy8gICAgICk7XG4gIC8vICAgICBsYXllckRhdGEgPSB7XG4gIC8vICAgICAgIC4uLmxheWVyRGF0YSxcbiAgLy8gICAgICAgcmVzdWx0XG4gIC8vICAgICB9O1xuICAvLyAgICAgbmV3TGF5ZXJzW2ldID0gbGF5ZXI7XG4gIC8vICAgICBuZXdMYXllckRhdGFzW2ldID0gbGF5ZXJEYXRhO1xuICAvLyAgICAgcmV0dXJuIHtcbiAgLy8gICAgICAgLi4uc3RhdGUsXG4gIC8vICAgICAgIGxheWVyczogbmV3TGF5ZXJzLFxuICAvLyAgICAgICBsYXllckRhdGE6IG5ld0xheWVyRGF0YXNcbiAgLy8gICAgIH07XG4gIC8vICAgfSk7XG4gIC8vIH1cblxuICByZXR1cm4gdXBkYXRlU3RhdGVXaXRoTGF5ZXJBbmREYXRhKHN0YXRlLCB7bGF5ZXJEYXRhLCBsYXllciwgaWR4fSk7XG59XG5cbi8qKlxuICogVXBkYXRlIGxheWVyIGB2aXNDb25maWdgXG4gKiBAbWVtYmVyb2YgdmlzU3RhdGVVcGRhdGVyc1xuICogQHBhcmFtIHtPYmplY3R9IHN0YXRlIGB2aXNTdGF0ZWBcbiAqIEBwYXJhbSB7T2JqZWN0fSBhY3Rpb24gYWN0aW9uXG4gKiBAcGFyYW0ge09iamVjdH0gYWN0aW9uLm9sZExheWVyIGxheWVyIHRvIGJlIHVwZGF0ZWRcbiAqIEBwYXJhbSB7T2JqZWN0fSBhY3Rpb24ubmV3VmlzQ29uZmlnIG5ldyB2aXNDb25maWcgYXMgYSBrZXkgdmFsdWUgbWFwOiBlLmcuIGB7b3BhY2l0eTogMC44fWBcbiAqIEByZXR1cm5zIHtPYmplY3R9IG5leHRTdGF0ZVxuICogQHB1YmxpY1xuICovXG5leHBvcnQgZnVuY3Rpb24gbGF5ZXJWaXNDb25maWdDaGFuZ2VVcGRhdGVyKHN0YXRlLCBhY3Rpb24pIHtcbiAgY29uc3Qge29sZExheWVyfSA9IGFjdGlvbjtcbiAgY29uc3QgaWR4ID0gc3RhdGUubGF5ZXJzLmZpbmRJbmRleChsID0+IGwuaWQgPT09IG9sZExheWVyLmlkKTtcbiAgY29uc3QgcHJvcHMgPSBPYmplY3Qua2V5cyhhY3Rpb24ubmV3VmlzQ29uZmlnKTtcblxuICBjb25zdCBuZXdWaXNDb25maWcgPSB7XG4gICAgLi4ub2xkTGF5ZXIuY29uZmlnLnZpc0NvbmZpZyxcbiAgICAuLi5hY3Rpb24ubmV3VmlzQ29uZmlnXG4gIH07XG4gIGNvbnN0IG5ld0xheWVyID0gb2xkTGF5ZXIudXBkYXRlTGF5ZXJDb25maWcoe3Zpc0NvbmZpZzogbmV3VmlzQ29uZmlnfSk7XG4gIGlmIChuZXdMYXllci5zaG91bGRDYWxjdWxhdGVMYXllckRhdGEocHJvcHMpKSB7XG4gICAgY29uc3Qgb2xkTGF5ZXJEYXRhID0gc3RhdGUubGF5ZXJEYXRhW2lkeF07XG4gICAgY29uc3Qge2xheWVyRGF0YSwgbGF5ZXJ9ID0gY2FsY3VsYXRlTGF5ZXJEYXRhKFxuICAgICAgbmV3TGF5ZXIsXG4gICAgICBzdGF0ZSxcbiAgICAgIG9sZExheWVyRGF0YSxcbiAgICAgIHtcbiAgICAgICAgc2FtZURhdGE6IHRydWVcbiAgICAgIH1cbiAgICApO1xuICAgIHJldHVybiB1cGRhdGVTdGF0ZVdpdGhMYXllckFuZERhdGEoc3RhdGUsIHtsYXllckRhdGEsIGxheWVyLCBpZHh9KTtcbiAgfVxuXG4gIHJldHVybiB1cGRhdGVTdGF0ZVdpdGhMYXllckFuZERhdGEoc3RhdGUsIHtsYXllcjogbmV3TGF5ZXIsIGlkeH0pO1xufVxuXG4vKiBlc2xpbnQtZW5hYmxlIG1heC1zdGF0ZW1lbnRzICovXG5cbi8qKlxuICogVXBkYXRlIGBpbnRlcmFjdGlvbkNvbmZpZ2BcbiAqIEBtZW1iZXJvZiB2aXNTdGF0ZVVwZGF0ZXJzXG4gKiBAcGFyYW0ge09iamVjdH0gc3RhdGUgYHZpc1N0YXRlYFxuICogQHBhcmFtIHtPYmplY3R9IGFjdGlvbiBhY3Rpb25cbiAqIEBwYXJhbSB7T2JqZWN0fSBhY3Rpb24uY29uZmlnIG5ldyBjb25maWcgYXMga2V5IHZhbHVlIG1hcDogYHt0b29sdGlwOiB7ZW5hYmxlZDogdHJ1ZX19YFxuICogQHJldHVybnMge09iamVjdH0gbmV4dFN0YXRlXG4gKiBAcHVibGljXG4gKi9cbmV4cG9ydCBmdW5jdGlvbiBpbnRlcmFjdGlvbkNvbmZpZ0NoYW5nZVVwZGF0ZXIoc3RhdGUsIGFjdGlvbikge1xuICBjb25zdCB7Y29uZmlnfSA9IGFjdGlvbjtcblxuICBjb25zdCBpbnRlcmFjdGlvbkNvbmZpZyA9IHtcbiAgICAuLi5zdGF0ZS5pbnRlcmFjdGlvbkNvbmZpZyxcbiAgICAuLi57W2NvbmZpZy5pZF06IGNvbmZpZ31cbiAgfTtcblxuICAvLyBEb24ndCBlbmFibGUgdG9vbHRpcCBhbmQgYnJ1c2ggYXQgdGhlIHNhbWUgdGltZVxuICAvLyBidXQgY29vcmRpbmF0ZXMgY2FuIGJlIHNob3duIGF0IGFsbCB0aW1lXG4gIGNvbnN0IGNvbnRyYWRpY3QgPSBbJ2JydXNoJywgJ3Rvb2x0aXAnXTtcblxuICBpZiAoXG4gICAgY29udHJhZGljdC5pbmNsdWRlcyhjb25maWcuaWQpICYmXG4gICAgY29uZmlnLmVuYWJsZWQgJiZcbiAgICAhc3RhdGUuaW50ZXJhY3Rpb25Db25maWdbY29uZmlnLmlkXS5lbmFibGVkXG4gICkge1xuICAgIC8vIG9ubHkgZW5hYmxlIG9uZSBpbnRlcmFjdGlvbiBhdCBhIHRpbWVcbiAgICBjb250cmFkaWN0LmZvckVhY2goayA9PiB7XG4gICAgICBpZiAoayAhPT0gY29uZmlnLmlkKSB7XG4gICAgICAgIGludGVyYWN0aW9uQ29uZmlnW2tdID0gey4uLmludGVyYWN0aW9uQ29uZmlnW2tdLCBlbmFibGVkOiBmYWxzZX07XG4gICAgICB9XG4gICAgfSk7XG4gIH1cblxuICByZXR1cm4ge1xuICAgIC4uLnN0YXRlLFxuICAgIGludGVyYWN0aW9uQ29uZmlnXG4gIH07XG59XG5cbi8qKlxuICogVXBkYXRlIGZpbHRlciBwcm9wZXJ0eVxuICogQHBhcmFtIHtvYmplY3R9IHN0YXRlXG4gKiBAcGFyYW0ge29iamVjdH0gYWN0aW9uXG4gKiBAcGFyYW0ge051bWJlcn0gYWN0aW9uLmlkeCBgaWR4YCBvZiBmaWx0ZXIgdG8gYmUgdXBkYXRlZFxuICogQHBhcmFtIHtzdHJpbmd9IGFjdGlvbi5wcm9wIGBwcm9wYCBvZiBmaWx0ZXIsIGUsZywgYGRhdGFJZGAsIGBuYW1lYCwgYHZhbHVlYFxuICogQHBhcmFtIHsqfSBhY3Rpb24udmFsdWUgbmV3IHZhbHVlXG4gKiBAcGFyYW0ge3N0cmluZ30gYWN0aW9uLmRhdGFJZFxuICogQHBhcmFtIHtzdHJpbmd9IGFjdGlvbi5yYW5nZVxuICogQHBhcmFtIHtvYmplY3R9IGFjdGlvbi5oaXN0b2dyYW1cbiAqIEByZXR1cm5zIHtvYmplY3R9IG5ld1N0YXRlXG4gKi9cbmV4cG9ydCBmdW5jdGlvbiBzZXRGaWx0ZXJBUElVcGRhdGVyKHN0YXRlLCBhY3Rpb24pIHtcbiAgY29uc3Qge1xuICAgIGRhdGFJZCxcbiAgICBwcm9wLFxuICAgIHZhbHVlLFxuICAgIHZhbHVlSW5kZXggPSAwLFxuICAgIGRvbWFpbixcbiAgICBoaXN0b2dyYW0gPSB7fSxcbiAgICBpZHhcbiAgfSA9IGFjdGlvbjtcbiAgbGV0IG5ld1N0YXRlID0gc3RhdGU7XG4gIGxldCBuZXdGaWx0ZXIgPSB7XG4gICAgLi4uc3RhdGUuZmlsdGVyc1tpZHhdLFxuICAgIFtwcm9wXTogdmFsdWVcbiAgfTtcbiAgaWYgKCFoaXN0b2dyYW0pIHtcbiAgICBoaXN0b2dyYW0gPSB7fTtcbiAgfVxuXG4gIGNvbnN0IGRhdGFzZXRJZCA9IG5ld0ZpbHRlci5kYXRhSWRbdmFsdWVJbmRleF07XG4gIGNvbnN0IHtmaWx0ZXI6IHVwZGF0ZWRGaWx0ZXJ9ID0gYXBwbHlGaWx0ZXJBcGlGaWVsZE5hbWUoXG4gICAgbmV3RmlsdGVyLFxuICAgIHN0YXRlLmRhdGFzZXRzW2RhdGFzZXRJZF0sXG4gICAgdmFsdWUsXG4gICAgdmFsdWVJbmRleCxcbiAgICB7bWVyZ2VEb21haW46IGZhbHNlfSxcbiAgICBoaXN0b2dyYW0sXG4gICAgZG9tYWluXG4gICk7XG4gIGlmICghdXBkYXRlZEZpbHRlcikge1xuICAgIHJldHVybiBzdGF0ZTtcbiAgfVxuXG4gIG5ld0ZpbHRlciA9IHVwZGF0ZWRGaWx0ZXI7XG5cbiAgLy8gbmV3U3RhdGUgPSBuZXdTdGF0ZS5sYXllcnMubWFwKGwgPT4ge1xuICAvLyAgIGlmIChsLmNvbmZpZy5kYXRhSWQgPT09IGRhdGFJZCkge1xuICAvLyAgICAgbGF5ZXJDb25maWdDaGFuZ2VVcGRhdGVyKGwsIHtcbiAgLy8gICAgICAgYXBpQ2FsbFJlcXVlc3Q6IHRydWVcbiAgLy8gICAgIH0pO1xuICAvLyAgIH1cbiAgLy8gfSk7XG5cbiAgbmV3U3RhdGUgPSB7XG4gICAgLi4ubmV3U3RhdGUsXG4gICAgZmlsdGVyczogT2JqZWN0LmFzc2lnbihbLi4uc3RhdGUuZmlsdGVyc10sIHtbaWR4XTogbmV3RmlsdGVyfSlcbiAgfTtcblxuICByZXR1cm4gbmV3U3RhdGU7XG59XG5cbi8qKlxuICogVXBkYXRlIGZpbHRlciBwcm9wZXJ0eVxuICogQG1lbWJlcm9mIHZpc1N0YXRlVXBkYXRlcnNcbiAqIEBwYXJhbSB7T2JqZWN0fSBzdGF0ZSBgdmlzU3RhdGVgXG4gKiBAcGFyYW0ge09iamVjdH0gYWN0aW9uIGFjdGlvblxuICogQHBhcmFtIHtOdW1iZXJ9IGFjdGlvbi5pZHggYGlkeGAgb2YgZmlsdGVyIHRvIGJlIHVwZGF0ZWRcbiAqIEBwYXJhbSB7c3RyaW5nfSBhY3Rpb24ucHJvcCBgcHJvcGAgb2YgZmlsdGVyLCBlLGcsIGBkYXRhSWRgLCBgbmFtZWAsIGB2YWx1ZWBcbiAqIEBwYXJhbSB7Kn0gYWN0aW9uLnZhbHVlIG5ldyB2YWx1ZVxuICogQHBhcmFtIHtzdHJpbmd9IGRhdGFzZXRJZCB1c2VkIHdoZW4gdXBkYXRpbmcgYSBwcm9wIChkYXRhSWQsIG5hbWUpIHRoYXQgY2FuIGJlIGxpbmtlZCB0byBtdWx0aXBsZSBkYXRhc2V0c1xuICogQHJldHVybnMge09iamVjdH0gbmV4dFN0YXRlXG4gKiBAcHVibGljXG4gKi9cbmV4cG9ydCBmdW5jdGlvbiBzZXRGaWx0ZXJVcGRhdGVyKHN0YXRlLCBhY3Rpb24pIHtcbiAgY29uc3Qge2lkeCwgcHJvcCwgdmFsdWUsIHZhbHVlSW5kZXggPSAwLCBtYXBTdGF0ZSwgYXV0aCwgcHJvamVjdH0gPSBhY3Rpb247XG5cbiAgY29uc3Qgb2xkRmlsdGVyID0gc3RhdGUuZmlsdGVyc1tpZHhdO1xuICBsZXQgbmV3RmlsdGVyID0gc2V0KFtwcm9wXSwgdmFsdWUsIG9sZEZpbHRlcik7XG4gIGxldCBuZXdTdGF0ZSA9IHN0YXRlO1xuICBjb25zdCB7ZGF0YUlkfSA9IG5ld0ZpbHRlcjtcblxuICAvLyBFbnN1cmluZyBiYWNrd2FyZCBjb21wYXRpYmlsaXR5XG4gIGxldCBkYXRhc2V0SWRzID0gQXJyYXkuaXNBcnJheShkYXRhSWQpID8gZGF0YUlkIDogW2RhdGFJZF07XG5cbiAgc3dpdGNoIChwcm9wKSB7XG4gICAgLy8gVE9ETzogTmV4dCBQUiBmb3IgVUkgaWYgd2UgdXBkYXRlIGRhdGFJZCwgd2UgbmVlZCB0byBjb25zaWRlciB0d28gY2FzZXM6XG4gICAgLy8gMS4gZGF0YUlkIGlzIGVtcHR5OiBjcmVhdGUgYSBkZWZhdWx0IGZpbHRlclxuICAgIC8vIDIuIEFkZCBhIG5ldyBkYXRhc2V0IGlkXG4gICAgY2FzZSBGSUxURVJfVVBEQVRFUl9QUk9QUy5kYXRhSWQ6XG4gICAgICAvLyBpZiB0cnlpbmcgdG8gdXBkYXRlIGZpbHRlciBkYXRhSWQuIGNyZWF0ZSBhbiBlbXB0eSBuZXcgZmlsdGVyXG4gICAgICBuZXdGaWx0ZXIgPSBnZXREZWZhdWx0RmlsdGVyKGRhdGFJZCk7XG4gICAgICBicmVhaztcblxuICAgIGNhc2UgRklMVEVSX1VQREFURVJfUFJPUFMubmFtZTpcbiAgICAgIC8vIHdlIGFyZSBzdXBwb3J0aW5nIHRoZSBjdXJyZW50IGZ1bmN0aW9uYWxpdHlcbiAgICAgIC8vIFRPRE86IE5leHQgUFIgZm9yIFVJIGZpbHRlciBuYW1lIHdpbGwgb25seSB1cGRhdGUgZmlsdGVyIG5hbWUgYnV0IGl0IHdvbid0IGhhdmUgc2lkZSBlZmZlY3RzXG4gICAgICAvLyB3ZSBhcmUgZ29ubmEgdXNlIHBhaXIgb2YgZGF0YXNldHMgYW5kIGZpZWxkSWR4IHRvIHVwZGF0ZSB0aGUgZmlsdGVyXG4gICAgICBjb25zdCBkYXRhc2V0SWQgPSBuZXdGaWx0ZXIuZGF0YUlkW3ZhbHVlSW5kZXhdO1xuICAgICAgY29uc3Qge1xuICAgICAgICBmaWx0ZXI6IHVwZGF0ZWRGaWx0ZXIsXG4gICAgICAgIGRhdGFzZXQ6IG5ld0RhdGFzZXRcbiAgICAgIH0gPSBhcHBseUZpbHRlckZpZWxkTmFtZShcbiAgICAgICAgbmV3RmlsdGVyLFxuICAgICAgICBzdGF0ZS5kYXRhc2V0c1tkYXRhc2V0SWRdLFxuICAgICAgICB2YWx1ZSxcbiAgICAgICAgdmFsdWVJbmRleCxcbiAgICAgICAge21lcmdlRG9tYWluOiBmYWxzZX1cbiAgICAgICk7XG4gICAgICBpZiAoIXVwZGF0ZWRGaWx0ZXIpIHtcbiAgICAgICAgcmV0dXJuIHN0YXRlO1xuICAgICAgfVxuXG4gICAgICBuZXdGaWx0ZXIgPSB1cGRhdGVkRmlsdGVyO1xuXG4gICAgICBuZXdTdGF0ZSA9IHtcbiAgICAgICAgLi4uc3RhdGUsXG4gICAgICAgIGRhdGFzZXRzOiB7XG4gICAgICAgICAgLi4uc3RhdGUuZGF0YXNldHMsXG4gICAgICAgICAgW2RhdGFzZXRJZF06IG5ld0RhdGFzZXRcbiAgICAgICAgfVxuICAgICAgfTtcbiAgICAgIGJyZWFrO1xuXG4gICAgY2FzZSBGSUxURVJfVVBEQVRFUl9QUk9QUy5sYXllcklkOlxuICAgICAgLy8gV2UgbmVlZCB0byB1cGRhdGUgb25seSBkYXRhc2V0SWQvcyBpZiB3ZSBoYXZlIGFkZGVkL3JlbW92ZWQgbGF5ZXJzXG4gICAgICAvLyAtIGNoZWNrIGZvciBsYXllcklkIGNoYW5nZXMgKFhPUiB3b3JrcyBiZWNhdXNlIG9mIHN0cmluZyB2YWx1ZXMpXG4gICAgICAvLyBpZiBubyBkaWZmZXJlbmNlcyBiZXR3ZWVuIGxheWVySWRzLCBkb24ndCBkbyBhbnkgZmlsdGVyaW5nXG4gICAgICBjb25zdCBsYXllcklkRGlmZmVyZW5jZSA9IHhvcihuZXdGaWx0ZXIubGF5ZXJJZCwgb2xkRmlsdGVyLmxheWVySWQpO1xuXG4gICAgICBjb25zdCBsYXllckRhdGFJZHMgPSB1bmlxKFxuICAgICAgICBsYXllcklkRGlmZmVyZW5jZVxuICAgICAgICAgIC5tYXAobGlkID0+XG4gICAgICAgICAgICBnZXQoXG4gICAgICAgICAgICAgIHN0YXRlLmxheWVycy5maW5kKGwgPT4gbC5pZCA9PT0gbGlkKSxcbiAgICAgICAgICAgICAgWydjb25maWcnLCAnZGF0YUlkJ11cbiAgICAgICAgICAgIClcbiAgICAgICAgICApXG4gICAgICAgICAgLmZpbHRlcihkID0+IGQpXG4gICAgICApO1xuXG4gICAgICAvLyBvbmx5IGZpbHRlciBkYXRhc2V0c0lkc1xuICAgICAgZGF0YXNldElkcyA9IGxheWVyRGF0YUlkcztcblxuICAgICAgLy8gVXBkYXRlIG5ld0ZpbHRlciBkYXRhSWRzXG4gICAgICBjb25zdCBuZXdEYXRhSWRzID0gdW5pcShcbiAgICAgICAgbmV3RmlsdGVyLmxheWVySWRcbiAgICAgICAgICAubWFwKGxpZCA9PlxuICAgICAgICAgICAgZ2V0KFxuICAgICAgICAgICAgICBzdGF0ZS5sYXllcnMuZmluZChsID0+IGwuaWQgPT09IGxpZCksXG4gICAgICAgICAgICAgIFsnY29uZmlnJywgJ2RhdGFJZCddXG4gICAgICAgICAgICApXG4gICAgICAgICAgKVxuICAgICAgICAgIC5maWx0ZXIoZCA9PiBkKVxuICAgICAgKTtcblxuICAgICAgbmV3RmlsdGVyID0ge1xuICAgICAgICAuLi5uZXdGaWx0ZXIsXG4gICAgICAgIGRhdGFJZDogbmV3RGF0YUlkc1xuICAgICAgfTtcbiAgICAgIC8vIG9ubHkgZmlsdGVyIHRoZSBjdXJyZW50IGRhdGFzZXRcbiAgICAgIGJyZWFrO1xuICAgIGRlZmF1bHQ6XG4gICAgICBicmVhaztcbiAgfVxuXG4gIGNvbnN0IGVubGFyZ2VkRmlsdGVyID0gc3RhdGUuZmlsdGVycy5maW5kKGYgPT4gZi5lbmxhcmdlZCk7XG5cbiAgaWYgKGVubGFyZ2VkRmlsdGVyICYmIGVubGFyZ2VkRmlsdGVyLmlkICE9PSBuZXdGaWx0ZXIuaWQpIHtcbiAgICAvLyB0aGVyZSBzaG91bGQgYmUgb25seSBvbmUgZW5sYXJnZWQgZmlsdGVyXG4gICAgbmV3RmlsdGVyLmVubGFyZ2VkID0gZmFsc2U7XG4gIH1cblxuICAvLyBzYXZlIG5ldyBmaWx0ZXJzIHRvIG5ld1N0YXRlXG4gIG5ld1N0YXRlID0ge1xuICAgIC4uLm5ld1N0YXRlLFxuICAgIGZpbHRlcnM6IE9iamVjdC5hc3NpZ24oWy4uLnN0YXRlLmZpbHRlcnNdLCB7W2lkeF06IG5ld0ZpbHRlcn0pXG4gIH07XG5cbiAgLy8gaWYgd2UgYXJlIGN1cnJlbnRseSBzZXR0aW5nIGEgcHJvcCB0aGF0IG9ubHkgcmVxdWlyZXMgdG8gZmlsdGVyIHRoZSBjdXJyZW50XG4gIC8vIGRhdGFzZXQgd2Ugd2lsbCBwYXNzIG9ubHkgdGhlIGN1cnJlbnQgZGF0YXNldCB0byBhcHBseUZpbHRlcnNUb0RhdGFzZXRzIGFuZFxuICAvLyB1cGRhdGVBbGxMYXllckRvbWFpbkRhdGEgb3RoZXJ3aXNlIHdlIHBhc3MgdGhlIGFsbCBsaXN0IG9mIGRhdGFzZXRzIGFzIGRlZmluZWQgaW4gZGF0YUlkXG4gIGNvbnN0IGRhdGFzZXRJZHNUb0ZpbHRlciA9IExJTUlURURfRklMVEVSX0VGRkVDVF9QUk9QU1twcm9wXVxuICAgID8gdG9BcnJheShkYXRhc2V0SWRzW3ZhbHVlSW5kZXhdKVxuICAgIDogZGF0YXNldElkcztcblxuICAvLyBmaWx0ZXIgZGF0YVxuICBuZXdTdGF0ZSA9IHtcbiAgICAuLi5uZXdTdGF0ZSxcbiAgICBkYXRhc2V0czogYXBwbHlGaWx0ZXJzVG9EYXRhc2V0cyhcbiAgICAgIGRhdGFzZXRJZHNUb0ZpbHRlcixcbiAgICAgIG5ld1N0YXRlLmRhdGFzZXRzLFxuICAgICAgbmV3U3RhdGUuZmlsdGVycyxcbiAgICAgIG5ld1N0YXRlLmxheWVyc1xuICAgIClcbiAgfTtcblxuICAvLyBuZXdTdGF0ZSA9IHVwZGF0ZVdpZGdldEFnZ3JlZ2F0aW9uRGF0YShuZXdTdGF0ZSwgbWFwU3RhdGUsIGF1dGgsIHByb2plY3QpO1xuICAvLyBkYXRhSWQgaXMgYW4gYXJyYXlcbiAgLy8gcGFzcyBvbmx5IHRoZSBkYXRhc2V0IHdlIG5lZWQgdG8gdXBkYXRlXG4gIG5ld1N0YXRlID0gdXBkYXRlQWxsTGF5ZXJEb21haW5EYXRhKG5ld1N0YXRlLCBkYXRhc2V0SWRzVG9GaWx0ZXIsIG5ld0ZpbHRlcik7XG5cbiAgcmV0dXJuIG5ld1N0YXRlO1xufVxuXG4vKipcbiAqIFNldCB0aGUgcHJvcGVydHkgb2YgYSBmaWx0ZXIgcGxvdFxuICogQG1lbWJlcm9mIHZpc1N0YXRlVXBkYXRlcnNcbiAqIEBwYXJhbSB7T2JqZWN0fSBzdGF0ZSBgdmlzU3RhdGVgXG4gKiBAcGFyYW0ge09iamVjdH0gYWN0aW9uIGFjdGlvblxuICogQHBhcmFtIHtOdW1iZXJ9IGFjdGlvbi5pZHhcbiAqIEBwYXJhbSB7T2JqZWN0fSBhY3Rpb24ubmV3UHJvcCBrZXkgdmFsdWUgbWFwcGluZyBvZiBuZXcgcHJvcCBge3lBeGlzOiAnaGlzdG9ncmFtJ31gXG4gKiBAcmV0dXJucyB7T2JqZWN0fSBuZXh0U3RhdGVcbiAqIEBwdWJsaWNcbiAqL1xuZXhwb3J0IGNvbnN0IHNldEZpbHRlclBsb3RVcGRhdGVyID0gKHN0YXRlLCB7aWR4LCBuZXdQcm9wfSkgPT4ge1xuICBsZXQgbmV3RmlsdGVyID0gey4uLnN0YXRlLmZpbHRlcnNbaWR4XSwgLi4ubmV3UHJvcH07XG4gIGNvbnN0IHByb3AgPSBPYmplY3Qua2V5cyhuZXdQcm9wKVswXTtcbiAgaWYgKHByb3AgPT09ICd5QXhpcycpIHtcbiAgICBjb25zdCBwbG90VHlwZSA9IGdldERlZmF1bHRGaWx0ZXJQbG90VHlwZShuZXdGaWx0ZXIpO1xuXG4gICAgaWYgKHBsb3RUeXBlKSB7XG4gICAgICBuZXdGaWx0ZXIgPSB7XG4gICAgICAgIC4uLm5ld0ZpbHRlcixcbiAgICAgICAgLi4uZ2V0RmlsdGVyUGxvdChcbiAgICAgICAgICB7Li4ubmV3RmlsdGVyLCBwbG90VHlwZX0sXG4gICAgICAgICAgc3RhdGUuZGF0YXNldHNbbmV3RmlsdGVyLmRhdGFJZF0uYWxsRGF0YVxuICAgICAgICApLFxuICAgICAgICBwbG90VHlwZVxuICAgICAgfTtcbiAgICB9XG4gIH1cblxuICByZXR1cm4ge1xuICAgIC4uLnN0YXRlLFxuICAgIGZpbHRlcnM6IHN0YXRlLmZpbHRlcnMubWFwKChmLCBpKSA9PiAoaSA9PT0gaWR4ID8gbmV3RmlsdGVyIDogZikpXG4gIH07XG59O1xuXG4vKipcbiAqIEFkZCBhIG5ldyBmaWx0ZXJcbiAqIEBtZW1iZXJvZiB2aXNTdGF0ZVVwZGF0ZXJzXG4gKiBAcGFyYW0ge09iamVjdH0gc3RhdGUgYHZpc1N0YXRlYFxuICogQHBhcmFtIHtPYmplY3R9IGFjdGlvbiBhY3Rpb25cbiAqIEBwYXJhbSB7c3RyaW5nfSBhY3Rpb24uZGF0YUlkIGRhdGFzZXQgYGlkYCB0aGlzIG5ldyBmaWx0ZXIgaXMgYXNzb2NpYXRlZCB3aXRoXG4gKiBAcmV0dXJucyB7T2JqZWN0fSBuZXh0U3RhdGVcbiAqIEBwdWJsaWNcbiAqL1xuZXhwb3J0IGNvbnN0IGFkZEZpbHRlclVwZGF0ZXIgPSAoc3RhdGUsIGFjdGlvbikgPT5cbiAgIWFjdGlvbi5kYXRhSWRcbiAgICA/IHN0YXRlXG4gICAgOiB7XG4gICAgICAgIC4uLnN0YXRlLFxuICAgICAgICBmaWx0ZXJzOiBbLi4uc3RhdGUuZmlsdGVycywgZ2V0RGVmYXVsdEZpbHRlcihhY3Rpb24uZGF0YUlkKV1cbiAgICAgIH07XG5cbi8qKlxuICogU2V0IGxheWVyIGNvbG9yIHBhbGV0dGUgdWkgc3RhdGVcbiAqIEBtZW1iZXJvZiB2aXNTdGF0ZVVwZGF0ZXJzXG4gKiBAcGFyYW0ge09iamVjdH0gc3RhdGVcbiAqIEBwYXJhbSB7T2JqZWN0fSBhY3Rpb25cbiAqIEBwYXJhbSB7T2JqZWN0fSBhY3Rpb24ucHJvcFxuICogQHBhcmFtIHtPYmplY3R9IGFjdGlvbi5uZXdDb25maWdcbiAqL1xuZXhwb3J0IGNvbnN0IGxheWVyQ29sb3JVSUNoYW5nZVVwZGF0ZXIgPSAoXG4gIHN0YXRlLFxuICB7b2xkTGF5ZXIsIHByb3AsIG5ld0NvbmZpZ31cbikgPT4ge1xuICBjb25zdCBuZXdMYXllciA9IG9sZExheWVyLnVwZGF0ZUxheWVyQ29sb3JVSShwcm9wLCBuZXdDb25maWcpO1xuICByZXR1cm4ge1xuICAgIC4uLnN0YXRlLFxuICAgIGxheWVyczogc3RhdGUubGF5ZXJzLm1hcChsID0+IChsLmlkID09PSBvbGRMYXllci5pZCA/IG5ld0xheWVyIDogbCkpXG4gIH07XG59O1xuXG4vKipcbiAqIFN0YXJ0IGFuZCBlbmQgZmlsdGVyIGFuaW1hdGlvblxuICogQG1lbWJlcm9mIHZpc1N0YXRlVXBkYXRlcnNcbiAqIEBwYXJhbSB7T2JqZWN0fSBzdGF0ZSBgdmlzU3RhdGVgXG4gKiBAcGFyYW0ge09iamVjdH0gYWN0aW9uIGFjdGlvblxuICogQHBhcmFtIHtOdW1iZXJ9IGFjdGlvbi5pZHggaWR4IG9mIGZpbHRlclxuICogQHJldHVybnMge09iamVjdH0gbmV4dFN0YXRlXG4gKiBAcHVibGljXG4gKi9cbmV4cG9ydCBjb25zdCB0b2dnbGVGaWx0ZXJBbmltYXRpb25VcGRhdGVyID0gKHN0YXRlLCBhY3Rpb24pID0+ICh7XG4gIC4uLnN0YXRlLFxuICBmaWx0ZXJzOiBzdGF0ZS5maWx0ZXJzLm1hcCgoZiwgaSkgPT5cbiAgICBpID09PSBhY3Rpb24uaWR4ID8gey4uLmYsIGlzQW5pbWF0aW5nOiAhZi5pc0FuaW1hdGluZ30gOiBmXG4gIClcbn0pO1xuXG4vKipcbiAqIENoYW5nZSBmaWx0ZXIgYW5pbWF0aW9uIHNwZWVkXG4gKiBAbWVtYmVyb2YgdmlzU3RhdGVVcGRhdGVyc1xuICogQHBhcmFtIHtPYmplY3R9IHN0YXRlIGB2aXNTdGF0ZWBcbiAqIEBwYXJhbSB7T2JqZWN0fSBhY3Rpb24gYWN0aW9uXG4gKiBAcGFyYW0ge051bWJlcn0gYWN0aW9uLmlkeCAgYGlkeGAgb2YgZmlsdGVyXG4gKiBAcGFyYW0ge051bWJlcn0gYWN0aW9uLnNwZWVkIGBzcGVlZGAgdG8gY2hhbmdlIGl0IHRvLiBgc3BlZWRgIGlzIGEgbXVsdGlwbGllclxuICogQHJldHVybnMge09iamVjdH0gbmV4dFN0YXRlXG4gKiBAcHVibGljXG4gKi9cbmV4cG9ydCBjb25zdCB1cGRhdGVGaWx0ZXJBbmltYXRpb25TcGVlZFVwZGF0ZXIgPSAoc3RhdGUsIGFjdGlvbikgPT4gKHtcbiAgLi4uc3RhdGUsXG4gIGZpbHRlcnM6IHN0YXRlLmZpbHRlcnMubWFwKChmLCBpKSA9PlxuICAgIGkgPT09IGFjdGlvbi5pZHggPyB7Li4uZiwgc3BlZWQ6IGFjdGlvbi5zcGVlZH0gOiBmXG4gIClcbn0pO1xuXG4vKipcbiAqIFJlc2V0IGFuaW1hdGlvbiBjb25maWcgY3VycmVudCB0aW1lIHRvIGEgc3BlY2lmaWVkIHZhbHVlXG4gKiBAbWVtYmVyb2YgdmlzU3RhdGVVcGRhdGVyc1xuICogQHBhcmFtIHtPYmplY3R9IHN0YXRlIGB2aXNTdGF0ZWBcbiAqIEBwYXJhbSB7T2JqZWN0fSBhY3Rpb24gYWN0aW9uXG4gKiBAcGFyYW0ge051bWJlcn0gYWN0aW9uLnZhbHVlIHRoZSB2YWx1ZSBjdXJyZW50IHRpbWUgd2lsbCBiZSBzZXQgdG9cbiAqIEByZXR1cm5zIHtPYmplY3R9IG5leHRTdGF0ZVxuICogQHB1YmxpY1xuICpcbiAqL1xuXG5leHBvcnQgY29uc3QgdXBkYXRlQW5pbWF0aW9uVGltZVVwZGF0ZXIgPSAoc3RhdGUsIHt2YWx1ZX0pID0+ICh7XG4gIC4uLnN0YXRlLFxuICBhbmltYXRpb25Db25maWc6IHtcbiAgICAuLi5zdGF0ZS5hbmltYXRpb25Db25maWcsXG4gICAgY3VycmVudFRpbWU6IHZhbHVlXG4gIH1cbn0pO1xuXG4vKipcbiAqIFVwZGF0ZSBhbmltYXRpb24gc3BlZWQgd2l0aCB0aGUgdmVydGljYWwgc3BlZWQgc2xpZGVyXG4gKiBAbWVtYmVyb2YgdmlzU3RhdGVVcGRhdGVyc1xuICogQHBhcmFtIHtPYmplY3R9IHN0YXRlIGB2aXNTdGF0ZWBcbiAqIEBwYXJhbSB7T2JqZWN0fSBhY3Rpb24gYWN0aW9uXG4gKiBAcGFyYW0ge051bWJlcn0gYWN0aW9uLnNwZWVkIHRoZSB1cGRhdGVkIHNwZWVkIG9mIHRoZSBhbmltYXRpb25cbiAqIEByZXR1cm5zIHtPYmplY3R9IG5leHRTdGF0ZVxuICogQHB1YmxpY1xuICpcbiAqL1xuXG5leHBvcnQgY29uc3QgdXBkYXRlTGF5ZXJBbmltYXRpb25TcGVlZFVwZGF0ZXIgPSAoc3RhdGUsIHtzcGVlZH0pID0+IHtcbiAgcmV0dXJuIHtcbiAgICAuLi5zdGF0ZSxcbiAgICBhbmltYXRpb25Db25maWc6IHtcbiAgICAgIC4uLnN0YXRlLmFuaW1hdGlvbkNvbmZpZyxcbiAgICAgIHNwZWVkXG4gICAgfVxuICB9O1xufTtcblxuLyoqXG4gKiBTaG93IGxhcmdlciB0aW1lIGZpbHRlciBhdCBib3R0b20gZm9yIHRpbWUgcGxheWJhY2sgKGFwcGx5IHRvIHRpbWUgZmlsdGVyIG9ubHkpXG4gKiBAbWVtYmVyb2YgdmlzU3RhdGVVcGRhdGVyc1xuICogQHBhcmFtIHtPYmplY3R9IHN0YXRlIGB2aXNTdGF0ZWBcbiAqIEBwYXJhbSB7T2JqZWN0fSBhY3Rpb24gYWN0aW9uXG4gKiBAcGFyYW0ge051bWJlcn0gYWN0aW9uLmlkeCBpbmRleCBvZiBmaWx0ZXIgdG8gZW5sYXJnZVxuICogQHJldHVybnMge09iamVjdH0gbmV4dFN0YXRlXG4gKiBAcHVibGljXG4gKi9cbmV4cG9ydCBjb25zdCBlbmxhcmdlRmlsdGVyVXBkYXRlciA9IChzdGF0ZSwgYWN0aW9uKSA9PiB7XG4gIGNvbnN0IGlzRW5sYXJnZWQgPSBzdGF0ZS5maWx0ZXJzW2FjdGlvbi5pZHhdLmVubGFyZ2VkO1xuXG4gIHJldHVybiB7XG4gICAgLi4uc3RhdGUsXG4gICAgZmlsdGVyczogc3RhdGUuZmlsdGVycy5tYXAoKGYsIGkpID0+IHtcbiAgICAgIGYuZW5sYXJnZWQgPSAhaXNFbmxhcmdlZCAmJiBpID09PSBhY3Rpb24uaWR4O1xuICAgICAgcmV0dXJuIGY7XG4gICAgfSlcbiAgfTtcbn07XG5cbi8qKlxuICogUmVtb3ZlIGEgZmlsdGVyXG4gKiBAbWVtYmVyb2YgdmlzU3RhdGVVcGRhdGVyc1xuICogQHBhcmFtIHtPYmplY3R9IHN0YXRlIGB2aXNTdGF0ZWBcbiAqIEBwYXJhbSB7T2JqZWN0fSBhY3Rpb24gYWN0aW9uXG4gKiBAcGFyYW0ge051bWJlcn0gYWN0aW9uLmlkeCBpbmRleCBvZiBmaWx0ZXIgdG8gYiBlIHJlbW92ZWRcbiAqIEByZXR1cm5zIHtPYmplY3R9IG5leHRTdGF0ZVxuICogQHB1YmxpY1xuICovXG5leHBvcnQgY29uc3QgcmVtb3ZlRmlsdGVyVXBkYXRlciA9IChzdGF0ZSwgYWN0aW9uKSA9PiB7XG4gIGNvbnN0IHtpZHgsIG1hcFN0YXRlLCBhdXRoLCBwcm9qZWN0fSA9IGFjdGlvbjtcbiAgY29uc3Qge2RhdGFJZH0gPSBzdGF0ZS5maWx0ZXJzW2lkeF07XG5cbiAgY29uc3QgbmV3RmlsdGVycyA9IFtcbiAgICAuLi5zdGF0ZS5maWx0ZXJzLnNsaWNlKDAsIGlkeCksXG4gICAgLi4uc3RhdGUuZmlsdGVycy5zbGljZShpZHggKyAxLCBzdGF0ZS5maWx0ZXJzLmxlbmd0aClcbiAgXTtcblxuICBjb25zdCBmaWx0ZXIgPSBzdGF0ZS5maWx0ZXJzW2lkeF07XG4gIGNvbnN0IGZpbHRlcmVkRGF0YXNldHMgPSBhcHBseUZpbHRlcnNUb0RhdGFzZXRzKFxuICAgIGRhdGFJZCxcbiAgICBzdGF0ZS5kYXRhc2V0cyxcbiAgICBuZXdGaWx0ZXJzLFxuICAgIHN0YXRlLmxheWVyc1xuICApO1xuXG4gIGxldCBuZXdTdGF0ZSA9IHtcbiAgICAuLi5zdGF0ZSxcbiAgICBmaWx0ZXJzOiBuZXdGaWx0ZXJzLFxuICAgIGVkaXRvcjoge1xuICAgICAgLi4uc3RhdGUuZWRpdG9yLFxuICAgICAgZmVhdHVyZXM6XG4gICAgICAgIGZpbHRlci50eXBlICE9PSBGSUxURVJfVFlQRVMucG9seWdvblxuICAgICAgICAgID8gc3RhdGUuZWRpdG9yLmZlYXR1cmVzXG4gICAgICAgICAgOiBzdGF0ZS5lZGl0b3IuZmVhdHVyZXMuZmlsdGVyKGYgPT4gZi5pZCAhPT0gZmlsdGVyLnZhbHVlLmlkKSxcbiAgICAgIHNlbGVjdGVkRmVhdHVyZTogbnVsbFxuICAgIH1cbiAgfTtcblxuICAvLyBjYWxsIGxheWVycyBhcGkgdG8gdXBkYXRlIGRhdGEgd2hlbiBhIGZpbHRlciBpcyByZW1vdmVkXG5cbiAgY29uc3QgbGF5ZXJzID0gbmV3U3RhdGUubGF5ZXJzLm1hcChsYXllciA9PiB7XG4gICAgaWYgKGxheWVyLmRhdGFJZCA9PT0gZGF0YUlkKSB7XG4gICAgICBsYXllci5jb25maWcuYXBpQ2FsbFJlcXVlc3QgPT09IHRydWU7XG4gICAgfVxuICAgIHJldHVybiBsYXllcjtcbiAgfSk7XG4gIG5ld1N0YXRlID0ge1xuICAgIC4uLm5ld1N0YXRlLFxuICAgIGxheWVyc1xuICB9O1xuICBuZXdTdGF0ZSA9IHNldChbJ2RhdGFzZXRzJ10sIGZpbHRlcmVkRGF0YXNldHMsIG5ld1N0YXRlKTtcblxuICByZXR1cm4gdXBkYXRlQWxsTGF5ZXJEb21haW5EYXRhKG5ld1N0YXRlLCBkYXRhSWQpO1xufTtcblxuZXhwb3J0IGNvbnN0IGFkZFdpZGdldFVwZGF0ZXIgPSAoc3RhdGUsIGFjdGlvbikgPT4ge1xuICBjb25zdCBkZWZhdWx0RGF0YXNldCA9IE9iamVjdC5rZXlzKHN0YXRlLmRhdGFzZXRzKVswXTtcbiAgY29uc3QgbmV3V2lkZ2V0ID0gbmV3IFdpZGdldCh7XG4gICAgaXNWaXNpYmxlOiB0cnVlLFxuICAgIGlzQ29uZmlnQWN0aXZlOiB0cnVlLFxuICAgIGRhdGFJZDogZGVmYXVsdERhdGFzZXQsXG4gICAgLi4uYWN0aW9uLnByb3BzXG4gIH0pO1xuXG4gIHJldHVybiAhZGVmYXVsdERhdGFzZXRcbiAgICA/IHN0YXRlXG4gICAgOiB7XG4gICAgICAgIC4uLnN0YXRlLFxuICAgICAgICB3aWRnZXRzOiBbLi4uc3RhdGUud2lkZ2V0cywgbmV3V2lkZ2V0XSxcbiAgICAgICAgd2lkZ2V0T3JkZXI6IFsuLi5zdGF0ZS53aWRnZXRPcmRlciwgc3RhdGUud2lkZ2V0T3JkZXIubGVuZ3RoXVxuICAgICAgfTtcbn07XG5cbmV4cG9ydCBjb25zdCByZW1vdmVXaWRnZXRVcGRhdGVyID0gKHN0YXRlLCB7aWR4fSkgPT4ge1xuICBjb25zdCB7d2lkZ2V0c30gPSBzdGF0ZTtcbiAgcmV0dXJuIHtcbiAgICAuLi5zdGF0ZSxcbiAgICB3aWRnZXRzOiBbXG4gICAgICAuLi53aWRnZXRzLnNsaWNlKDAsIGlkeCksXG4gICAgICAuLi53aWRnZXRzLnNsaWNlKGlkeCArIDEsIHdpZGdldHMubGVuZ3RoKVxuICAgIF0sXG4gICAgd2lkZ2V0T3JkZXI6IHN0YXRlLndpZGdldE9yZGVyXG4gICAgICAuZmlsdGVyKGkgPT4gaSAhPT0gaWR4KVxuICAgICAgLm1hcChwaWQgPT4gKHBpZCA+IGlkeCA/IHBpZCAtIDEgOiBwaWQpKVxuICB9O1xufTtcblxuZXhwb3J0IGNvbnN0IHJlb3JkZXJXaWRnZXRVcGRhdGVyID0gKHN0YXRlLCB7b3JkZXJ9KSA9PiB7XG4gIHJldHVybiB7XG4gICAgLi4uc3RhdGUsXG4gICAgd2lkZ2V0T3JkZXI6IG9yZGVyXG4gIH07XG59O1xuXG4vKipcbiAqIEFkZCBhIG5ldyBsYXllclxuICogQG1lbWJlcm9mIHZpc1N0YXRlVXBkYXRlcnNcbiAqIEBwYXJhbSB7T2JqZWN0fSBzdGF0ZSBgdmlzU3RhdGVgXG4gKiBAcGFyYW0ge09iamVjdH0gYWN0aW9uIGFjdGlvblxuICogQHBhcmFtIHtPYmplY3R9IGFjdGlvbi5wcm9wcyAtIG5ldyBsYXllciBwcm9wc1xuICogQHJldHVybnMge09iamVjdH0gbmV4dFN0YXRlXG4gKiBAcHVibGljXG4gKi9cbmV4cG9ydCBjb25zdCBhZGRMYXllclVwZGF0ZXIgPSAoc3RhdGUsIGFjdGlvbikgPT4ge1xuICBjb25zdCBkZWZhdWx0RGF0YXNldCA9IE9iamVjdC5rZXlzKHN0YXRlLmRhdGFzZXRzKVswXTtcblxuICBjb25zdCBuZXdMYXllciA9IG5ldyBMYXllcih7XG4gICAgaXNWaXNpYmxlOiB0cnVlLFxuICAgIGlzQ29uZmlnQWN0aXZlOiB0cnVlLFxuICAgIGRhdGFJZDogZGVmYXVsdERhdGFzZXQsXG4gICAgLi4uYWN0aW9uLnByb3BzXG4gIH0pO1xuXG4gIHJldHVybiB7XG4gICAgLi4uc3RhdGUsXG4gICAgbGF5ZXJzOiBbLi4uc3RhdGUubGF5ZXJzLCBuZXdMYXllcl0sXG4gICAgbGF5ZXJEYXRhOiBbLi4uc3RhdGUubGF5ZXJEYXRhLCB7fV0sXG4gICAgbGF5ZXJPcmRlcjogWy4uLnN0YXRlLmxheWVyT3JkZXIsIHN0YXRlLmxheWVyT3JkZXIubGVuZ3RoXSxcbiAgICBzcGxpdE1hcHM6IGFkZE5ld0xheWVyc1RvU3BsaXRNYXAoc3RhdGUuc3BsaXRNYXBzLCBuZXdMYXllcilcbiAgfTtcbn07XG5cbi8qKlxuICogcmVtb3ZlIGxheWVyXG4gKiBAbWVtYmVyb2YgdmlzU3RhdGVVcGRhdGVyc1xuICogQHBhcmFtIHtPYmplY3R9IHN0YXRlIGB2aXNTdGF0ZWBcbiAqIEBwYXJhbSB7T2JqZWN0fSBhY3Rpb24gYWN0aW9uXG4gKiBAcGFyYW0ge051bWJlcn0gYWN0aW9uLmlkeCBpbmRleCBvZiBsYXllciB0byBiIGUgcmVtb3ZlZFxuICogQHJldHVybnMge09iamVjdH0gbmV4dFN0YXRlXG4gKiBAcHVibGljXG4gKi9cbmV4cG9ydCBjb25zdCByZW1vdmVMYXllclVwZGF0ZXIgPSAoc3RhdGUsIHtpZHh9KSA9PiB7XG4gIGNvbnN0IHtsYXllcnMsIGxheWVyRGF0YSwgY2xpY2tlZCwgaG92ZXJJbmZvfSA9IHN0YXRlO1xuICBjb25zdCBsYXllclRvUmVtb3ZlID0gc3RhdGUubGF5ZXJzW2lkeF07XG4gIGNvbnN0IG5ld01hcHMgPSByZW1vdmVMYXllckZyb21TcGxpdE1hcHMoc3RhdGUuc3BsaXRNYXBzLCBsYXllclRvUmVtb3ZlKTtcblxuICBjb25zdCBuZXdTdGF0ZSA9IHtcbiAgICAuLi5zdGF0ZSxcbiAgICBsYXllcnM6IFsuLi5sYXllcnMuc2xpY2UoMCwgaWR4KSwgLi4ubGF5ZXJzLnNsaWNlKGlkeCArIDEsIGxheWVycy5sZW5ndGgpXSxcbiAgICBsYXllckRhdGE6IFtcbiAgICAgIC4uLmxheWVyRGF0YS5zbGljZSgwLCBpZHgpLFxuICAgICAgLi4ubGF5ZXJEYXRhLnNsaWNlKGlkeCArIDEsIGxheWVyRGF0YS5sZW5ndGgpXG4gICAgXSxcbiAgICBsYXllck9yZGVyOiBzdGF0ZS5sYXllck9yZGVyXG4gICAgICAuZmlsdGVyKGkgPT4gaSAhPT0gaWR4KVxuICAgICAgLm1hcChwaWQgPT4gKHBpZCA+IGlkeCA/IHBpZCAtIDEgOiBwaWQpKSxcbiAgICBjbGlja2VkOiBsYXllclRvUmVtb3ZlLmlzTGF5ZXJIb3ZlcmVkKGNsaWNrZWQpID8gdW5kZWZpbmVkIDogY2xpY2tlZCxcbiAgICBob3ZlckluZm86IGxheWVyVG9SZW1vdmUuaXNMYXllckhvdmVyZWQoaG92ZXJJbmZvKSA/IHVuZGVmaW5lZCA6IGhvdmVySW5mbyxcbiAgICBzcGxpdE1hcHM6IG5ld01hcHNcbiAgICAvLyBUT0RPOiB1cGRhdGUgZmlsdGVycywgY3JlYXRlIGhlbHBlciB0byByZW1vdmUgbGF5ZXIgZm9ybSBmaWx0ZXIgKHJlbW92ZSBsYXllcmlkIGFuZCBkYXRhaWQpIGlmIG1hcHBlZFxuICB9O1xuXG4gIHJldHVybiB1cGRhdGVBbmltYXRpb25Eb21haW4obmV3U3RhdGUpO1xufTtcblxuLyoqXG4gKiBSZW9yZGVyIGxheWVyXG4gKiBAbWVtYmVyb2YgdmlzU3RhdGVVcGRhdGVyc1xuICogQHBhcmFtIHtPYmplY3R9IHN0YXRlIGB2aXNTdGF0ZWBcbiAqIEBwYXJhbSB7T2JqZWN0fSBhY3Rpb24gYWN0aW9uXG4gKiBAcGFyYW0ge0FycmF5PE51bWJlcj59IGFjdGlvbi5vcmRlciBhbiBhcnJheSBvZiBsYXllciBpbmRleGVzXG4gKiBAcmV0dXJucyB7T2JqZWN0fSBuZXh0U3RhdGVcbiAqIEBwdWJsaWNcbiAqL1xuZXhwb3J0IGNvbnN0IHJlb3JkZXJMYXllclVwZGF0ZXIgPSAoc3RhdGUsIHtvcmRlcn0pID0+ICh7XG4gIC4uLnN0YXRlLFxuICBsYXllck9yZGVyOiBvcmRlclxufSk7XG5cbi8qKlxuICogUmVtb3ZlIGEgZGF0YXNldCBhbmQgYWxsIGxheWVycywgZmlsdGVycywgdG9vbHRpcCBjb25maWdzIHRoYXQgYmFzZWQgb24gaXRcbiAqIEBtZW1iZXJvZiB2aXNTdGF0ZVVwZGF0ZXJzXG4gKiBAcGFyYW0ge09iamVjdH0gc3RhdGUgYHZpc1N0YXRlYFxuICogQHBhcmFtIHtPYmplY3R9IGFjdGlvbiBhY3Rpb25cbiAqIEBwYXJhbSB7c3RyaW5nfSBhY3Rpb24ua2V5IGRhdGFzZXQgaWRcbiAqIEByZXR1cm5zIHtPYmplY3R9IG5leHRTdGF0ZVxuICogQHB1YmxpY1xuICovXG5leHBvcnQgY29uc3QgcmVtb3ZlRGF0YXNldFVwZGF0ZXIgPSAoc3RhdGUsIGFjdGlvbikgPT4ge1xuICAvLyBleHRyYWN0IGRhdGFzZXQga2V5XG4gIGNvbnN0IHtrZXk6IGRhdGFzZXRLZXl9ID0gYWN0aW9uO1xuICBjb25zdCB7ZGF0YXNldHN9ID0gc3RhdGU7XG5cbiAgLy8gY2hlY2sgaWYgZGF0YXNldCBpcyBwcmVzZW50XG4gIGlmICghZGF0YXNldHNbZGF0YXNldEtleV0pIHtcbiAgICByZXR1cm4gc3RhdGU7XG4gIH1cblxuICAvKiBlc2xpbnQtZGlzYWJsZSBuby11bnVzZWQtdmFycyAqL1xuICBjb25zdCB7XG4gICAgbGF5ZXJzLFxuICAgIHdpZGdldHMsXG4gICAgZGF0YXNldHM6IHtbZGF0YXNldEtleV06IGRhdGFzZXQsIC4uLm5ld0RhdGFzZXRzfVxuICB9ID0gc3RhdGU7XG4gIC8qIGVzbGludC1lbmFibGUgbm8tdW51c2VkLXZhcnMgKi9cblxuICBjb25zdCBpbmRleGVzID0gbGF5ZXJzLnJlZHVjZSgobGlzdE9mSW5kZXhlcywgbGF5ZXIsIGluZGV4KSA9PiB7XG4gICAgaWYgKGxheWVyLmNvbmZpZy5kYXRhSWQgPT09IGRhdGFzZXRLZXkpIHtcbiAgICAgIGxpc3RPZkluZGV4ZXMucHVzaChpbmRleCk7XG4gICAgfVxuICAgIHJldHVybiBsaXN0T2ZJbmRleGVzO1xuICB9LCBbXSk7XG5cbiAgY29uc3Qgd2lkZ2V0SW5kZXhlcyA9IHdpZGdldHMucmVkdWNlKChsaXN0T2ZJbmRleGVzLCB3aWRnZXQsIGluZGV4KSA9PiB7XG4gICAgaWYgKHdpZGdldC5jb25maWcuZGF0YUlkID09PSBkYXRhc2V0S2V5KSB7XG4gICAgICBsaXN0T2ZJbmRleGVzLnB1c2goaW5kZXgpO1xuICAgIH1cbiAgICByZXR1cm4gbGlzdE9mSW5kZXhlcztcbiAgfSwgW10pO1xuXG4gIC8vIHJlbW92ZSBsYXllcnMgYW5kIGRhdGFzZXRzXG4gIGNvbnN0IHtuZXdTdGF0ZX0gPSBpbmRleGVzLnJlZHVjZShcbiAgICAoe25ld1N0YXRlOiBjdXJyZW50U3RhdGUsIGluZGV4Q291bnRlcn0sIGlkeCkgPT4ge1xuICAgICAgY29uc3QgY3VycmVudEluZGV4ID0gaWR4IC0gaW5kZXhDb3VudGVyO1xuICAgICAgY3VycmVudFN0YXRlID0gcmVtb3ZlTGF5ZXJVcGRhdGVyKGN1cnJlbnRTdGF0ZSwge2lkeDogY3VycmVudEluZGV4fSk7XG4gICAgICBpbmRleENvdW50ZXIrKztcbiAgICAgIHJldHVybiB7bmV3U3RhdGU6IGN1cnJlbnRTdGF0ZSwgaW5kZXhDb3VudGVyfTtcbiAgICB9LFxuICAgIHtuZXdTdGF0ZTogey4uLnN0YXRlLCBkYXRhc2V0czogbmV3RGF0YXNldHN9LCBpbmRleENvdW50ZXI6IDB9XG4gICk7XG5cbiAgLy8gcmVtb3ZlIHdpZGdldHNcbiAgLy8gbmV3U3RhdGUgPSB7XG4gIC8vICAgLi4ubmV3U3RhdGUsXG4gIC8vICAgd2lkZ2V0czogd2lkZ2V0SW5kZXhlcy5tYXAoaWR4ID0+IFtcbiAgLy8gICAgIC4uLndpZGdldHMuc2xpY2UoMCwgaWR4KSxcbiAgLy8gICAgIC4uLndpZGdldHMuc2xpY2UoaWR4ICsgMSwgd2lkZ2V0cy5sZW5ndGgpXG4gIC8vICAgXSlcbiAgLy8gfTtcblxuICAvLyBjb25zdCB3aWRnZXRzID0gc3RhdGUud2lkZ2V0cy5maWx0ZXIoXG4gIC8vICAgd2lkZ2V0ID0+IHdpZGdldC5jb25maWcuZGF0YUlkICE9PSBkYXRhc2V0S2V5XG4gIC8vICk7XG5cbiAgY29uc3Qge2ZpbmFsU3RhdGV9ID0gd2lkZ2V0SW5kZXhlcy5yZWR1Y2UoXG4gICAgKHtmaW5hbFN0YXRlOiBzdGF0ZSwgaW5kZXhDb3VudGVyfSwgaWR4KSA9PiB7XG4gICAgICBjb25zdCBjdXJyZW50SW5kZXggPSBpZHggLSBpbmRleENvdW50ZXI7XG4gICAgICBzdGF0ZSA9IHJlbW92ZVdpZGdldFVwZGF0ZXIoc3RhdGUsIHtpZHg6IGN1cnJlbnRJbmRleH0pO1xuICAgICAgaW5kZXhDb3VudGVyKys7XG4gICAgICByZXR1cm4ge2ZpbmFsU3RhdGU6IHN0YXRlLCBpbmRleENvdW50ZXJ9O1xuICAgIH0sXG4gICAge2ZpbmFsU3RhdGU6IHsuLi5uZXdTdGF0ZX0sIGluZGV4Q291bnRlcjogMH1cbiAgKTtcblxuICAvLyByZW1vdmUgZmlsdGVyc1xuICBjb25zdCBmaWx0ZXJzID0gc3RhdGUuZmlsdGVycy5maWx0ZXIoXG4gICAgZmlsdGVyID0+ICFkYXRhc2V0S2V5LmluY2x1ZGVzKGZpbHRlci5kYXRhSWQpXG4gICk7XG5cbiAgLy8gdXBkYXRlIGludGVyYWN0aW9uQ29uZmlnXG4gIGxldCB7aW50ZXJhY3Rpb25Db25maWd9ID0gc3RhdGU7XG4gIGNvbnN0IHt0b29sdGlwfSA9IGludGVyYWN0aW9uQ29uZmlnO1xuICBpZiAodG9vbHRpcCkge1xuICAgIGNvbnN0IHtjb25maWd9ID0gdG9vbHRpcDtcbiAgICAvKiBlc2xpbnQtZGlzYWJsZSBuby11bnVzZWQtdmFycyAqL1xuICAgIGNvbnN0IHtbZGF0YXNldEtleV06IGZpZWxkcywgLi4uZmllbGRzVG9TaG93fSA9IGNvbmZpZy5maWVsZHNUb1Nob3c7XG4gICAgLyogZXNsaW50LWVuYWJsZSBuby11bnVzZWQtdmFycyAqL1xuICAgIGludGVyYWN0aW9uQ29uZmlnID0ge1xuICAgICAgLi4uaW50ZXJhY3Rpb25Db25maWcsXG4gICAgICB0b29sdGlwOiB7Li4udG9vbHRpcCwgY29uZmlnOiB7Li4uY29uZmlnLCBmaWVsZHNUb1Nob3d9fVxuICAgIH07XG4gIH1cblxuICByZXR1cm4gey4uLmZpbmFsU3RhdGUsIGZpbHRlcnMsIGludGVyYWN0aW9uQ29uZmlnfTtcbn07XG5cbi8qKlxuICogdXBkYXRlIGxheWVyIGJsZW5kaW5nIG1vZGVcbiAqIEBtZW1iZXJvZiB2aXNTdGF0ZVVwZGF0ZXJzXG4gKiBAcGFyYW0ge09iamVjdH0gc3RhdGUgYHZpc1N0YXRlYFxuICogQHBhcmFtIHtPYmplY3R9IGFjdGlvbiBhY3Rpb25cbiAqIEBwYXJhbSB7c3RyaW5nfSBhY3Rpb24ubW9kZSBvbmUgb2YgYGFkZGl0aXZlYCwgYG5vcm1hbGAgYW5kIGBzdWJ0cmFjdGl2ZWBcbiAqIEByZXR1cm5zIHtPYmplY3R9IG5leHRTdGF0ZVxuICogQHB1YmxpY1xuICovXG5leHBvcnQgY29uc3QgdXBkYXRlTGF5ZXJCbGVuZGluZ1VwZGF0ZXIgPSAoc3RhdGUsIGFjdGlvbikgPT4gKHtcbiAgLi4uc3RhdGUsXG4gIGxheWVyQmxlbmRpbmc6IGFjdGlvbi5tb2RlXG59KTtcblxuLyoqXG4gKiBEaXNwbGF5IGRhdGFzZXQgdGFibGUgaW4gYSBtb2RhbFxuICogQG1lbWJlcm9mIHZpc1N0YXRlVXBkYXRlcnNcbiAqIEBwYXJhbSB7T2JqZWN0fSBzdGF0ZSBgdmlzU3RhdGVgXG4gKiBAcGFyYW0ge09iamVjdH0gYWN0aW9uIGFjdGlvblxuICogQHBhcmFtIHtzdHJpbmd9IGFjdGlvbi5kYXRhSWQgZGF0YXNldCBpZCB0byBzaG93IGluIHRhYmxlXG4gKiBAcmV0dXJucyB7T2JqZWN0fSBuZXh0U3RhdGVcbiAqIEBwdWJsaWNcbiAqL1xuZXhwb3J0IGNvbnN0IHNob3dEYXRhc2V0VGFibGVVcGRhdGVyID0gKHN0YXRlLCBhY3Rpb24pID0+IHtcbiAgcmV0dXJuIHtcbiAgICAuLi5zdGF0ZSxcbiAgICBlZGl0aW5nRGF0YXNldDogYWN0aW9uLmRhdGFJZFxuICB9O1xufTtcblxuLyoqXG4gKiByZXNldCB2aXNTdGF0ZSB0byBpbml0aWFsIFN0YXRlXG4gKiBAbWVtYmVyb2YgdmlzU3RhdGVVcGRhdGVyc1xuICogQHBhcmFtIHtPYmplY3R9IHN0YXRlIGB2aXNTdGF0ZWBcbiAqIEByZXR1cm5zIHtPYmplY3R9IG5leHRTdGF0ZVxuICogQHB1YmxpY1xuICovXG5leHBvcnQgY29uc3QgcmVzZXRNYXBDb25maWdVcGRhdGVyID0gc3RhdGUgPT4gKHtcbiAgLi4uSU5JVElBTF9WSVNfU1RBVEUsXG4gIC4uLnN0YXRlLmluaXRpYWxTdGF0ZSxcbiAgaW5pdGlhbFN0YXRlOiBzdGF0ZS5pbml0aWFsU3RhdGVcbn0pO1xuXG4vKipcbiAqIFByb3BhZ2F0ZSBgdmlzU3RhdGVgIHJlZHVjZXIgd2l0aCBhIG5ldyBjb25maWd1cmF0aW9uLiBDdXJyZW50IGNvbmZpZyB3aWxsIGJlIG92ZXJyaWRlLlxuICogQG1lbWJlcm9mIHZpc1N0YXRlVXBkYXRlcnNcbiAqIEBwYXJhbSB7T2JqZWN0fSBzdGF0ZSBgdmlzU3RhdGVgXG4gKiBAcGFyYW0ge09iamVjdH0gYWN0aW9uIGFjdGlvblxuICogQHBhcmFtIHtPYmplY3R9IGFjdGlvbi5wYXlsb2FkIG1hcCBjb25maWcgdG8gYmUgcHJvcGFnYXRlZFxuICogQHBhcmFtIHtPYmplY3R9IGFjdGlvbi5wYXlsb2FkLmNvbmZpZyBtYXAgY29uZmlnIHRvIGJlIHByb3BhZ2F0ZWRcbiAqIEBwYXJhbSB7T2JqZWN0fSBhY3Rpb24ucGF5bG9hZC5vcHRpb24ge2tlZXBFeGlzdGluZ0NvbmZpZzogdHJ1ZSB8IGZhbHNlfVxuICogQHJldHVybnMge09iamVjdH0gbmV4dFN0YXRlXG4gKiBAcHVibGljXG4gKi9cbmV4cG9ydCBjb25zdCByZWNlaXZlTWFwQ29uZmlnVXBkYXRlciA9IChcbiAgc3RhdGUsXG4gIHtwYXlsb2FkOiB7Y29uZmlnID0ge30sIG9wdGlvbnMgPSB7fX19XG4pID0+IHtcbiAgaWYgKCFjb25maWcudmlzU3RhdGUpIHtcbiAgICByZXR1cm4gc3RhdGU7XG4gIH1cblxuICBjb25zdCB7XG4gICAgZmlsdGVycyxcbiAgICBsYXllcnMsXG4gICAgd2lkZ2V0cyxcbiAgICBpbnRlcmFjdGlvbkNvbmZpZyxcbiAgICBsYXllckJsZW5kaW5nLFxuICAgIHNwbGl0TWFwcyxcbiAgICBhbmltYXRpb25Db25maWdcbiAgfSA9IGNvbmZpZy52aXNTdGF0ZTtcblxuICBjb25zdCB7a2VlcEV4aXN0aW5nQ29uZmlnfSA9IG9wdGlvbnM7XG5cbiAgLy8gcmVzZXQgY29uZmlnIGlmIGtlZXBFeGlzdGluZ0NvbmZpZyBpcyBmYWxzeVxuICBsZXQgbWVyZ2VkU3RhdGUgPSAha2VlcEV4aXN0aW5nQ29uZmlnID8gcmVzZXRNYXBDb25maWdVcGRhdGVyKHN0YXRlKSA6IHN0YXRlO1xuICBtZXJnZWRTdGF0ZSA9IG1lcmdlRmlsdGVycyhtZXJnZWRTdGF0ZSwgZmlsdGVycyk7XG4gIC8vIGNvbnNvbGUubG9nKCdBZnRlciBNZXJnZUZpbHRlcnMnLCBtZXJnZWRTdGF0ZSk7XG4gIG1lcmdlZFN0YXRlID0gbWVyZ2VMYXllcnMobWVyZ2VkU3RhdGUsIGxheWVycyk7XG4gIC8vIGNvbnNvbGUubG9nKCdBZnRlciBNZXJnZUxheWVycycsIG1lcmdlZFN0YXRlKTtcbiAgbWVyZ2VkU3RhdGUgPSBtZXJnZUludGVyYWN0aW9ucyhtZXJnZWRTdGF0ZSwgaW50ZXJhY3Rpb25Db25maWcpO1xuICBtZXJnZWRTdGF0ZSA9IG1lcmdlTGF5ZXJCbGVuZGluZyhtZXJnZWRTdGF0ZSwgbGF5ZXJCbGVuZGluZyk7XG4gIG1lcmdlZFN0YXRlID0gbWVyZ2VTcGxpdE1hcHMobWVyZ2VkU3RhdGUsIHNwbGl0TWFwcyk7XG4gIG1lcmdlZFN0YXRlID0gbWVyZ2VBbmltYXRpb25Db25maWcobWVyZ2VkU3RhdGUsIGFuaW1hdGlvbkNvbmZpZyk7XG4gIG1lcmdlZFN0YXRlID0gbWVyZ2VXaWRnZXRzKG1lcmdlZFN0YXRlLCB3aWRnZXRzKTtcblxuICByZXR1cm4gbWVyZ2VkU3RhdGU7XG59O1xuXG4vKipcbiAqIFRyaWdnZXIgbGF5ZXIgaG92ZXIgZXZlbnQgd2l0aCBob3ZlcmVkIG9iamVjdFxuICogQG1lbWJlcm9mIHZpc1N0YXRlVXBkYXRlcnNcbiAqIEBwYXJhbSB7T2JqZWN0fSBzdGF0ZSBgdmlzU3RhdGVgXG4gKiBAcGFyYW0ge09iamVjdH0gYWN0aW9uIGFjdGlvblxuICogQHBhcmFtIHtPYmplY3R9IGFjdGlvbi5pbmZvIE9iamVjdCBob3ZlcmVkLCByZXR1cm5lZCBieSBkZWNrLmdsXG4gKiBAcmV0dXJucyB7T2JqZWN0fSBuZXh0U3RhdGVcbiAqIEBwdWJsaWNcbiAqL1xuZXhwb3J0IGNvbnN0IGxheWVySG92ZXJVcGRhdGVyID0gKHN0YXRlLCBhY3Rpb24pID0+ICh7XG4gIC4uLnN0YXRlLFxuICBob3ZlckluZm86IGFjdGlvbi5pbmZvXG59KTtcblxuLyoqXG4gKiBUcmlnZ2VyIGxheWVyIGNsaWNrIGV2ZW50IHdpdGggY2xpY2tlZCBvYmplY3RcbiAqIEBtZW1iZXJvZiB2aXNTdGF0ZVVwZGF0ZXJzXG4gKiBAcGFyYW0ge09iamVjdH0gc3RhdGUgYHZpc1N0YXRlYFxuICogQHBhcmFtIHtPYmplY3R9IGFjdGlvbiBhY3Rpb25cbiAqIEBwYXJhbSB7T2JqZWN0fSBhY3Rpb24uaW5mbyBPYmplY3QgY2xpY2tlZCwgcmV0dXJuZWQgYnkgZGVjay5nbFxuICogQHJldHVybnMge09iamVjdH0gbmV4dFN0YXRlXG4gKiBAcHVibGljXG4gKi9cbmV4cG9ydCBjb25zdCBsYXllckNsaWNrVXBkYXRlciA9IChzdGF0ZSwgYWN0aW9uKSA9PiAoe1xuICAuLi5zdGF0ZSxcbiAgbW91c2VQb3M6IHN0YXRlLmludGVyYWN0aW9uQ29uZmlnLmNvb3JkaW5hdGUuZW5hYmxlZFxuICAgID8ge1xuICAgICAgICAuLi5zdGF0ZS5tb3VzZVBvcyxcbiAgICAgICAgcGlubmVkOiBzdGF0ZS5tb3VzZVBvcy5waW5uZWQgPyBudWxsIDogY2xvbmVEZWVwKHN0YXRlLm1vdXNlUG9zKVxuICAgICAgfVxuICAgIDogc3RhdGUubW91c2VQb3MsXG4gIGNsaWNrZWQ6IGFjdGlvbi5pbmZvICYmIGFjdGlvbi5pbmZvLnBpY2tlZCA/IGFjdGlvbi5pbmZvIDogbnVsbFxufSk7XG5cbi8qKlxuICogVHJpZ2dlciBtYXAgY2xpY2sgZXZlbnQsIHVuc2VsZWN0IGNsaWNrZWQgb2JqZWN0XG4gKiBAbWVtYmVyb2YgdmlzU3RhdGVVcGRhdGVyc1xuICogQHBhcmFtIHtPYmplY3R9IHN0YXRlIGB2aXNTdGF0ZWBcbiAqIEByZXR1cm5zIHtPYmplY3R9IG5leHRTdGF0ZVxuICogQHB1YmxpY1xuICovXG5leHBvcnQgY29uc3QgbWFwQ2xpY2tVcGRhdGVyID0gc3RhdGUgPT4ge1xuICByZXR1cm4ge1xuICAgIC4uLnN0YXRlLFxuICAgIGNsaWNrZWQ6IG51bGxcbiAgfTtcbn07XG5cbmV4cG9ydCBjb25zdCBtb3VzZU1vdmVVcGRhdGVyID0gKHN0YXRlLCB7ZXZ0fSkgPT4ge1xuICBpZiAoT2JqZWN0LnZhbHVlcyhzdGF0ZS5pbnRlcmFjdGlvbkNvbmZpZykuc29tZShjb25maWcgPT4gY29uZmlnLmVuYWJsZWQpKSB7XG4gICAgcmV0dXJuIHtcbiAgICAgIC4uLnN0YXRlLFxuICAgICAgbW91c2VQb3M6IHtcbiAgICAgICAgLi4uc3RhdGUubW91c2VQb3MsXG4gICAgICAgIG1vdXNlUG9zaXRpb246IFsuLi5ldnQucG9pbnRdLFxuICAgICAgICBjb29yZGluYXRlOiBbLi4uZXZ0LmxuZ0xhdF1cbiAgICAgIH1cbiAgICB9O1xuICB9XG5cbiAgcmV0dXJuIHN0YXRlO1xufTtcbi8qKlxuICogVG9nZ2xlIHZpc2liaWxpdHkgb2YgYSBsYXllciBmb3IgYSBzcGxpdCBtYXBcbiAqIEBtZW1iZXJvZiB2aXNTdGF0ZVVwZGF0ZXJzXG4gKiBAcGFyYW0ge09iamVjdH0gc3RhdGUgYHZpc1N0YXRlYFxuICogQHBhcmFtIHtPYmplY3R9IGFjdGlvbiBhY3Rpb25cbiAqIEBwYXJhbSB7TnVtYmVyfHVuZGVmaW5lZH0gYWN0aW9uLnBheWxvYWQgaW5kZXggb2YgdGhlIHNwbGl0IG1hcFxuICogQHJldHVybnMge09iamVjdH0gbmV4dFN0YXRlXG4gKiBAcHVibGljXG4gKi9cbmV4cG9ydCBjb25zdCB0b2dnbGVTcGxpdE1hcFVwZGF0ZXIgPSAoc3RhdGUsIGFjdGlvbikgPT5cbiAgc3RhdGUuc3BsaXRNYXBzICYmIHN0YXRlLnNwbGl0TWFwcy5sZW5ndGggPT09IDBcbiAgICA/IHtcbiAgICAgICAgLi4uc3RhdGUsXG4gICAgICAgIC8vIG1heWJlIHdlIHNob3VsZCB1c2UgYW4gYXJyYXkgdG8gc3RvcmUgc3RhdGUgZm9yIGEgc2luZ2xlIG1hcCBhcyB3ZWxsXG4gICAgICAgIC8vIGlmIGN1cnJlbnQgbWFwcyBsZW5ndGggaXMgZXF1YWwgdG8gMCBpdCBtZWFucyB0aGF0IHdlIGFyZSBhYm91dCB0byBzcGxpdCB0aGUgdmlld1xuICAgICAgICBzcGxpdE1hcHM6IGNvbXB1dGVTcGxpdE1hcExheWVycyhzdGF0ZS5sYXllcnMpXG4gICAgICB9XG4gICAgOiBjbG9zZVNwZWNpZmljTWFwQXRJbmRleChzdGF0ZSwgYWN0aW9uKTtcblxuLyoqXG4gKiBUb2dnbGUgdmlzaWJpbGl0eSBvZiBhIGxheWVyIGluIGEgc3BsaXQgbWFwXG4gKiBAbWVtYmVyb2YgdmlzU3RhdGVVcGRhdGVyc1xuICogQHBhcmFtIHtPYmplY3R9IHN0YXRlXG4gKiBAcGFyYW0ge09iamVjdH0gYWN0aW9uXG4gKiBAcGFyYW0ge051bWJlcn0gYWN0aW9uLm1hcEluZGV4IGluZGV4IG9mIHRoZSBzcGxpdCBtYXBcbiAqIEBwYXJhbSB7c3RyaW5nfSBhY3Rpb24ubGF5ZXJJZCBpZCBvZiB0aGUgbGF5ZXJcbiAqIEByZXR1cm5zIHtPYmplY3R9IG5leHRTdGF0ZVxuICogQHB1YmxpY1xuICovXG5leHBvcnQgY29uc3QgdG9nZ2xlTGF5ZXJGb3JNYXBVcGRhdGVyID0gKHN0YXRlLCB7bWFwSW5kZXgsIGxheWVySWR9KSA9PiB7XG4gIGNvbnN0IHtzcGxpdE1hcHN9ID0gc3RhdGU7XG5cbiAgcmV0dXJuIHtcbiAgICAuLi5zdGF0ZSxcbiAgICBzcGxpdE1hcHM6IHNwbGl0TWFwcy5tYXAoKHNtLCBpKSA9PlxuICAgICAgaSA9PT0gbWFwSW5kZXhcbiAgICAgICAgPyB7XG4gICAgICAgICAgICAuLi5zcGxpdE1hcHNbaV0sXG4gICAgICAgICAgICBsYXllcnM6IHtcbiAgICAgICAgICAgICAgLi4uc3BsaXRNYXBzW2ldLmxheWVycyxcbiAgICAgICAgICAgICAgLy8gaWYgbGF5ZXJJZCBub3QgaW4gbGF5ZXJzLCBzZXQgaXQgdG8gdmlzaWJsZVxuICAgICAgICAgICAgICBbbGF5ZXJJZF06ICFzcGxpdE1hcHNbaV0ubGF5ZXJzW2xheWVySWRdXG4gICAgICAgICAgICB9XG4gICAgICAgICAgfVxuICAgICAgICA6IHNtXG4gICAgKVxuICB9O1xufTtcblxuLyoqXG4gKiBBZGQgbmV3IGRhdGFzZXQgdG8gYHZpc1N0YXRlYCwgd2l0aCBvcHRpb24gdG8gbG9hZCBhIG1hcCBjb25maWcgYWxvbmcgd2l0aCB0aGUgZGF0YXNldHNcbiAqIEBtZW1iZXJvZiB2aXNTdGF0ZVVwZGF0ZXJzXG4gKiBAcGFyYW0ge09iamVjdH0gc3RhdGUgYHZpc1N0YXRlYFxuICogQHBhcmFtIHtPYmplY3R9IGFjdGlvbiBhY3Rpb25cbiAqIEBwYXJhbSB7QXJyYXk8T2JqZWN0PnxPYmplY3R9IGFjdGlvbi5kYXRhc2V0cyAtICoqKnJlcXVpcmVkKiogZGF0YXNldHMgY2FuIGJlIGEgZGF0YXNldCBvciBhbiBhcnJheSBvZiBkYXRhc2V0c1xuICogRWFjaCBkYXRhc2V0IG9iamVjdCBuZWVkcyB0byBoYXZlIGBpbmZvYCBhbmQgYGRhdGFgIHByb3BlcnR5LlxuICogQHBhcmFtIHtPYmplY3R9IGFjdGlvbi5kYXRhc2V0cy5pbmZvIC1pbmZvIG9mIGEgZGF0YXNldFxuICogQHBhcmFtIHtzdHJpbmd9IGFjdGlvbi5kYXRhc2V0cy5pbmZvLmlkIC0gaWQgb2YgdGhpcyBkYXRhc2V0LiBJZiBjb25maWcgaXMgZGVmaW5lZCwgYGlkYCBzaG91bGQgbWF0Y2hlcyB0aGUgYGRhdGFJZGAgaW4gY29uZmlnLlxuICogQHBhcmFtIHtzdHJpbmd9IGFjdGlvbi5kYXRhc2V0cy5pbmZvLmxhYmVsIC0gQSBkaXNwbGF5IG5hbWUgb2YgdGhpcyBkYXRhc2V0XG4gKiBAcGFyYW0ge09iamVjdH0gYWN0aW9uLmRhdGFzZXRzLmRhdGEgLSAqKipyZXF1aXJlZCoqIFRoZSBkYXRhIG9iamVjdCwgaW4gYSB0YWJ1bGFyIGZvcm1hdCB3aXRoIDIgcHJvcGVydGllcyBgZmllbGRzYCBhbmQgYHJvd3NgXG4gKiBAcGFyYW0ge0FycmF5PE9iamVjdD59IGFjdGlvbi5kYXRhc2V0cy5kYXRhLmZpZWxkcyAtICoqKnJlcXVpcmVkKiogQXJyYXkgb2YgZmllbGRzLFxuICogQHBhcmFtIHtzdHJpbmd9IGFjdGlvbi5kYXRhc2V0cy5kYXRhLmZpZWxkcy5uYW1lIC0gKioqcmVxdWlyZWQqKiBOYW1lIG9mIHRoZSBmaWVsZCxcbiAqIEBwYXJhbSB7QXJyYXk8QXJyYXk+fSBhY3Rpb24uZGF0YXNldHMuZGF0YS5yb3dzIC0gKioqcmVxdWlyZWQqKiBBcnJheSBvZiByb3dzLCBpbiBhIHRhYnVsYXIgZm9ybWF0IHdpdGggYGZpZWxkc2AgYW5kIGByb3dzYFxuICogQHBhcmFtIHtPYmplY3R9IGFjdGlvbi5vcHRpb25zIG9wdGlvbiBvYmplY3QgYHtjZW50ZXJNYXA6IHRydWUsIGtlZXBFeGlzdGluZ0NvbmZpZzogZmFsc2V9YFxuICogQHBhcmFtIHtPYmplY3R9IGFjdGlvbi5jb25maWcgbWFwIGNvbmZpZ1xuICogQHJldHVybnMge09iamVjdH0gbmV4dFN0YXRlXG4gKiBAcHVibGljXG4gKi9cbi8qIGVzbGludC1kaXNhYmxlIG1heC1zdGF0ZW1lbnRzICovXG5leHBvcnQgY29uc3QgdXBkYXRlVmlzRGF0YVVwZGF0ZXIgPSAoc3RhdGUsIGFjdGlvbikgPT4ge1xuICAvLyBkYXRhc2V0cyBjYW4gYmUgYSBzaW5nbGUgZGF0YSBlbnRyaWVzIG9yIGFuIGFycmF5IG9mIG11bHRpcGxlIGRhdGEgZW50cmllc1xuICBjb25zdCB7Y29uZmlnLCBvcHRpb25zfSA9IGFjdGlvbjtcblxuICBjb25zdCBkYXRhc2V0cyA9IEFycmF5LmlzQXJyYXkoYWN0aW9uLmRhdGFzZXRzKVxuICAgID8gYWN0aW9uLmRhdGFzZXRzXG4gICAgOiBbYWN0aW9uLmRhdGFzZXRzXTtcblxuICBjb25zdCBuZXdEYXRlRW50cmllcyA9IGRhdGFzZXRzLnJlZHVjZShcbiAgICAoYWNjdSwge2luZm8gPSB7fSwgZGF0YX0pID0+ICh7XG4gICAgICAuLi5hY2N1LFxuICAgICAgLi4uKGNyZWF0ZU5ld0RhdGFFbnRyeSh7aW5mbywgZGF0YX0sIHN0YXRlLmRhdGFzZXRzKSB8fCB7fSlcbiAgICB9KSxcbiAgICB7fVxuICApO1xuXG4gIGlmICghT2JqZWN0LmtleXMobmV3RGF0ZUVudHJpZXMpLmxlbmd0aCkge1xuICAgIHJldHVybiBzdGF0ZTtcbiAgfVxuXG4gIC8vIGFwcGx5IGNvbmZpZyBpZiBwYXNzZWQgZnJvbSBhY3Rpb25cbiAgY29uc3QgcHJldmlvdXNTdGF0ZSA9IGNvbmZpZ1xuICAgID8gcmVjZWl2ZU1hcENvbmZpZ1VwZGF0ZXIoc3RhdGUsIHtcbiAgICAgICAgcGF5bG9hZDoge2NvbmZpZywgb3B0aW9uc31cbiAgICAgIH0pXG4gICAgOiBzdGF0ZTtcblxuICBjb25zdCBzdGF0ZVdpdGhOZXdEYXRhID0ge1xuICAgIC4uLnByZXZpb3VzU3RhdGUsXG4gICAgZGF0YXNldHM6IHtcbiAgICAgIC4uLnByZXZpb3VzU3RhdGUuZGF0YXNldHMsXG4gICAgICAuLi5uZXdEYXRlRW50cmllc1xuICAgIH1cbiAgfTtcblxuICAvLyBwcmV2aW91c2x5IHNhdmVkIGNvbmZpZyBiZWZvcmUgZGF0YSBsb2FkZWRcbiAgY29uc3Qge1xuICAgIGZpbHRlclRvQmVNZXJnZWQgPSBbXSxcbiAgICBsYXllclRvQmVNZXJnZWQgPSBbXSxcbiAgICB3aWRnZXRUb0JlTWVyZ2VkID0gW10sXG4gICAgaW50ZXJhY3Rpb25Ub0JlTWVyZ2VkID0ge30sXG4gICAgc3BsaXRNYXBzVG9CZU1lcmdlZCA9IFtdXG4gIH0gPSBzdGF0ZVdpdGhOZXdEYXRhO1xuXG4gIC8vIG1lcmdlIHN0YXRlIHdpdGggc2F2ZWQgbGF5ZXJzXG4gIC8vIG1ha2Ugc3VyZSBsYXllcnMgYXJlIG1lcmdlZCBmaXJzdFxuICBsZXQgbWVyZ2VkU3RhdGUgPSBtZXJnZUxheWVycyhzdGF0ZVdpdGhOZXdEYXRhLCBsYXllclRvQmVNZXJnZWQpO1xuXG4gIC8vIG1lcmdlIHN0YXRlIHdpdGggc2F2ZWQgZmlsdGVyc1xuICBtZXJnZWRTdGF0ZSA9IG1lcmdlRmlsdGVycyhtZXJnZWRTdGF0ZSwgZmlsdGVyVG9CZU1lcmdlZCk7XG5cbiAgLy8gbWVyZ2Ugc3RhdGUgd2l0aCBzYXZlZCBzcGxpdE1hcHNcbiAgbWVyZ2VkU3RhdGUgPSBtZXJnZVNwbGl0TWFwcyhtZXJnZWRTdGF0ZSwgc3BsaXRNYXBzVG9CZU1lcmdlZCk7XG5cbiAgbGV0IG5ld0xheWVycyA9IG1lcmdlZFN0YXRlLmxheWVycy5maWx0ZXIoXG4gICAgbCA9PiBsLmNvbmZpZy5kYXRhSWQgaW4gbmV3RGF0ZUVudHJpZXNcbiAgKTtcblxuICBpZiAoIW5ld0xheWVycy5sZW5ndGgpIHtcbiAgICAvLyBubyBsYXllciBtZXJnZWQsIGZpbmQgZGVmYXVsdHNcbiAgICBjb25zdCByZXN1bHQgPSBhZGREZWZhdWx0TGF5ZXJzKG1lcmdlZFN0YXRlLCBuZXdEYXRlRW50cmllcyk7XG4gICAgLy8gY29uc3QgcmVzdWx0ID0gbWVyZ2VkU3RhdGU7XG4gICAgbWVyZ2VkU3RhdGUgPSByZXN1bHQuc3RhdGU7XG4gICAgbmV3TGF5ZXJzID0gcmVzdWx0Lm5ld0xheWVycztcbiAgfVxuXG4gIC8vIGlmIChtZXJnZWRTdGF0ZS53aWRnZXRzLmxlbmd0aCA9PT0gc3RhdGUud2lkZ2V0cy5sZW5ndGgpIHtcbiAgLy8gICBtZXJnZWRTdGF0ZSA9IGFkZERlZmF1bHRXaWRnZXQobWVyZ2VkU3RhdGUsIG5ld0RhdGVFbnRyaWVzKTtcbiAgLy8gfVxuXG4gIGlmIChtZXJnZWRTdGF0ZS5zcGxpdE1hcHMubGVuZ3RoKSB7XG4gICAgLy8gaWYgbWFwIGlzIHNwbGl0LCBhZGQgbmV3IGxheWVycyB0byBzcGxpdE1hcHNcbiAgICBuZXdMYXllcnMgPSBtZXJnZWRTdGF0ZS5sYXllcnMuZmlsdGVyKFxuICAgICAgbCA9PiBsLmNvbmZpZy5kYXRhSWQgaW4gbmV3RGF0ZUVudHJpZXNcbiAgICApO1xuICAgIG1lcmdlZFN0YXRlID0ge1xuICAgICAgLi4ubWVyZ2VkU3RhdGUsXG4gICAgICBzcGxpdE1hcHM6IGFkZE5ld0xheWVyc1RvU3BsaXRNYXAobWVyZ2VkU3RhdGUuc3BsaXRNYXBzLCBuZXdMYXllcnMpXG4gICAgfTtcbiAgfVxuICAvLyBjb25zb2xlLmxvZyhtZXJnZWRTdGF0ZSk7XG5cbiAgLy8gbWVyZ2Ugc3RhdGUgd2l0aCBzYXZlZCBpbnRlcmFjdGlvbnNcbiAgbWVyZ2VkU3RhdGUgPSBtZXJnZUludGVyYWN0aW9ucyhtZXJnZWRTdGF0ZSwgaW50ZXJhY3Rpb25Ub0JlTWVyZ2VkKTtcblxuICAvLyBtZXJnZSBzdGF0ZSB3aXRoIHNhdmVkIHdpZGdldHNcbiAgbWVyZ2VkU3RhdGUgPSBtZXJnZVdpZGdldHMobWVyZ2VkU3RhdGUsIHdpZGdldFRvQmVNZXJnZWQpO1xuXG4gIC8vIGlmIG5vIHRvb2x0aXBzIG1lcmdlZCBhZGQgZGVmYXVsdCB0b29sdGlwc1xuICBPYmplY3Qua2V5cyhuZXdEYXRlRW50cmllcykuZm9yRWFjaChkYXRhSWQgPT4ge1xuICAgIGNvbnN0IHRvb2x0aXBGaWVsZHMgPVxuICAgICAgbWVyZ2VkU3RhdGUuaW50ZXJhY3Rpb25Db25maWcudG9vbHRpcC5jb25maWcuZmllbGRzVG9TaG93W2RhdGFJZF07XG4gICAgaWYgKCFBcnJheS5pc0FycmF5KHRvb2x0aXBGaWVsZHMpIHx8ICF0b29sdGlwRmllbGRzLmxlbmd0aCkge1xuICAgICAgbWVyZ2VkU3RhdGUgPSBhZGREZWZhdWx0VG9vbHRpcHMobWVyZ2VkU3RhdGUsIG5ld0RhdGVFbnRyaWVzW2RhdGFJZF0pO1xuICAgIH1cbiAgfSk7XG5cbiAgbGV0IHVwZGF0ZWRTdGF0ZSA9IHVwZGF0ZUFsbExheWVyRG9tYWluRGF0YShcbiAgICBtZXJnZWRTdGF0ZSxcbiAgICBPYmplY3Qua2V5cyhuZXdEYXRlRW50cmllcylcbiAgKTtcblxuICAvLyByZWdpc3RlciBsYXllciBhbmltYXRpb24gZG9tYWluLFxuICAvLyBuZWVkIHRvIGJlIGNhbGxlZCBhZnRlciBsYXllciBkYXRhIGlzIGNhbGN1bGF0ZWRcbiAgdXBkYXRlZFN0YXRlID0gdXBkYXRlQW5pbWF0aW9uRG9tYWluKHVwZGF0ZWRTdGF0ZSk7XG5cbiAgcmV0dXJuIHVwZGF0ZWRTdGF0ZTtcbn07XG4vKiBlc2xpbnQtZW5hYmxlIG1heC1zdGF0ZW1lbnRzICovXG5cbi8qKlxuICogSGlkZSBhbiBleGlzdGluZyBsYXllcnMgZnJvbSBjdXN0b20gbWFwIGxheWVyIG9iamVjdHNcbiAqIEBwYXJhbSBzdGF0ZVxuICogQHBhcmFtIHdpZGdldFxuICogQHJldHVybnMge1sqLCpdfSBNYXBzIG9mIGN1c3RvbSBsYXllciBvYmplY3RzXG4gKi9cbmZ1bmN0aW9uIHRvZ2dsZVdpZGdldEZyb21TcGxpdE1hcHMoc3RhdGUsIGxheWVyKSB7XG4gIC8vIGNvbnNvbGUubG9nKCcwJyk7XG4gIHJldHVybiBzdGF0ZS5zcGxpdE1hcHMubWFwKHNldHRpbmdzID0+IHtcbiAgICBjb25zdCB7d2lkZ2V0c30gPSBzZXR0aW5ncztcbiAgICBjb25zdCBuZXdXaWRnZXRzID0ge1xuICAgICAgLi4ud2lkZ2V0cyxcbiAgICAgIFt3aWRnZXQuaWRdOiBnZW5lcmF0ZUxheWVyTWV0YUZvclNwbGl0Vmlld3Mod2lkZ2V0KVxuICAgIH07XG5cbiAgICByZXR1cm4ge1xuICAgICAgLi4uc2V0dGluZ3MsXG4gICAgICB3aWRnZXRzOiBuZXdXaWRnZXRzXG4gICAgfTtcbiAgfSk7XG59XG5cbi8qKlxuICogV2hlbiBhIHVzZXIgY2xpY2tzIG9uIHRoZSBzcGVjaWZpYyBtYXAgY2xvc2luZyBpY29uXG4gKiB0aGUgYXBwbGljYXRpb24gd2lsbCBjbG9zZSB0aGUgc2VsZWN0ZWQgbWFwXG4gKiBhbmQgd2lsbCBtZXJnZSB0aGUgcmVtYWluaW5nIG9uZSB3aXRoIHRoZSBnbG9iYWwgc3RhdGVcbiAqIFRPRE86IGkgdGhpbmsgaW4gdGhlIGZ1dHVyZSB0aGlzIGFjdGlvbiBzaG91bGQgYmUgY2FsbGVkIG1lcmdlIG1hcCBsYXllcnMgd2l0aCBnbG9iYWwgc2V0dGluZ3NcbiAqIEBwYXJhbSB7T2JqZWN0fSBzdGF0ZSBgdmlzU3RhdGVgXG4gKiBAcGFyYW0ge09iamVjdH0gYWN0aW9uIGFjdGlvblxuICogQHJldHVybnMge09iamVjdH0gbmV4dFN0YXRlXG4gKi9cbmZ1bmN0aW9uIGNsb3NlU3BlY2lmaWNNYXBBdEluZGV4KHN0YXRlLCBhY3Rpb24pIHtcbiAgLy8gcmV0cmlldmUgbGF5ZXJzIG1ldGEgZGF0YSBmcm9tIHRoZSByZW1haW5pbmcgbWFwIHRoYXQgd2UgbmVlZCB0byBrZWVwXG4gIGNvbnN0IGluZGV4VG9SZXRyaWV2ZSA9IDEgLSBhY3Rpb24ucGF5bG9hZDtcbiAgY29uc3QgbWFwTGF5ZXJzID0gc3RhdGUuc3BsaXRNYXBzW2luZGV4VG9SZXRyaWV2ZV0ubGF5ZXJzO1xuICBjb25zdCB7bGF5ZXJzfSA9IHN0YXRlO1xuXG4gIC8vIHVwZGF0ZSBsYXllciB2aXNpYmlsaXR5XG4gIGNvbnN0IG5ld0xheWVycyA9IGxheWVycy5tYXAobGF5ZXIgPT5cbiAgICAhbWFwTGF5ZXJzW2xheWVyLmlkXSAmJiBsYXllci5jb25maWcuaXNWaXNpYmxlXG4gICAgICA/IGxheWVyLnVwZGF0ZUxheWVyQ29uZmlnKHtcbiAgICAgICAgICAvLyBpZiBsYXllci5pZCBpcyBub3QgaW4gbWFwTGF5ZXJzLCBpdCBzaG91bGQgYmUgaW5WaXNpYmxlXG4gICAgICAgICAgaXNWaXNpYmxlOiBmYWxzZVxuICAgICAgICB9KVxuICAgICAgOiBsYXllclxuICApO1xuXG4gIC8vIGRlbGV0ZSBtYXBcbiAgcmV0dXJuIHtcbiAgICAuLi5zdGF0ZSxcbiAgICBsYXllcnM6IG5ld0xheWVycyxcbiAgICBzcGxpdE1hcHM6IFtdXG4gIH07XG59XG5cbi8qKlxuICogVHJpZ2dlciBmaWxlIGxvYWRpbmcgZGlzcGF0Y2ggYGFkZERhdGFUb01hcGAgaWYgc3VjY2VlZCwgb3IgYGxvYWRGaWxlc0VycmAgaWYgZmFpbGVkXG4gKiBAbWVtYmVyb2YgdmlzU3RhdGVVcGRhdGVyc1xuICogQHBhcmFtIHtPYmplY3R9IHN0YXRlIGB2aXNTdGF0ZWBcbiAqIEBwYXJhbSB7T2JqZWN0fSBhY3Rpb24gYWN0aW9uXG4gKiBAcGFyYW0ge0FycmF5PE9iamVjdD59IGFjdGlvbi5maWxlcyBhcnJheSBvZiBmaWxlYmxvYlxuICogQHJldHVybnMge09iamVjdH0gbmV4dFN0YXRlXG4gKiBAcHVibGljXG4gKi9cbmV4cG9ydCBjb25zdCBsb2FkRmlsZXNVcGRhdGVyID0gKHN0YXRlLCBhY3Rpb24pID0+IHtcbiAgY29uc3Qge2ZpbGVzfSA9IGFjdGlvbjtcbiAgY29uc3QgZmlsZXNUb0xvYWQgPSBmaWxlcy5tYXAoZmlsZUJsb2IgPT4gcHJvY2Vzc0ZpbGVUb0xvYWQoZmlsZUJsb2IpKTtcbiAgLy8gcmVhZGVyIC0+IHBhcnNlciAtPiBhdWdtZW50IC0+IHJlY2VpdmVWaXNEYXRhXG4gIC8vIGNvbnNvbGUubG9nKCdMT0FEX0ZJTEVfVEFTSyBpbnNpZGUgbG9hZEZpbGVzVXBkYXRlcicsIExPQURfRklMRV9UQVNLKTtcbiAgY29uc3QgbG9hZEZpbGVUYXNrcyA9IFtcbiAgICBUYXNrLmFsbChmaWxlc1RvTG9hZC5tYXAoTE9BRF9GSUxFX1RBU0spKS5iaW1hcChyZXN1bHRzID0+IHtcbiAgICAgIGNvbnN0IGRhdGEgPSByZXN1bHRzLnJlZHVjZShcbiAgICAgICAgKGYsIGMpID0+ICh7XG4gICAgICAgICAgLy8gdXNpbmcgY29uY2F0IGhlcmUgYmVjYXVzZSB0aGUgY3VycmVudCBkYXRhc2V0cyBjb3VsZCBiZSBhbiBhcnJheSBvciBhIHNpbmdsZSBpdGVtXG4gICAgICAgICAgZGF0YXNldHM6IGYuZGF0YXNldHMuY29uY2F0KGMuZGF0YXNldHMpLFxuICAgICAgICAgIC8vIHdlIG5lZWQgdG8gZGVlcCBtZXJnZSB0aGlzIHRoaW5nIHVubGVzcyB3ZSBmaW5kIGEgYmV0dGVyIHNvbHV0aW9uXG4gICAgICAgICAgLy8gdGhpcyBjYXNlIHdpbGwgb25seSBoYXBwZW4gaWYgd2UgYWxsb3cgdG8gbG9hZCBtdWx0aXBsZSBrZXBsZXJnbCBqc29uIGZpbGVzXG4gICAgICAgICAgY29uZmlnOiB7XG4gICAgICAgICAgICAuLi5mLmNvbmZpZyxcbiAgICAgICAgICAgIC4uLihjLmNvbmZpZyB8fCB7fSlcbiAgICAgICAgICB9XG4gICAgICAgIH0pLFxuICAgICAgICB7ZGF0YXNldHM6IFtdLCBjb25maWc6IHt9LCBvcHRpb25zOiB7Y2VudGVyTWFwOiB0cnVlfX1cbiAgICAgICk7XG4gICAgICByZXR1cm4gYWRkRGF0YVRvTWFwKGRhdGEpO1xuICAgIH0sIGxvYWRGaWxlc0VycilcbiAgXTtcblxuICAvLyBjb25zb2xlLmxvZygnbG9hZEZpbGVUYXNrcyBpbnNpZGUgbG9hZEZpbGVzVXBkYXRlcicsIGxvYWRGaWxlVGFza3MpO1xuXG4gIHJldHVybiB3aXRoVGFzayhzdGF0ZSwgbG9hZEZpbGVUYXNrcyk7XG59O1xuXG4vKipcbiAqIFRyaWdnZXIgbG9hZGluZyBmaWxlIGVycm9yXG4gKiBAbWVtYmVyb2YgdmlzU3RhdGVVcGRhdGVyc1xuICogQHBhcmFtIHtPYmplY3R9IHN0YXRlIGB2aXNTdGF0ZWBcbiAqIEBwYXJhbSB7T2JqZWN0fSBhY3Rpb24gYWN0aW9uXG4gKiBAcGFyYW0geyp9IGFjdGlvbi5lcnJvclxuICogQHJldHVybnMge09iamVjdH0gbmV4dFN0YXRlXG4gKiBAcHVibGljXG4gKi9cbmV4cG9ydCBjb25zdCBsb2FkRmlsZXNFcnJVcGRhdGVyID0gKHN0YXRlLCB7ZXJyb3J9KSA9PiAoe1xuICAuLi5zdGF0ZSxcbiAgZmlsZUxvYWRpbmc6IGZhbHNlLFxuICBmaWxlTG9hZGluZ0VycjogZXJyb3Jcbn0pO1xuXG4vKipcbiAqXG4gKiBAcGFyYW0ge29iamVjdH0gc3RhdGUgYHZpc1N0YXRlYFxuICogQHBhcmFtIHtvYmplY3R9IGFjdGlvbiBhY3Rpb25cbiAqIEBwYXJhbSB7VGV4dDxPYmplY3Q+fSBhY3Rpb24uVVJMIHVybCBvZiBtYXBCb3ggdmVjdG9yIHRpbGVzXG4gKiBAcmV0dXJucyB7T2JqZWN0fSBuZXh0U3RhdGVcbiAqIEBwdWJsaWNcbiAqL1xuXG5leHBvcnQgZnVuY3Rpb24gbG9hZFVSTFVwZGF0ZXIoc3RhdGUsIGFjdGlvbikge1xuICBjb25zdCB7VVJMLCByYW5nZX0gPSBhY3Rpb247XG4gIHZhciBuZXdMYXllcjtcbiAgaWYgKFVSTCkge1xuICAgIGNvbnN0IGRhdGFJZCA9IGdlbmVyYXRlSGFzaElkKDQpO1xuICAgIGNvbnN0IGRhdGFzZXRzID0ge1xuICAgICAgW2RhdGFJZF06IHtcbiAgICAgICAgVVJMLFxuICAgICAgICBwb3B1bGF0aW9uUmFuZ2U6IHJhbmdlLFxuICAgICAgICBmaWVsZHM6IFtcbiAgICAgICAgICAvLyB7XG4gICAgICAgICAgLy8gICBmb3JtYXQ6ICcnLFxuICAgICAgICAgIC8vICAgaWQ6ICdfZ2VvanNvbicsXG4gICAgICAgICAgLy8gICBuYW1lOiAnX2dlb2pzb24nLFxuICAgICAgICAgIC8vICAgdGFibGVGaWVsZEluZGV4OiAxLFxuICAgICAgICAgIC8vICAgdHlwZTogJ2dlb2pzb24nXG4gICAgICAgICAgLy8gfSxcbiAgICAgICAgICAvLyB7XG4gICAgICAgICAgLy8gICBmb3JtYXQ6ICcnLFxuICAgICAgICAgIC8vICAgaWQ6ICdwb3B1bGF0aW9uJyxcbiAgICAgICAgICAvLyAgIG5hbWU6ICdQb3B1bGF0aW9uJyxcbiAgICAgICAgICAvLyAgIHRhYmxlRmllbGRJbmRleDogMixcbiAgICAgICAgICAvLyAgIHR5cGU6ICdpbnRlZ2VyJ1xuICAgICAgICAgIC8vIH1cbiAgICAgICAgXSxcbiAgICAgICAgaWQ6IGRhdGFJZCxcbiAgICAgICAgZXh0ZXJuYWxEYXRhOiB0cnVlLFxuICAgICAgICBjb2xvcjogZ2V0TmV3RGF0YXNldENvbG9yKHN0YXRlLmRhdGFzZXRzKSxcbiAgICAgICAgbGFiZWw6ICdwb3B1bGF0aW9uIGRhdGEnXG4gICAgICB9XG4gICAgfTtcbiAgICBzdGF0ZSA9IHsuLi5zdGF0ZSwgLi4uc3RhdGUuZGF0YXNldHMsIGRhdGFzZXRzfTtcbiAgICBuZXdMYXllciA9IG5ldyBzdGF0ZS5sYXllckNsYXNzZXMuTVZUKHtcbiAgICAgIGlzVmlzaWJsZTogdHJ1ZSxcbiAgICAgIGlzQ29uZmlnQWN0aXZlOiB0cnVlLFxuICAgICAgZGF0YUlkLFxuICAgICAgdXJsOiBVUkxcbiAgICB9KTtcblxuICAgIC8vIG5ld0xheWVyID0gbmV3IHN0YXRlLmxheWVyQ2xhc3Nlc1snbXZ0J10oKTtcbiAgfVxuXG4gIHJldHVybiB7XG4gICAgLi4uc3RhdGUsXG4gICAgbGF5ZXJzOiBbLi4uc3RhdGUubGF5ZXJzLCBuZXdMYXllcl0sXG4gICAgbGF5ZXJEYXRhOiBbLi4uc3RhdGUubGF5ZXJEYXRhLCB7fV0sXG4gICAgbGF5ZXJPcmRlcjogWy4uLnN0YXRlLmxheWVyT3JkZXIsIHN0YXRlLmxheWVyT3JkZXIubGVuZ3RoXSxcbiAgICBzcGxpdE1hcHM6IGFkZE5ld0xheWVyc1RvU3BsaXRNYXAoc3RhdGUuc3BsaXRNYXBzLCBuZXdMYXllcilcbiAgfTtcbn1cblxuZXhwb3J0IGNvbnN0IGxvYWRFRExpbmtEYXRhID0gKHN0YXRlLCBhY3Rpb24pID0+IHtcbiAgY29uc3Qge2RhdGEsIGRhdGFJZCwgaWR4fSA9IGFjdGlvbjtcbiAgY29uc3QgZGF0YXNldCA9IHByb2Nlc3NHZW9qc29uKGRhdGEpO1xuICBjb25zdCB2YWxpZGF0ZWREYXRhID0gdmFsaWRhdGVJbnB1dERhdGEoZGF0YXNldCk7XG4gIGlmICghdmFsaWRhdGVkRGF0YSkge1xuICAgIHJldHVybiBzdGF0ZTtcbiAgfVxuICBjb25zdCBhbGxEYXRhID0gdmFsaWRhdGVkRGF0YS5yb3dzO1xuICBjb25zdCBmaWVsZHMgPSB2YWxpZGF0ZWREYXRhLmZpZWxkcy5tYXAoKGYsIGkpID0+ICh7XG4gICAgLi4uZixcbiAgICBpZDogZi5uYW1lLFxuICAgIHRhYmxlRmllbGRJbmRleDogaSArIDFcbiAgfSkpO1xuXG4gIC8vIGNvbnN0IGlkeCA9IHN0YXRlLmxheWVycy5maW5kSW5kZXgobCA9PiBsLmNvbmZpZy5kYXRhSWQgPT09IGRhdGFJZCk7XG5cbiAgaWYgKHN0YXRlLmZpbHRlcnMubGVuZ3RoKSB7XG4gICAgY29uc3QgZmlsdGVycyA9IHN0YXRlLmZpbHRlcnMubWFwKGZpbHRlciA9PiB7XG4gICAgICBpZiAoZmlsdGVyLmRhdGFJZCA9PT0gZGF0YUlkKSB7XG4gICAgICAgIGNvbnN0IGZpZWxkID0gZGF0YXNldC5maWVsZHNbZmlsdGVyLmZpZWxkSWR4XTtcbiAgICAgICAgZmlsdGVyID0ge1xuICAgICAgICAgIC4uLmZpbHRlcixcbiAgICAgICAgICAuLi5nZXRGaWx0ZXJQcm9wcyhhbGxEYXRhLCBmaWVsZCksXG4gICAgICAgICAgdmFsdWU6IGZpbHRlci52YWx1ZVxuICAgICAgICB9O1xuICAgICAgfVxuICAgICAgcmV0dXJuIGZpbHRlcjtcbiAgICB9KTtcbiAgICBzdGF0ZSA9IHtcbiAgICAgIC4uLnN0YXRlLFxuICAgICAgZmlsdGVyc1xuICAgIH07XG4gIH1cbiAgLy8gZmlsdGVycy5tYXAoZiA9PntcbiAgLy8gICB2YXIgZmlsdGVyID0gZlxuICAvLyAgIGNvbnN0IGZpZWxkID0gZGF0YXNldC5maWVsZHNbZi5maWVsZElkeF1cbiAgLy8gICBmaWx0ZXIgPXtcbiAgLy8gICAgIC4uLmZpbHRlcixcbiAgLy8gICAgIC4uLmdldEZpbHRlclByb3BzKGRhdGFzZXRbYWxsRGF0YV0sZmllbGQpXG4gIC8vICAgfVxuICAvLyB9KVxuXG4gIC8vIGRhdGFzZXQgPSB7XG4gIC8vICAgLi4uZGF0YXNldFtkYXRhSWRdLCBhbGxEYXRhOiBhbGxEYXRhLFxuICAvLyAgIGZpZWxkczogZmllbGRzLFxuICAvLyAgIGRhdGE6IGFsbERhdGEuc2xpY2UoKSwgZmlsdGVyZWRJbmRleDogYWxsRGF0YS5tYXAoKF8sIGkpID0+IGkpLFxuICAvLyAgIGZpbHRlcmVkSW5kZXhGb3JEb21haW46IGFsbERhdGEubWFwKChfLCBpKSA9PiBpKSxcbiAgLy8gICBmaWVsZFBhaXJzOiBmaW5kUG9pbnRGaWVsZFBhaXJzKGZpZWxkcylcbiAgLy8gfVxuXG4gIC8vIGxldCBsYXllckRhdGEgPU9iamVjdC5hc3NpZ24oc3RhdGUubGF5ZXJEYXRhKTtcbiAgLy8gbGF5ZXJEYXRhW2lkeF0gPSBkYXRhLmZlYXR1cmVzO1xuXG4gIGNvbnN0IHN0YXRlV2l0aE5ld0RhdGEgPSB7XG4gICAgLi4uc3RhdGUsXG4gICAgZGF0YXNldHM6IHtcbiAgICAgIC4uLnN0YXRlLmRhdGFzZXRzLFxuICAgICAgW2RhdGFJZF06IHtcbiAgICAgICAgLi4uc3RhdGUuZGF0YXNldHNbZGF0YUlkXSxcbiAgICAgICAgYWxsRGF0YSxcbiAgICAgICAgZmllbGRzLFxuICAgICAgICAuLi5maWx0ZXJUaWxlTGF5ZXJEYXRhKFxuICAgICAgICAgIGFsbERhdGEsXG4gICAgICAgICAgc3RhdGUuZmlsdGVycyxcbiAgICAgICAgICBzdGF0ZS5sYXllcnMuZmlsdGVyKGwgPT4gbC5jb25maWcuZGF0YUlkID09PSBkYXRhSWQpXG4gICAgICAgICksXG4gICAgICAgIGZpZWxkUGFpcnM6IGZpbmRQb2ludEZpZWxkUGFpcnMoZmllbGRzKVxuICAgICAgfVxuICAgIH0sXG4gICAgbGF5ZXJEYXRhOiBzdGF0ZS5sYXllckRhdGEubWFwKChseXJEYXRhLCBpKSA9PlxuICAgICAgaSA9PT0gaWR4ID8gW2RhdGEuZmVhdHVyZXNdIDogbHlyRGF0YVxuICAgIClcbiAgfTtcblxuICByZXR1cm4gc3RhdGVXaXRoTmV3RGF0YTtcbn07XG5cbi8qKlxuICogaGVscGVyIGZ1bmN0aW9uIHRvIHVwZGF0ZSBBbGwgbGF5ZXIgZG9tYWluIGFuZCBsYXllciBkYXRhIG9mIHN0YXRlXG4gKlxuICogQHBhcmFtIHtvYmplY3R9IHN0YXRlXG4gKiBAcGFyYW0ge3N0cmluZ30gZGF0YXNldHNcbiAqIEByZXR1cm5zIHtvYmplY3R9IHN0YXRlXG4gKi9cbmV4cG9ydCBmdW5jdGlvbiBhZGREZWZhdWx0TGF5ZXJzKHN0YXRlLCBkYXRhc2V0cykge1xuICBjb25zdCBkZWZhdWx0TGF5ZXJzID0gT2JqZWN0LnZhbHVlcyhkYXRhc2V0cykucmVkdWNlKFxuICAgIChhY2N1LCBkYXRhc2V0KSA9PiBbXG4gICAgICAuLi5hY2N1LFxuICAgICAgLi4uKGZpbmREZWZhdWx0TGF5ZXIoZGF0YXNldCwgc3RhdGUubGF5ZXJDbGFzc2VzKSB8fCBbXSlcbiAgICBdLFxuICAgIFtdXG4gICk7XG5cbiAgcmV0dXJuIHtcbiAgICBzdGF0ZToge1xuICAgICAgLi4uc3RhdGUsXG4gICAgICBsYXllcnM6IFsuLi5zdGF0ZS5sYXllcnMsIC4uLmRlZmF1bHRMYXllcnNdLFxuICAgICAgbGF5ZXJPcmRlcjogW1xuICAgICAgICAvLyBwdXQgbmV3IGxheWVycyBvbiB0b3Agb2Ygb2xkIG9uZXNcbiAgICAgICAgLi4uZGVmYXVsdExheWVycy5tYXAoKF8sIGkpID0+IHN0YXRlLmxheWVycy5sZW5ndGggKyBpKSxcbiAgICAgICAgLi4uc3RhdGUubGF5ZXJPcmRlclxuICAgICAgXVxuICAgIH0sXG4gICAgbmV3TGF5ZXJzOiBkZWZhdWx0TGF5ZXJzXG4gIH07XG59XG5cbi8qKlxuICogaGVscGVyIGZ1bmN0aW9uIHRvIHVwZGF0ZSBBbGwgbGF5ZXIgZG9tYWluIGFuZCBsYXllciBkYXRhIG9mIHN0YXRlXG4gKlxuICogQHBhcmFtIHtvYmplY3R9IHN0YXRlXG4gKiBAcGFyYW0ge3N0cmluZ30gZGF0YXNldHNcbiAqIEByZXR1cm5zIHtvYmplY3R9IHN0YXRlXG4gKi9cbi8vIGV4cG9ydCBmdW5jdGlvbiBhZGREZWZhdWx0V2lkZ2V0KHN0YXRlLCBkYXRhc2V0cykge1xuLy8gICBjb25zdCBkZWZhdWx0V2lkZ2V0ID0gT2JqZWN0LnZhbHVlcyhkYXRhc2V0cykucmVkdWNlKFxuLy8gICAgIChhY2N1LCBkYXRhc2V0KSA9PiBbXG4vLyAgICAgICAuLi5hY2N1LFxuLy8gICAgICAgLi4uKGZpbmREZWZhdWx0TGF5ZXIoZGF0YXNldCwgc3RhdGUud2lkZ2V0Q2xhc3NlcykgfHwgW10pXG4vLyAgICAgXSxcbi8vICAgICBbXVxuLy8gICApO1xuLy8gICByZXR1cm4ge1xuLy8gICAgIC4uLnN0YXRlLFxuLy8gICAgIHdpZGdldHM6IFsuLi5zdGF0ZS53aWRnZXRzLCAuLi5kZWZhdWx0V2lkZ2V0XSxcbi8vICAgICBsYXllck9yZGVyOiBbXG4vLyAgICAgICAvLyBwdXQgbmV3IGxheWVycyBvbiB0b3Agb2Ygb2xkIG9uZXNcbi8vICAgICAgIC4uLmRlZmF1bHRXaWRnZXQubWFwKChfLCBpKSA9PiBzdGF0ZS53aWRnZXRzLmxlbmd0aCArIGkpLFxuLy8gICAgICAgLi4uc3RhdGUud2lkZ2V0T3JkZXJcbi8vICAgICBdXG4vLyAgIH07XG4vLyB9XG5cbi8qKlxuICogaGVscGVyIGZ1bmN0aW9uIHRvIGZpbmQgZGVmYXVsdCB0b29sdGlwc1xuICogQHBhcmFtIHtPYmplY3R9IHN0YXRlXG4gKiBAcGFyYW0ge09iamVjdH0gZGF0YXNldFxuICogQHJldHVybnMge09iamVjdH0gbmV4dFN0YXRlXG4gKi9cbmV4cG9ydCBmdW5jdGlvbiBhZGREZWZhdWx0VG9vbHRpcHMoc3RhdGUsIGRhdGFzZXQpIHtcbiAgY29uc3QgdG9vbHRpcEZpZWxkcyA9IGZpbmRGaWVsZHNUb1Nob3coZGF0YXNldCk7XG5cbiAgcmV0dXJuIHtcbiAgICAuLi5zdGF0ZSxcbiAgICBpbnRlcmFjdGlvbkNvbmZpZzoge1xuICAgICAgLi4uc3RhdGUuaW50ZXJhY3Rpb25Db25maWcsXG4gICAgICB0b29sdGlwOiB7XG4gICAgICAgIC4uLnN0YXRlLmludGVyYWN0aW9uQ29uZmlnLnRvb2x0aXAsXG4gICAgICAgIGNvbmZpZzoge1xuICAgICAgICAgIC8vIGZpbmQgZGVmYXVsdCBmaWVsZHMgdG8gc2hvdyBpbiB0b29sdGlwXG4gICAgICAgICAgZmllbGRzVG9TaG93OiB7XG4gICAgICAgICAgICAuLi5zdGF0ZS5pbnRlcmFjdGlvbkNvbmZpZy50b29sdGlwLmNvbmZpZy5maWVsZHNUb1Nob3csXG4gICAgICAgICAgICAuLi50b29sdGlwRmllbGRzXG4gICAgICAgICAgfVxuICAgICAgICB9XG4gICAgICB9XG4gICAgfVxuICB9O1xufVxuXG4vKipcbiAqIEhlbHBlciBmdW5jdGlvbiB0byB1cGRhdGUgbGF5ZXIgZG9tYWlucyBmb3IgYW4gYXJyYXkgb2YgZGF0YXNldHNcbiAqIEBwYXJhbSB7T2JqZWN0fSBzdGF0ZVxuICogQHBhcmFtIHtBcnJheXxBcnJheTxzdHJpbmc+fSBkYXRhSWQgZGF0YXNldCBpZCBvciBhcnJheSBvZiBkYXRhc2V0IGlkc1xuICogQHBhcmFtIHtPYmplY3R9IG5ld0ZpbHRlciBpZiBpcyBjYWxsZWQgYnkgc2V0RmlsdGVyLCB0aGUgZmlsdGVyIHRoYXQgaGFzIGNoYW5nZWRcbiAqIEByZXR1cm5zIHtPYmplY3R9IG5leHRTdGF0ZVxuICovXG5leHBvcnQgZnVuY3Rpb24gdXBkYXRlQWxsTGF5ZXJEb21haW5EYXRhKHN0YXRlLCBkYXRhSWQsIG5ld0ZpbHRlcikge1xuICBjb25zdCBkYXRhSWRzID0gdHlwZW9mIGRhdGFJZCA9PT0gJ3N0cmluZycgPyBbZGF0YUlkXSA6IGRhdGFJZDtcbiAgY29uc3QgbmV3TGF5ZXJzID0gW107XG4gIGNvbnN0IG5ld0xheWVyRGF0YSA9IFtdO1xuICBzdGF0ZS5sYXllcnMuZm9yRWFjaCgob2xkTGF5ZXIsIGkpID0+IHtcbiAgICBpZiAob2xkTGF5ZXIuY29uZmlnLmRhdGFJZCAmJiBkYXRhSWRzLmluY2x1ZGVzKG9sZExheWVyLmNvbmZpZy5kYXRhSWQpKSB7XG4gICAgICAvLyBObyBuZWVkIHRvIHJlY2FsY3VsYXRlIGxheWVyIGRvbWFpbiBpZiBmaWx0ZXIgaGFzIGZpeGVkIGRvbWFpblxuICAgICAgdmFyIG5ld0xheWVyO1xuICAgICAgaWYgKG9sZExheWVyLnR5cGUgPT09ICdib3VuZGFyeScpIHtcbiAgICAgICAgbmV3TGF5ZXIgPVxuICAgICAgICAgIG5ld0ZpbHRlciAmJiBuZXdGaWx0ZXIuZml4ZWREb21haW5cbiAgICAgICAgICAgID8gb2xkTGF5ZXJcbiAgICAgICAgICAgIDogb2xkTGF5ZXIudXBkYXRlTGF5ZXJEb21haW4oXG4gICAgICAgICAgICAgICAgc3RhdGUuZGF0YXNldHNbb2xkTGF5ZXIuY29uZmlnLmRhdGFJZF0sXG4gICAgICAgICAgICAgICAgc3RhdGUubGF5ZXJEYXRhW2ldLFxuICAgICAgICAgICAgICAgIG5ld0ZpbHRlclxuICAgICAgICAgICAgICApO1xuICAgICAgfSBlbHNlIHtcbiAgICAgICAgbmV3TGF5ZXIgPVxuICAgICAgICAgIG5ld0ZpbHRlciAmJiBuZXdGaWx0ZXIuZml4ZWREb21haW5cbiAgICAgICAgICAgID8gb2xkTGF5ZXJcbiAgICAgICAgICAgIDogb2xkTGF5ZXIudXBkYXRlTGF5ZXJEb21haW4oXG4gICAgICAgICAgICAgICAgc3RhdGUuZGF0YXNldHNbb2xkTGF5ZXIuY29uZmlnLmRhdGFJZF0sXG4gICAgICAgICAgICAgICAgbmV3RmlsdGVyXG4gICAgICAgICAgICAgICk7XG4gICAgICB9XG4gICAgICB2YXIge2xheWVyRGF0YSwgbGF5ZXJ9ID0gY2FsY3VsYXRlTGF5ZXJEYXRhKFxuICAgICAgICBuZXdMYXllcixcbiAgICAgICAgc3RhdGUsXG4gICAgICAgIHN0YXRlLmxheWVyRGF0YVtpXVxuICAgICAgKTtcblxuICAgICAgLy8gY29uc29sZS5sb2coJ0xheWVyRGF0YScsIGxheWVyRGF0YSk7XG4gICAgICBuZXdMYXllcnMucHVzaChsYXllcik7XG4gICAgICBuZXdMYXllckRhdGEucHVzaChsYXllckRhdGEpO1xuICAgIH0gZWxzZSB7XG4gICAgICBuZXdMYXllcnMucHVzaChvbGRMYXllcik7XG4gICAgICBuZXdMYXllckRhdGEucHVzaChzdGF0ZS5sYXllckRhdGFbaV0pO1xuICAgIH1cbiAgfSk7XG5cbiAgY29uc3QgbmV3U3RhdGUgPSB7XG4gICAgLi4uc3RhdGUsXG4gICAgbGF5ZXJzOiBuZXdMYXllcnMsXG4gICAgbGF5ZXJEYXRhOiBuZXdMYXllckRhdGFcbiAgfTtcblxuICByZXR1cm4gbmV3U3RhdGU7XG59XG5cbmV4cG9ydCBmdW5jdGlvbiB1cGRhdGVBbmltYXRpb25Eb21haW4oc3RhdGUpIHtcbiAgLy8gbWVyZ2UgYWxsIGFuaW1hdGFibGUgbGF5ZXIgZG9tYWluIGFuZCB1cGRhdGUgZ2xvYmFsIGNvbmZpZ1xuICBjb25zdCBhbmltYXRhYmxlTGF5ZXJzID0gc3RhdGUubGF5ZXJzLmZpbHRlcihcbiAgICBsID0+XG4gICAgICBsLmNvbmZpZy5pc1Zpc2libGUgJiZcbiAgICAgIGwuY29uZmlnLmFuaW1hdGlvbiAmJlxuICAgICAgbC5jb25maWcuYW5pbWF0aW9uLmVuYWJsZWQgJiZcbiAgICAgIEFycmF5LmlzQXJyYXkobC5hbmltYXRpb25Eb21haW4pXG4gICk7XG5cbiAgaWYgKCFhbmltYXRhYmxlTGF5ZXJzLmxlbmd0aCkge1xuICAgIHJldHVybiB7XG4gICAgICAuLi5zdGF0ZSxcbiAgICAgIGFuaW1hdGlvbkNvbmZpZzogZGVmYXVsdEFuaW1hdGlvbkNvbmZpZ1xuICAgIH07XG4gIH1cblxuICBjb25zdCBtZXJnZWREb21haW4gPSBhbmltYXRhYmxlTGF5ZXJzLnJlZHVjZShcbiAgICAoYWNjdSwgbGF5ZXIpID0+IFtcbiAgICAgIE1hdGgubWluKGFjY3VbMF0sIGxheWVyLmFuaW1hdGlvbkRvbWFpblswXSksXG4gICAgICBNYXRoLm1heChhY2N1WzFdLCBsYXllci5hbmltYXRpb25Eb21haW5bMV0pXG4gICAgXSxcbiAgICBbTnVtYmVyKEluZmluaXR5KSwgLUluZmluaXR5XVxuICApO1xuXG4gIHJldHVybiB7XG4gICAgLi4uc3RhdGUsXG4gICAgYW5pbWF0aW9uQ29uZmlnOiB7XG4gICAgICAuLi5zdGF0ZS5hbmltYXRpb25Db25maWcsXG4gICAgICBjdXJyZW50VGltZTogaXNJblJhbmdlKHN0YXRlLmFuaW1hdGlvbkNvbmZpZy5jdXJyZW50VGltZSwgbWVyZ2VkRG9tYWluKVxuICAgICAgICA/IHN0YXRlLmFuaW1hdGlvbkNvbmZpZy5jdXJyZW50VGltZVxuICAgICAgICA6IG1lcmdlZERvbWFpblswXSxcbiAgICAgIGRvbWFpbjogbWVyZ2VkRG9tYWluXG4gICAgfVxuICB9O1xufVxuXG4vKipcbiAqIGhlbHBlciBmdW5jdGlvbiB0byByZWNhbGN1bHRlIHdpZGdldCBhZ2dyZWdhdGlvbkRhdGEgZXZlcnl0aW1lIGxheWVyRGF0YSBpcyB1cGRhdGVkXG4gKlxuICogQHBhcmFtIHtvYmplY3R9IHN0YXRlXG4gKiBAcmV0dXJucyB7b2JqZWN0fSBzdGF0ZVxuICovXG5cbmV4cG9ydCBmdW5jdGlvbiB1cGRhdGVXaWRnZXRBZ2dyZWdhdGlvbkRhdGEoc3RhdGUsIG1hcFN0YXRlLCBhdXRoLCBwcm9qZWN0KSB7XG4gIHZhciB3aWRnZXRzID0gc3RhdGUud2lkZ2V0cztcbiAgdmFyIG5ld1dpZGdldHMgPSBbXTtcblxuICB3aWRnZXRzLm1hcCh3ID0+IHtcbiAgICBjb25zdCB7bmV3V2lkZ2V0fSA9IHcuY2FsY3VsYXRlQWdncmVnYXRpb25EYXRhKFxuICAgICAgdyxcbiAgICAgIHN0YXRlLFxuICAgICAgbWFwU3RhdGUsXG4gICAgICBhdXRoLFxuICAgICAgcHJvamVjdFxuICAgICk7XG4gICAgbmV3V2lkZ2V0cy5wdXNoKG5ld1dpZGdldCk7XG4gIH0pO1xuICByZXR1cm4ge1xuICAgIC4uLnN0YXRlLFxuICAgIHdpZGdldHM6IG5ld1dpZGdldHNcbiAgfTtcbn1cblxuLyoqXG4gKiBoZWxwZXIgZnVuY3Rpb24gdG8gdXBkYXRlIHN0YXRlc1xuICpcbiAqIEBwYXJhbSB7b2JqZWN0fSBzdGF0ZVxuICogQHJldHVybnMge29iamVjdH0gc3RhdGVcbiAqL1xuXG5leHBvcnQgZnVuY3Rpb24gdXBkYXRlU3RhdGVXaXRoTGF5ZXJEYXRhVXBkYXRlcihzdGF0ZSwgYWN0aW9uKSB7XG4gIGNvbnN0IHtjb2xsZWN0ZWR9ID0gYWN0aW9uO1xuICBjb25zdCBuZXdMYXllciA9IGFjdGlvbi5sYXllcjtcbiAgY29uc3QgaWR4ID0gc3RhdGUubGF5ZXJzLmZpbmRJbmRleChsID0+IGwuaWQgPT09IG5ld0xheWVyLmlkKTtcbiAgdmFyIHtsYXllckRhdGEsIGxheWVyfSA9IGNhbGN1bGF0ZUxheWVyRGF0YUFmdGVyQVBJQ2FsbChcbiAgICBuZXdMYXllcixcbiAgICBzdGF0ZSxcbiAgICBzdGF0ZS5sYXllckRhdGFbaWR4XSxcbiAgICBjb2xsZWN0ZWQsXG4gICAge3NhbWVEYXRhOiB0cnVlfVxuICApO1xuICByZXR1cm4ge1xuICAgIC4uLnN0YXRlLFxuICAgIGxheWVyRGF0YTogc3RhdGUubGF5ZXJEYXRhLm1hcCgobHlyRGF0YSwgaSkgPT5cbiAgICAgIGkgPT09IGlkeCA/IGxheWVyRGF0YSA6IGx5ckRhdGFcbiAgICApXG4gIH07XG59XG5cbi8qKlxuICogaGVscGVyIGZ1bmN0aW9uIGZvciBhc3luYyBBUEkgY2FsbFxuICpcbiAqIEBwYXJhbSB7b2JqZWN0fSBzdGF0ZVxuICogQHJldHVybnMge29iamVjdH0gZGF0YVxuICovXG5leHBvcnQgZnVuY3Rpb24gYXBpQ2FsbERhdGEoc3RhdGUsIGFjdGlvbikge1xuICAvLyBjb25zb2xlLmxvZyhzdGF0ZSwgYWN0aW9uKTtcbiAgY29uc3Qge2xheWVyfSA9IGFjdGlvbjtcbiAgY29uc3Qge2FsbERhdGF9ID0gc3RhdGUuZGF0YXNldHNbbGF5ZXIuY29uZmlnLmRhdGFJZF07XG4gIC8vIGNvbnNvbGUubG9nKGFsbERhdGEpO1xuICByZXR1cm4gc3RhdGU7XG59XG5cbi8qKlxuICogdXBkYXRlIGRhdGFzZXQgbGFzdCBydW4gdGltZVxuICogQG1lbWJlcm9mIHZpc1N0YXRlVXBkYXRlcnNcbiAqIEBwYXJhbSBzdGF0ZVxuICogQHBhcmFtIHtPYmplY3R9IHBheWxvYWRcbiAqIEByZXR1cm4ge09iamVjdH0gbmV4dFN0YXRlXG4gKi9cblxuZXhwb3J0IGZ1bmN0aW9uIHVwZGF0ZURhdGFzZXRJbmZvKHN0YXRlLCBhY3Rpb24pIHtcbiAgY29uc3Qge2RhdGFJZCwgdXBkYXRlZEF0fSA9IGFjdGlvbjtcblxuICBjb25zdCBuZXdTdGF0ZSA9IHtcbiAgICAuLi5zdGF0ZSxcbiAgICBkYXRhc2V0czoge1xuICAgICAgLi4uc3RhdGUuZGF0YXNldHMsXG4gICAgICBbZGF0YUlkXToge1xuICAgICAgICAuLi5zdGF0ZS5kYXRhc2V0c1tkYXRhSWRdLFxuICAgICAgICBsYXN0VXBkYXRlZEF0OiB1cGRhdGVkQXRcbiAgICAgIH1cbiAgICB9XG4gIH07XG4gIHJldHVybiBuZXdTdGF0ZTtcbn1cblxuLyoqXG4gKiBVcGRhdGUgdGhlIHN0YXR1cyBvZiB0aGUgZWRpdG9yXG4gKiBAbWVtYmVyb2YgdmlzU3RhdGVVcGRhdGVyc1xuICogQHBhcmFtIHtPYmplY3R9IHN0YXRlIGB2aXNTdGF0ZWBcbiAqIEBwYXJhbSB7c3RyaW5nfSBtb2RlIHRvIHNldCB0byBlZGl0b3IgdG9cbiAqIEByZXR1cm4ge09iamVjdH0gbmV4dFN0YXRlXG4gKi9cbmV4cG9ydCBjb25zdCBzZXRFZGl0b3JNb2RlVXBkYXRlciA9IChzdGF0ZSwge21vZGV9KSA9PiAoe1xuICAuLi5zdGF0ZSxcbiAgZWRpdG9yOiB7XG4gICAgLi4uc3RhdGUuZWRpdG9yLFxuICAgIG1vZGUsXG4gICAgc2VsZWN0ZWRGZWF0dXJlOiBudWxsXG4gIH1cbn0pO1xuXG4vLyBjb25zdCBmZWF0dXJlVG9GaWx0ZXJWYWx1ZSA9IChmZWF0dXJlKSA9PiAoey4uLmZlYXR1cmUsIGlkOiBmZWF0dXJlLmlkfSk7XG4vKipcbiAqIFVwZGF0ZSBlZGl0b3IgZmVhdHVyZXNcbiAqIEBtZW1iZXJvZiB2aXNTdGF0ZVVwZGF0ZXJzXG4gKiBAcGFyYW0ge09iamVjdH0gc3RhdGUgYHZpc1N0YXRlYFxuICogQHBhcmFtIHtbT2JqZWN0XX0gZmVhdHVyZXMgdG8gc3RvcmVcbiAqIEByZXR1cm4ge09iamVjdH0gbmV4dFN0YXRlXG4gKi9cbmV4cG9ydCBmdW5jdGlvbiBzZXRGZWF0dXJlc1VwZGF0ZXIoXG4gIHN0YXRlLFxuICB7ZmVhdHVyZXMgPSBbXSwgYXV0aCwgcHJvamVjdCwgbWFwU3RhdGV9XG4pIHtcbiAgY29uc3QgbGFzdEZlYXR1cmUgPSBmZWF0dXJlcy5sZW5ndGggJiYgZmVhdHVyZXNbZmVhdHVyZXMubGVuZ3RoIC0gMV07XG5cbiAgY29uc3QgbmV3U3RhdGUgPSB7XG4gICAgLi4uc3RhdGUsXG4gICAgZWRpdG9yOiB7XG4gICAgICAuLi5zdGF0ZS5lZGl0b3IsXG4gICAgICAvLyBvbmx5IHNhdmUgbm9uZSBmaWx0ZXIgZmVhdHVyZXMgdG8gZWRpdG9yXG4gICAgICBmZWF0dXJlczogZmVhdHVyZXMuZmlsdGVyKGYgPT4gIWdldEZpbHRlcklkSW5GZWF0dXJlKGYpKSxcbiAgICAgIG1vZGU6XG4gICAgICAgIGxhc3RGZWF0dXJlICYmIGxhc3RGZWF0dXJlLnByb3BlcnRpZXMuaXNDbG9zZWRcbiAgICAgICAgICA/IEVESVRPUl9NT0RFUy5FRElUXG4gICAgICAgICAgOiBzdGF0ZS5lZGl0b3IubW9kZVxuICAgIH1cbiAgfTtcblxuICAvLyBSZXRyaWV2ZSBleGlzdGluZyBmZWF0dXJlXG4gIGNvbnN0IHtzZWxlY3RlZEZlYXR1cmV9ID0gc3RhdGUuZWRpdG9yO1xuXG4gIC8vIElmIG5vIGZlYXR1cmUgaXMgc2VsZWN0ZWQgd2UgY2FuIHNpbXBseSByZXR1cm4gc2luY2Ugbm8gb3BlcmF0aW9uc1xuICBpZiAoIXNlbGVjdGVkRmVhdHVyZSkge1xuICAgIHJldHVybiBuZXdTdGF0ZTtcbiAgfVxuXG4gIC8vIFRPRE86IGNoZWNrIGlmIHRoZSBmZWF0dXJlIGhhcyBjaGFuZ2VkXG4gIGNvbnN0IGZlYXR1cmUgPSBmZWF0dXJlcy5maW5kKGYgPT4gZi5pZCA9PT0gc2VsZWN0ZWRGZWF0dXJlLmlkKTtcblxuICAvLyBpZiBmZWF0dXJlIGlzIHBhcnQgb2YgYSBmaWx0ZXJcbiAgY29uc3QgZmlsdGVySWQgPSBmZWF0dXJlICYmIGdldEZpbHRlcklkSW5GZWF0dXJlKGZlYXR1cmUpO1xuICBpZiAoZmlsdGVySWQpIHtcbiAgICBjb25zdCBmZWF0dXJlVmFsdWUgPSBmZWF0dXJlVG9GaWx0ZXJWYWx1ZShmZWF0dXJlLCBmaWx0ZXJJZCk7XG4gICAgY29uc3QgZmlsdGVySWR4ID0gc3RhdGUuZmlsdGVycy5maW5kSW5kZXgoZmlsID0+IGZpbC5pZCA9PT0gZmlsdGVySWQpO1xuICAgIHJldHVybiBzZXRGaWx0ZXJVcGRhdGVyKG5ld1N0YXRlLCB7XG4gICAgICBpZHg6IGZpbHRlcklkeCxcbiAgICAgIHByb3A6ICd2YWx1ZScsXG4gICAgICB2YWx1ZTogZmVhdHVyZVZhbHVlLFxuICAgICAgYXV0aCxcbiAgICAgIHByb2plY3QsXG4gICAgICBtYXBTdGF0ZVxuICAgIH0pO1xuICB9XG5cbiAgcmV0dXJuIG5ld1N0YXRlO1xufVxuXG4vKipcbiAqIFNldCB0aGUgY3VycmVudCBzZWxlY3RlZCBmZWF0dXJlXG4gKiBAbWVtYmVyb2YgdWlTdGF0ZVVwZGF0ZXJzXG4gKiBAcGFyYW0ge09iamVjdH0gc3RhdGUgYHVpU3RhdGVgXG4gKiBAcGFyYW0ge1tPYmplY3RdfSBmZWF0dXJlcyB0byBzdG9yZVxuICogQHJldHVybiB7T2JqZWN0fSBuZXh0U3RhdGVcbiAqL1xuZXhwb3J0IGNvbnN0IHNldFNlbGVjdGVkRmVhdHVyZVVwZGF0ZXIgPSAoc3RhdGUsIHtmZWF0dXJlfSkgPT4gKHtcbiAgLi4uc3RhdGUsXG4gIGVkaXRvcjoge1xuICAgIC4uLnN0YXRlLmVkaXRvcixcbiAgICBzZWxlY3RlZEZlYXR1cmU6IGZlYXR1cmVcbiAgfVxufSk7XG5cbi8qKlxuICogRGVsZXRlIGV4aXN0aW5nIGZlYXR1cmUgZnJvbSBmaWx0ZXJzXG4gKiBAbWVtYmVyb2YgdmlzU3RhdGVVcGRhdGVyc1xuICogQHBhcmFtIHtPYmplY3R9IHN0YXRlIGB2aXNTdGF0ZWBcbiAqIEBwYXJhbSB7c3RyaW5nfSBzZWxlY3RlZEZlYXR1cmVJZCBmZWF0dXJlIHRvIGRlbGV0ZVxuICogQHJldHVybiB7T2JqZWN0fSBuZXh0U3RhdGVcbiAqL1xuZXhwb3J0IGZ1bmN0aW9uIGRlbGV0ZUZlYXR1cmVVcGRhdGVyKHN0YXRlLCB7ZmVhdHVyZX0pIHtcbiAgaWYgKCFmZWF0dXJlKSB7XG4gICAgcmV0dXJuIHN0YXRlO1xuICB9XG5cbiAgY29uc3QgbmV3U3RhdGUgPSB7XG4gICAgLi4uc3RhdGUsXG4gICAgZWRpdG9yOiB7XG4gICAgICAuLi5zdGF0ZS5lZGl0b3IsXG4gICAgICBzZWxlY3RlZEZlYXR1cmU6IG51bGxcbiAgICB9XG4gIH07XG5cbiAgaWYgKGdldEZpbHRlcklkSW5GZWF0dXJlKGZlYXR1cmUpKSB7XG4gICAgY29uc3QgZmlsdGVySWR4ID0gbmV3U3RhdGUuZmlsdGVycy5maW5kSW5kZXgoXG4gICAgICBmID0+IGYuaWQgPT09IGdldEZpbHRlcklkSW5GZWF0dXJlKGZlYXR1cmUpXG4gICAgKTtcblxuICAgIHJldHVybiBmaWx0ZXJJZHggPiAtMVxuICAgICAgPyByZW1vdmVGaWx0ZXJVcGRhdGVyKG5ld1N0YXRlLCB7aWR4OiBmaWx0ZXJJZHh9KVxuICAgICAgOiBuZXdTdGF0ZTtcbiAgfVxuXG4gIC8vIG1vZGlmeSBlZGl0b3Igb2JqZWN0XG4gIGNvbnN0IG5ld0VkaXRvciA9IHtcbiAgICAuLi5zdGF0ZS5lZGl0b3IsXG4gICAgZmVhdHVyZXM6IHN0YXRlLmVkaXRvci5mZWF0dXJlcy5maWx0ZXIoZiA9PiBmLmlkICE9PSBmZWF0dXJlLmlkKSxcbiAgICBzZWxlY3RlZEZlYXR1cmU6IG51bGxcbiAgfTtcblxuICByZXR1cm4ge1xuICAgIC4uLnN0YXRlLFxuICAgIGVkaXRvcjogbmV3RWRpdG9yXG4gIH07XG59XG5cbi8qKlxuICogVG9nZ2xlIGZlYXR1cmUgYXMgbGF5ZXIgZmlsdGVyXG4gKiBAbWVtYmVyb2YgdmlzU3RhdGVVcGRhdGVyc1xuICogQHBhcmFtIHN0YXRlXG4gKiBAcGFyYW0ge09iamVjdH0gcGF5bG9hZFxuICogQHBhcmFtIHtzdHJpbmd9IHBheWxvYWQuZmVhdHVyZUlkXG4gKiBAcGFyYW0ge09iamVjdH0gcGF5bG9hZC5sYXllclxuICogQHJldHVybiB7T2JqZWN0fSBuZXh0U3RhdGVcbiAqL1xuZXhwb3J0IGZ1bmN0aW9uIHNldFBvbHlnb25GaWx0ZXJMYXllclVwZGF0ZXIoc3RhdGUsIHBheWxvYWQpIHtcbiAgY29uc3Qge2xheWVyLCBmZWF0dXJlLCBhdXRoLCBwcm9qZWN0LCBtYXBTdGF0ZX0gPSBwYXlsb2FkO1xuICBjb25zdCBmaWx0ZXJJZCA9IGdldEZpbHRlcklkSW5GZWF0dXJlKGZlYXR1cmUpO1xuXG4gIC8vIGxldCBuZXdGaWx0ZXIgPSBudWxsO1xuICBsZXQgZmlsdGVySWR4O1xuICBsZXQgbmV3TGF5ZXJJZCA9IFtsYXllci5pZF07XG4gIGxldCBuZXdTdGF0ZSA9IHN0YXRlO1xuICAvLyBJZiBwb2x5Z29uIGZpbHRlciBhbHJlYWR5IGV4aXN0cywgd2UgbmVlZCB0byBmaW5kIG91dCBpZiB0aGUgY3VycmVudCBsYXllciBpcyBhbHJlYWR5IGluY2x1ZGVkXG4gIGlmIChmaWx0ZXJJZCkge1xuICAgIGZpbHRlcklkeCA9IHN0YXRlLmZpbHRlcnMuZmluZEluZGV4KGYgPT4gZi5pZCA9PT0gZmlsdGVySWQpO1xuXG4gICAgaWYgKCFzdGF0ZS5maWx0ZXJzW2ZpbHRlcklkeF0pIHtcbiAgICAgIC8vIHdoYXQgaWYgZmlsdGVyIGRvZXNuJ3QgZXhpc3Q/Li4uIG5vdCBwb3NzaWJsZS5cbiAgICAgIC8vIGJlY2F1c2UgZmVhdHVyZXMgaW4gdGhlIGVkaXRvciBpcyBwYXNzZWQgaW4gZnJvbSBmaWx0ZXJzIGFuZCBlZGl0b3JzLlxuICAgICAgLy8gYnV0IHdlIHdpbGwgbW92ZSB0aGlzIGZlYXR1cmUgYmFjayB0byBlZGl0b3IganVzdCBpbiBjYXNlXG4gICAgICBjb25zdCBub25lRmlsdGVyRmVhdHVyZSA9IHtcbiAgICAgICAgLi4uZmVhdHVyZSxcbiAgICAgICAgcHJvcGVydGllczoge1xuICAgICAgICAgIC4uLmZlYXR1cmUucHJvcGVydGllcyxcbiAgICAgICAgICBmaWx0ZXJJZDogbnVsbFxuICAgICAgICB9XG4gICAgICB9O1xuXG4gICAgICByZXR1cm4ge1xuICAgICAgICAuLi5zdGF0ZSxcbiAgICAgICAgZWRpdG9yOiB7XG4gICAgICAgICAgLi4uc3RhdGUuZWRpdG9yLFxuICAgICAgICAgIGZlYXR1cmVzOiBbLi4uc3RhdGUuZWRpdG9yLmZlYXR1cmVzLCBub25lRmlsdGVyRmVhdHVyZV0sXG4gICAgICAgICAgc2VsZWN0ZWRGZWF0dXJlOiBub25lRmlsdGVyRmVhdHVyZVxuICAgICAgICB9XG4gICAgICB9O1xuICAgIH1cblxuICAgIGNvbnN0IHtsYXllcklkfSA9IHN0YXRlLmZpbHRlcnNbZmlsdGVySWR4XSB8fCBbXTtcbiAgICBjb25zdCBpc0xheWVySW5jbHVkZWQgPSBsYXllcklkLmluY2x1ZGVzKGxheWVyLmlkKTtcbiAgICBjb25zdCBmaWx0ZXIgPSBzdGF0ZS5maWx0ZXJzW2ZpbHRlcklkeF07XG5cbiAgICBuZXdMYXllcklkID0gaXNMYXllckluY2x1ZGVkXG4gICAgICA/IC8vIGlmIGxheWVyIGlzIGluY2x1ZGVkLCByZW1vdmUgaXRcbiAgICAgICAgZmlsdGVyLmxheWVySWQuZmlsdGVyKGwgPT4gbCAhPT0gbGF5ZXIuaWQpXG4gICAgICA6IFsuLi5maWx0ZXIubGF5ZXJJZCwgbGF5ZXIuaWRdO1xuICB9IGVsc2Uge1xuICAgIC8vIGlmIHdlIGhhdmVuJ3QgY3JlYXRlIHRoZSBwb2x5Z29uIGZpbHRlciwgY3JlYXRlIGl0XG4gICAgY29uc3QgbmV3RmlsdGVyID0gZ2VuZXJhdGVQb2x5Z29uRmlsdGVyKFtdLCBmZWF0dXJlKTtcbiAgICBmaWx0ZXJJZHggPSBzdGF0ZS5maWx0ZXJzLmxlbmd0aDtcblxuICAgIC8vIGFkZCBmZWF0dXJlLCByZW1vdmUgZmVhdHVyZSBmcm9tIGVpZHRvclxuICAgIG5ld1N0YXRlID0ge1xuICAgICAgLi4uc3RhdGUsXG4gICAgICBmaWx0ZXJzOiBbLi4uc3RhdGUuZmlsdGVycywgbmV3RmlsdGVyXSxcbiAgICAgIGVkaXRvcjoge1xuICAgICAgICAuLi5zdGF0ZS5lZGl0b3IsXG4gICAgICAgIGZlYXR1cmVzOiBzdGF0ZS5lZGl0b3IuZmVhdHVyZXMuZmlsdGVyKGYgPT4gZi5pZCAhPT0gZmVhdHVyZS5pZCksXG4gICAgICAgIHNlbGVjdGVkRmVhdHVyZTogbmV3RmlsdGVyLnZhbHVlXG4gICAgICB9XG4gICAgfTtcbiAgfVxuXG4gIHJldHVybiBzZXRGaWx0ZXJVcGRhdGVyKG5ld1N0YXRlLCB7XG4gICAgaWR4OiBmaWx0ZXJJZHgsXG4gICAgcHJvcDogJ2xheWVySWQnLFxuICAgIHZhbHVlOiBuZXdMYXllcklkLFxuICAgIGF1dGgsXG4gICAgcHJvamVjdCxcbiAgICBtYXBTdGF0ZVxuICB9KTtcbn1cblxuLyoqXG4gKiBVcGRhdGUgZWRpdG9yXG4gKiBAcGFyYW0ge09iamVjdH0gc3RhdGUgYHZpc1N0YXRlYFxuICogQHBhcmFtIHZpc2libGVcbiAqIEByZXR1cm4ge09iamVjdH0gbmV4dFN0YXRlXG4gKi9cbmV4cG9ydCBmdW5jdGlvbiB0b2dnbGVFZGl0b3JWaXNpYmlsaXR5KHN0YXRlLCB7dmlzaWJsZX0pIHtcbiAgcmV0dXJuIHtcbiAgICAuLi5zdGF0ZSxcbiAgICBlZGl0b3I6IHtcbiAgICAgIC4uLnN0YXRlLmVkaXRvcixcbiAgICAgIHZpc2libGU6ICFzdGF0ZS5lZGl0b3IudmlzaWJsZVxuICAgIH1cbiAgfTtcbn1cbiJdfQ==