'use strict';

Object.defineProperty(exports, "__esModule", {
  value: true
});

var _index = require('../index.js');

var _index2 = _interopRequireDefault(_index);

var _collection = require('../collection.js');

var _collection2 = _interopRequireDefault(_collection);

var _collectioneventtype = require('../collectioneventtype.js');

var _collectioneventtype2 = _interopRequireDefault(_collectioneventtype);

var _object = require('../object.js');

var _object2 = _interopRequireDefault(_object);

var _objecteventtype = require('../objecteventtype.js');

var _objecteventtype2 = _interopRequireDefault(_objecteventtype);

var _asserts = require('../asserts.js');

var _asserts2 = _interopRequireDefault(_asserts);

var _events = require('../events.js');

var _events2 = _interopRequireDefault(_events);

var _eventtype = require('../events/eventtype.js');

var _eventtype2 = _interopRequireDefault(_eventtype);

var _extent = require('../extent.js');

var _extent2 = _interopRequireDefault(_extent);

var _base = require('../layer/base.js');

var _base2 = _interopRequireDefault(_base);

var _obj = require('../obj.js');

var _obj2 = _interopRequireDefault(_obj);

var _state = require('../source/state.js');

var _state2 = _interopRequireDefault(_state);

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

/**
 * @classdesc
 * A {@link ol.Collection} of layers that are handled together.
 *
 * A generic `change` event is triggered when the group/Collection changes.
 *
 * @constructor
 * @extends {ol.layer.Base}
 * @param {olx.layer.GroupOptions=} opt_options Layer options.
 * @api
 */
var _ol_layer_Group_ = function (opt_options) {

  var options = opt_options || {};
  var baseOptions = /** @type {olx.layer.GroupOptions} */
  _obj2.default.assign({}, options);
  delete baseOptions.layers;

  var layers = options.layers;

  _base2.default.call(this, baseOptions);

  /**
   * @private
   * @type {Array.<ol.EventsKey>}
   */
  this.layersListenerKeys_ = [];

  /**
   * @private
   * @type {Object.<string, Array.<ol.EventsKey>>}
   */
  this.listenerKeys_ = {};

  _events2.default.listen(this, _object2.default.getChangeEventType(_ol_layer_Group_.Property_.LAYERS), this.handleLayersChanged_, this);

  if (layers) {
    if (Array.isArray(layers)) {
      layers = new _collection2.default(layers.slice(), { unique: true });
    } else {
      _asserts2.default.assert(layers instanceof _collection2.default, 43); // Expected `layers` to be an array or an `ol.Collection`
      layers = layers;
    }
  } else {
    layers = new _collection2.default(undefined, { unique: true });
  }

  this.setLayers(layers);
};

_index2.default.inherits(_ol_layer_Group_, _base2.default);

/**
 * @private
 */
_ol_layer_Group_.prototype.handleLayerChange_ = function () {
  this.changed();
};

/**
 * @param {ol.events.Event} event Event.
 * @private
 */
_ol_layer_Group_.prototype.handleLayersChanged_ = function (event) {
  this.layersListenerKeys_.forEach(_events2.default.unlistenByKey);
  this.layersListenerKeys_.length = 0;

  var layers = this.getLayers();
  this.layersListenerKeys_.push(_events2.default.listen(layers, _collectioneventtype2.default.ADD, this.handleLayersAdd_, this), _events2.default.listen(layers, _collectioneventtype2.default.REMOVE, this.handleLayersRemove_, this));

  for (var id in this.listenerKeys_) {
    this.listenerKeys_[id].forEach(_events2.default.unlistenByKey);
  }
  _obj2.default.clear(this.listenerKeys_);

  var layersArray = layers.getArray();
  var i, ii, layer;
  for (i = 0, ii = layersArray.length; i < ii; i++) {
    layer = layersArray[i];
    this.listenerKeys_[_index2.default.getUid(layer).toString()] = [_events2.default.listen(layer, _objecteventtype2.default.PROPERTYCHANGE, this.handleLayerChange_, this), _events2.default.listen(layer, _eventtype2.default.CHANGE, this.handleLayerChange_, this)];
  }

  this.changed();
};

/**
 * @param {ol.Collection.Event} collectionEvent Collection event.
 * @private
 */
_ol_layer_Group_.prototype.handleLayersAdd_ = function (collectionEvent) {
  var layer = /** @type {ol.layer.Base} */collectionEvent.element;
  var key = _index2.default.getUid(layer).toString();
  this.listenerKeys_[key] = [_events2.default.listen(layer, _objecteventtype2.default.PROPERTYCHANGE, this.handleLayerChange_, this), _events2.default.listen(layer, _eventtype2.default.CHANGE, this.handleLayerChange_, this)];
  this.changed();
};

/**
 * @param {ol.Collection.Event} collectionEvent Collection event.
 * @private
 */
_ol_layer_Group_.prototype.handleLayersRemove_ = function (collectionEvent) {
  var layer = /** @type {ol.layer.Base} */collectionEvent.element;
  var key = _index2.default.getUid(layer).toString();
  this.listenerKeys_[key].forEach(_events2.default.unlistenByKey);
  delete this.listenerKeys_[key];
  this.changed();
};

/**
 * Returns the {@link ol.Collection collection} of {@link ol.layer.Layer layers}
 * in this group.
 * @return {!ol.Collection.<ol.layer.Base>} Collection of
 *   {@link ol.layer.Base layers} that are part of this group.
 * @observable
 * @api
 */
_ol_layer_Group_.prototype.getLayers = function () {
  return (
    /** @type {!ol.Collection.<ol.layer.Base>} */this.get(_ol_layer_Group_.Property_.LAYERS)
  );
};

/**
 * Set the {@link ol.Collection collection} of {@link ol.layer.Layer layers}
 * in this group.
 * @param {!ol.Collection.<ol.layer.Base>} layers Collection of
 *   {@link ol.layer.Base layers} that are part of this group.
 * @observable
 * @api
 */
_ol_layer_Group_.prototype.setLayers = function (layers) {
  this.set(_ol_layer_Group_.Property_.LAYERS, layers);
};

/**
 * @inheritDoc
 */
_ol_layer_Group_.prototype.getLayersArray = function (opt_array) {
  var array = opt_array !== undefined ? opt_array : [];
  this.getLayers().forEach(function (layer) {
    layer.getLayersArray(array);
  });
  return array;
};

/**
 * @inheritDoc
 */
_ol_layer_Group_.prototype.getLayerStatesArray = function (opt_states) {
  var states = opt_states !== undefined ? opt_states : [];

  var pos = states.length;

  this.getLayers().forEach(function (layer) {
    layer.getLayerStatesArray(states);
  });

  var ownLayerState = this.getLayerState();
  var i, ii, layerState;
  for (i = pos, ii = states.length; i < ii; i++) {
    layerState = states[i];
    layerState.opacity *= ownLayerState.opacity;
    layerState.visible = layerState.visible && ownLayerState.visible;
    layerState.maxResolution = Math.min(layerState.maxResolution, ownLayerState.maxResolution);
    layerState.minResolution = Math.max(layerState.minResolution, ownLayerState.minResolution);
    if (ownLayerState.extent !== undefined) {
      if (layerState.extent !== undefined) {
        layerState.extent = _extent2.default.getIntersection(layerState.extent, ownLayerState.extent);
      } else {
        layerState.extent = ownLayerState.extent;
      }
    }
  }

  return states;
};

/**
 * @inheritDoc
 */
_ol_layer_Group_.prototype.getSourceState = function () {
  return _state2.default.READY;
};

/**
 * @enum {string}
 * @private
 */
_ol_layer_Group_.Property_ = {
  LAYERS: 'layers'
};
exports.default = _ol_layer_Group_;
module.exports = exports['default'];