'use strict';

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

var _transform = require('../../transform.js');

var _transform2 = _interopRequireDefault(_transform);

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

var _index2 = _interopRequireDefault(_index);

var _array = require('../../array.js');

var _array2 = _interopRequireDefault(_array);

var _css = require('../../css.js');

var _css2 = _interopRequireDefault(_css);

var _dom = require('../../dom.js');

var _dom2 = _interopRequireDefault(_dom);

var _layer = require('../../layer/layer.js');

var _layer2 = _interopRequireDefault(_layer);

var _event = require('../../render/event.js');

var _event2 = _interopRequireDefault(_event);

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

var _eventtype2 = _interopRequireDefault(_eventtype);

var _canvas = require('../../render/canvas.js');

var _canvas2 = _interopRequireDefault(_canvas);

var _immediate = require('../../render/canvas/immediate.js');

var _immediate2 = _interopRequireDefault(_immediate);

var _map = require('../map.js');

var _map2 = _interopRequireDefault(_map);

var _type = require('../type.js');

var _type2 = _interopRequireDefault(_type);

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

var _state2 = _interopRequireDefault(_state);

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

/**
 * @constructor
 * @extends {ol.renderer.Map}
 * @param {Element} container Container.
 * @param {ol.PluggableMap} map Map.
 * @api
 */
var _ol_renderer_canvas_Map_ = function (container, map) {

  _map2.default.call(this, container, map);

  /**
   * @private
   * @type {CanvasRenderingContext2D}
   */
  this.context_ = _dom2.default.createCanvasContext2D();

  /**
   * @private
   * @type {HTMLCanvasElement}
   */
  this.canvas_ = this.context_.canvas;

  this.canvas_.style.width = '100%';
  this.canvas_.style.height = '100%';
  this.canvas_.style.display = 'block';
  this.canvas_.className = _css2.default.CLASS_UNSELECTABLE;
  container.insertBefore(this.canvas_, container.childNodes[0] || null);

  /**
   * @private
   * @type {boolean}
   */
  this.renderedVisible_ = true;

  /**
   * @private
   * @type {ol.Transform}
   */
  this.transform_ = _transform2.default.create();
}; // FIXME offset panning

_index2.default.inherits(_ol_renderer_canvas_Map_, _map2.default);

/**
 * Determine if this renderer handles the provided layer.
 * @param {ol.renderer.Type} type The renderer type.
 * @return {boolean} The renderer can render the layer.
 */
_ol_renderer_canvas_Map_['handles'] = function (type) {
  return type === _type2.default.CANVAS;
};

/**
 * Create the map renderer.
 * @param {Element} container Container.
 * @param {ol.PluggableMap} map Map.
 * @return {ol.renderer.canvas.Map} The map renderer.
 */
_ol_renderer_canvas_Map_['create'] = function (container, map) {
  return new _ol_renderer_canvas_Map_(container, map);
};

/**
 * @param {ol.render.EventType} type Event type.
 * @param {olx.FrameState} frameState Frame state.
 * @private
 */
_ol_renderer_canvas_Map_.prototype.dispatchComposeEvent_ = function (type, frameState) {
  var map = this.getMap();
  var context = this.context_;
  if (map.hasListener(type)) {
    var extent = frameState.extent;
    var pixelRatio = frameState.pixelRatio;
    var viewState = frameState.viewState;
    var rotation = viewState.rotation;

    var transform = this.getTransform(frameState);

    var vectorContext = new _immediate2.default(context, pixelRatio, extent, transform, rotation);
    var composeEvent = new _event2.default(type, vectorContext, frameState, context, null);
    map.dispatchEvent(composeEvent);
  }
};

/**
 * @param {olx.FrameState} frameState Frame state.
 * @protected
 * @return {!ol.Transform} Transform.
 */
_ol_renderer_canvas_Map_.prototype.getTransform = function (frameState) {
  var viewState = frameState.viewState;
  var dx1 = this.canvas_.width / 2;
  var dy1 = this.canvas_.height / 2;
  var sx = frameState.pixelRatio / viewState.resolution;
  var sy = -sx;
  var angle = -viewState.rotation;
  var dx2 = -viewState.center[0];
  var dy2 = -viewState.center[1];
  return _transform2.default.compose(this.transform_, dx1, dy1, sx, sy, angle, dx2, dy2);
};

/**
 * @inheritDoc
 */
_ol_renderer_canvas_Map_.prototype.getType = function () {
  return _type2.default.CANVAS;
};

/**
 * @inheritDoc
 */
_ol_renderer_canvas_Map_.prototype.renderFrame = function (frameState) {

  if (!frameState) {
    if (this.renderedVisible_) {
      this.canvas_.style.display = 'none';
      this.renderedVisible_ = false;
    }
    return;
  }

  var context = this.context_;
  var pixelRatio = frameState.pixelRatio;
  var width = Math.round(frameState.size[0] * pixelRatio);
  var height = Math.round(frameState.size[1] * pixelRatio);
  if (this.canvas_.width != width || this.canvas_.height != height) {
    this.canvas_.width = width;
    this.canvas_.height = height;
  } else {
    context.clearRect(0, 0, width, height);
  }

  var rotation = frameState.viewState.rotation;

  this.calculateMatrices2D(frameState);

  this.dispatchComposeEvent_(_eventtype2.default.PRECOMPOSE, frameState);

  var layerStatesArray = frameState.layerStatesArray;
  _array2.default.stableSort(layerStatesArray, _map2.default.sortByZIndex);

  if (rotation) {
    context.save();
    _canvas2.default.rotateAtOffset(context, rotation, width / 2, height / 2);
  }

  var viewResolution = frameState.viewState.resolution;
  var i, ii, layer, layerRenderer, layerState;
  for (i = 0, ii = layerStatesArray.length; i < ii; ++i) {
    layerState = layerStatesArray[i];
    layer = layerState.layer;
    layerRenderer = /** @type {ol.renderer.canvas.Layer} */this.getLayerRenderer(layer);
    if (!_layer2.default.visibleAtResolution(layerState, viewResolution) || layerState.sourceState != _state2.default.READY) {
      continue;
    }
    if (layerRenderer.prepareFrame(frameState, layerState)) {
      layerRenderer.composeFrame(frameState, layerState, context);
    }
  }

  if (rotation) {
    context.restore();
  }

  this.dispatchComposeEvent_(_eventtype2.default.POSTCOMPOSE, frameState);

  if (!this.renderedVisible_) {
    this.canvas_.style.display = '';
    this.renderedVisible_ = true;
  }

  this.scheduleRemoveUnusedLayerRenderers(frameState);
  this.scheduleExpireIconCache(frameState);
};

/**
 * @inheritDoc
 */
_ol_renderer_canvas_Map_.prototype.forEachLayerAtPixel = function (pixel, frameState, callback, thisArg, layerFilter, thisArg2) {
  var result;
  var viewState = frameState.viewState;
  var viewResolution = viewState.resolution;

  var layerStates = frameState.layerStatesArray;
  var numLayers = layerStates.length;

  var coordinate = _transform2.default.apply(frameState.pixelToCoordinateTransform, pixel.slice());

  var i;
  for (i = numLayers - 1; i >= 0; --i) {
    var layerState = layerStates[i];
    var layer = layerState.layer;
    if (_layer2.default.visibleAtResolution(layerState, viewResolution) && layerFilter.call(thisArg2, layer)) {
      var layerRenderer = /** @type {ol.renderer.canvas.Layer} */this.getLayerRenderer(layer);
      result = layerRenderer.forEachLayerAtCoordinate(coordinate, frameState, callback, thisArg);
      if (result) {
        return result;
      }
    }
  }
  return undefined;
};
exports.default = _ol_renderer_canvas_Map_;
module.exports = exports['default'];