'use strict';

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

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

var _events2 = _interopRequireDefault(_events);

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

var _eventtype2 = _interopRequireDefault(_eventtype);

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

var _index2 = _interopRequireDefault(_index);

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

var _object2 = _interopRequireDefault(_object);

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

var _base2 = _interopRequireDefault(_base);

var _property = require('../layer/property.js');

var _property2 = _interopRequireDefault(_property);

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

var _obj2 = _interopRequireDefault(_obj);

var _eventtype3 = require('../render/eventtype.js');

var _eventtype4 = _interopRequireDefault(_eventtype3);

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

var _state2 = _interopRequireDefault(_state);

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

/**
 * @classdesc
 * Abstract base class; normally only used for creating subclasses and not
 * instantiated in apps.
 * A visual representation of raster or vector map data.
 * Layers group together those properties that pertain to how the data is to be
 * displayed, irrespective of the source of that data.
 *
 * Layers are usually added to a map with {@link ol.Map#addLayer}. Components
 * like {@link ol.interaction.Select} use unmanaged layers internally. These
 * unmanaged layers are associated with the map using
 * {@link ol.layer.Layer#setMap} instead.
 *
 * A generic `change` event is fired when the state of the source changes.
 *
 * @constructor
 * @abstract
 * @extends {ol.layer.Base}
 * @fires ol.render.Event
 * @param {olx.layer.LayerOptions} options Layer options.
 * @api
 */
var _ol_layer_Layer_ = function (options) {

  var baseOptions = _obj2.default.assign({}, options);
  delete baseOptions.source;

  _base2.default.call(this, /** @type {olx.layer.BaseOptions} */baseOptions);

  /**
   * @private
   * @type {?ol.EventsKey}
   */
  this.mapPrecomposeKey_ = null;

  /**
   * @private
   * @type {?ol.EventsKey}
   */
  this.mapRenderKey_ = null;

  /**
   * @private
   * @type {?ol.EventsKey}
   */
  this.sourceChangeKey_ = null;

  if (options.map) {
    this.setMap(options.map);
  }

  _events2.default.listen(this, _object2.default.getChangeEventType(_property2.default.SOURCE), this.handleSourcePropertyChange_, this);

  var source = options.source ? options.source : null;
  this.setSource(source);
};

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

/**
 * Return `true` if the layer is visible, and if the passed resolution is
 * between the layer's minResolution and maxResolution. The comparison is
 * inclusive for `minResolution` and exclusive for `maxResolution`.
 * @param {ol.LayerState} layerState Layer state.
 * @param {number} resolution Resolution.
 * @return {boolean} The layer is visible at the given resolution.
 */
_ol_layer_Layer_.visibleAtResolution = function (layerState, resolution) {
  return layerState.visible && resolution >= layerState.minResolution && resolution < layerState.maxResolution;
};

/**
 * @inheritDoc
 */
_ol_layer_Layer_.prototype.getLayersArray = function (opt_array) {
  var array = opt_array ? opt_array : [];
  array.push(this);
  return array;
};

/**
 * @inheritDoc
 */
_ol_layer_Layer_.prototype.getLayerStatesArray = function (opt_states) {
  var states = opt_states ? opt_states : [];
  states.push(this.getLayerState());
  return states;
};

/**
 * Get the layer source.
 * @return {ol.source.Source} The layer source (or `null` if not yet set).
 * @observable
 * @api
 */
_ol_layer_Layer_.prototype.getSource = function () {
  var source = this.get(_property2.default.SOURCE);
  return (/** @type {ol.source.Source} */source || null
  );
};

/**
  * @inheritDoc
  */
_ol_layer_Layer_.prototype.getSourceState = function () {
  var source = this.getSource();
  return !source ? _state2.default.UNDEFINED : source.getState();
};

/**
 * @private
 */
_ol_layer_Layer_.prototype.handleSourceChange_ = function () {
  this.changed();
};

/**
 * @private
 */
_ol_layer_Layer_.prototype.handleSourcePropertyChange_ = function () {
  if (this.sourceChangeKey_) {
    _events2.default.unlistenByKey(this.sourceChangeKey_);
    this.sourceChangeKey_ = null;
  }
  var source = this.getSource();
  if (source) {
    this.sourceChangeKey_ = _events2.default.listen(source, _eventtype2.default.CHANGE, this.handleSourceChange_, this);
  }
  this.changed();
};

/**
 * Sets the layer to be rendered on top of other layers on a map. The map will
 * not manage this layer in its layers collection, and the callback in
 * {@link ol.Map#forEachLayerAtPixel} will receive `null` as layer. This
 * is useful for temporary layers. To remove an unmanaged layer from the map,
 * use `#setMap(null)`.
 *
 * To add the layer to a map and have it managed by the map, use
 * {@link ol.Map#addLayer} instead.
 * @param {ol.PluggableMap} map Map.
 * @api
 */
_ol_layer_Layer_.prototype.setMap = function (map) {
  if (this.mapPrecomposeKey_) {
    _events2.default.unlistenByKey(this.mapPrecomposeKey_);
    this.mapPrecomposeKey_ = null;
  }
  if (!map) {
    this.changed();
  }
  if (this.mapRenderKey_) {
    _events2.default.unlistenByKey(this.mapRenderKey_);
    this.mapRenderKey_ = null;
  }
  if (map) {
    this.mapPrecomposeKey_ = _events2.default.listen(map, _eventtype4.default.PRECOMPOSE, function (evt) {
      var layerState = this.getLayerState();
      layerState.managed = false;
      layerState.zIndex = Infinity;
      evt.frameState.layerStatesArray.push(layerState);
      evt.frameState.layerStates[_index2.default.getUid(this)] = layerState;
    }, this);
    this.mapRenderKey_ = _events2.default.listen(this, _eventtype2.default.CHANGE, map.render, map);
    this.changed();
  }
};

/**
 * Set the layer source.
 * @param {ol.source.Source} source The layer source.
 * @observable
 * @api
 */
_ol_layer_Layer_.prototype.setSource = function (source) {
  this.set(_property2.default.SOURCE, source);
};
exports.default = _ol_layer_Layer_;
module.exports = exports['default'];