'use strict';

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

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

var _index2 = _interopRequireDefault(_index);

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

var _extent2 = _interopRequireDefault(_extent);

var _functions = require('../../functions.js');

var _functions2 = _interopRequireDefault(_functions);

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 _layer = require('../layer.js');

var _layer2 = _interopRequireDefault(_layer);

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

var _transform2 = _interopRequireDefault(_transform);

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

/**
 * @constructor
 * @abstract
 * @extends {ol.renderer.Layer}
 * @param {ol.layer.Layer} layer Layer.
 */
var _ol_renderer_canvas_Layer_ = function (layer) {

  _layer2.default.call(this, layer);

  /**
   * @protected
   * @type {number}
   */
  this.renderedResolution;

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

_index2.default.inherits(_ol_renderer_canvas_Layer_, _layer2.default);

/**
 * @param {CanvasRenderingContext2D} context Context.
 * @param {olx.FrameState} frameState Frame state.
 * @param {ol.Extent} extent Clip extent.
 * @protected
 */
_ol_renderer_canvas_Layer_.prototype.clip = function (context, frameState, extent) {
  var pixelRatio = frameState.pixelRatio;
  var width = frameState.size[0] * pixelRatio;
  var height = frameState.size[1] * pixelRatio;
  var rotation = frameState.viewState.rotation;
  var topLeft = _extent2.default.getTopLeft( /** @type {ol.Extent} */extent);
  var topRight = _extent2.default.getTopRight( /** @type {ol.Extent} */extent);
  var bottomRight = _extent2.default.getBottomRight( /** @type {ol.Extent} */extent);
  var bottomLeft = _extent2.default.getBottomLeft( /** @type {ol.Extent} */extent);

  _transform2.default.apply(frameState.coordinateToPixelTransform, topLeft);
  _transform2.default.apply(frameState.coordinateToPixelTransform, topRight);
  _transform2.default.apply(frameState.coordinateToPixelTransform, bottomRight);
  _transform2.default.apply(frameState.coordinateToPixelTransform, bottomLeft);

  context.save();
  _canvas2.default.rotateAtOffset(context, -rotation, width / 2, height / 2);
  context.beginPath();
  context.moveTo(topLeft[0] * pixelRatio, topLeft[1] * pixelRatio);
  context.lineTo(topRight[0] * pixelRatio, topRight[1] * pixelRatio);
  context.lineTo(bottomRight[0] * pixelRatio, bottomRight[1] * pixelRatio);
  context.lineTo(bottomLeft[0] * pixelRatio, bottomLeft[1] * pixelRatio);
  context.clip();
  _canvas2.default.rotateAtOffset(context, rotation, width / 2, height / 2);
};

/**
 * @param {ol.render.EventType} type Event type.
 * @param {CanvasRenderingContext2D} context Context.
 * @param {olx.FrameState} frameState Frame state.
 * @param {ol.Transform=} opt_transform Transform.
 * @private
 */
_ol_renderer_canvas_Layer_.prototype.dispatchComposeEvent_ = function (type, context, frameState, opt_transform) {
  var layer = this.getLayer();
  if (layer.hasListener(type)) {
    var width = frameState.size[0] * frameState.pixelRatio;
    var height = frameState.size[1] * frameState.pixelRatio;
    var rotation = frameState.viewState.rotation;
    _canvas2.default.rotateAtOffset(context, -rotation, width / 2, height / 2);
    var transform = opt_transform !== undefined ? opt_transform : this.getTransform(frameState, 0);
    var render = new _immediate2.default(context, frameState.pixelRatio, frameState.extent, transform, frameState.viewState.rotation);
    var composeEvent = new _event2.default(type, render, frameState, context, null);
    layer.dispatchEvent(composeEvent);
    _canvas2.default.rotateAtOffset(context, rotation, width / 2, height / 2);
  }
};

/**
 * @param {ol.Coordinate} coordinate Coordinate.
 * @param {olx.FrameState} frameState FrameState.
 * @param {function(this: S, ol.layer.Layer, (Uint8ClampedArray|Uint8Array)): T} callback Layer
 *     callback.
 * @param {S} thisArg Value to use as `this` when executing `callback`.
 * @return {T|undefined} Callback result.
 * @template S,T,U
 */
_ol_renderer_canvas_Layer_.prototype.forEachLayerAtCoordinate = function (coordinate, frameState, callback, thisArg) {
  var hasFeature = this.forEachFeatureAtCoordinate(coordinate, frameState, 0, _functions2.default.TRUE, this);

  if (hasFeature) {
    return callback.call(thisArg, this.getLayer(), null);
  } else {
    return undefined;
  }
};

/**
 * @param {CanvasRenderingContext2D} context Context.
 * @param {olx.FrameState} frameState Frame state.
 * @param {ol.LayerState} layerState Layer state.
 * @param {ol.Transform=} opt_transform Transform.
 * @protected
 */
_ol_renderer_canvas_Layer_.prototype.postCompose = function (context, frameState, layerState, opt_transform) {
  this.dispatchComposeEvent_(_eventtype2.default.POSTCOMPOSE, context, frameState, opt_transform);
};

/**
 * @param {CanvasRenderingContext2D} context Context.
 * @param {olx.FrameState} frameState Frame state.
 * @param {ol.Transform=} opt_transform Transform.
 * @protected
 */
_ol_renderer_canvas_Layer_.prototype.preCompose = function (context, frameState, opt_transform) {
  this.dispatchComposeEvent_(_eventtype2.default.PRECOMPOSE, context, frameState, opt_transform);
};

/**
 * @param {CanvasRenderingContext2D} context Context.
 * @param {olx.FrameState} frameState Frame state.
 * @param {ol.Transform=} opt_transform Transform.
 * @protected
 */
_ol_renderer_canvas_Layer_.prototype.dispatchRenderEvent = function (context, frameState, opt_transform) {
  this.dispatchComposeEvent_(_eventtype2.default.RENDER, context, frameState, opt_transform);
};

/**
 * @param {olx.FrameState} frameState Frame state.
 * @param {number} offsetX Offset on the x-axis in view coordinates.
 * @protected
 * @return {!ol.Transform} Transform.
 */
_ol_renderer_canvas_Layer_.prototype.getTransform = function (frameState, offsetX) {
  var viewState = frameState.viewState;
  var pixelRatio = frameState.pixelRatio;
  var dx1 = pixelRatio * frameState.size[0] / 2;
  var dy1 = pixelRatio * frameState.size[1] / 2;
  var sx = pixelRatio / viewState.resolution;
  var sy = -sx;
  var angle = -viewState.rotation;
  var dx2 = -viewState.center[0] + offsetX;
  var dy2 = -viewState.center[1];
  return _transform2.default.compose(this.transform_, dx1, dy1, sx, sy, angle, dx2, dy2);
};

/**
 * @abstract
 * @param {olx.FrameState} frameState Frame state.
 * @param {ol.LayerState} layerState Layer state.
 * @param {CanvasRenderingContext2D} context Context.
 */
_ol_renderer_canvas_Layer_.prototype.composeFrame = function (frameState, layerState, context) {};

/**
 * @abstract
 * @param {olx.FrameState} frameState Frame state.
 * @param {ol.LayerState} layerState Layer state.
 * @return {boolean} whether composeFrame should be called.
 */
_ol_renderer_canvas_Layer_.prototype.prepareFrame = function (frameState, layerState) {};
exports.default = _ol_renderer_canvas_Layer_;
module.exports = exports['default'];