'use strict';

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

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

var _index2 = _interopRequireDefault(_index);

var _imagebase = require('../imagebase.js');

var _imagebase2 = _interopRequireDefault(_imagebase);

var _imagestate = require('../imagestate.js');

var _imagestate2 = _interopRequireDefault(_imagestate);

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

var _reproj2 = _interopRequireDefault(_reproj);

var _triangulation = require('../reproj/triangulation.js');

var _triangulation2 = _interopRequireDefault(_triangulation);

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

/**
 * @classdesc
 * Class encapsulating single reprojected image.
 * See {@link ol.source.Image}.
 *
 * @constructor
 * @extends {ol.ImageBase}
 * @param {ol.proj.Projection} sourceProj Source projection (of the data).
 * @param {ol.proj.Projection} targetProj Target projection.
 * @param {ol.Extent} targetExtent Target extent.
 * @param {number} targetResolution Target resolution.
 * @param {number} pixelRatio Pixel ratio.
 * @param {ol.ReprojImageFunctionType} getImageFunction
 *     Function returning source images (extent, resolution, pixelRatio).
 */
var _ol_reproj_Image_ = function (sourceProj, targetProj, targetExtent, targetResolution, pixelRatio, getImageFunction) {

  /**
   * @private
   * @type {ol.proj.Projection}
   */
  this.targetProj_ = targetProj;

  /**
   * @private
   * @type {ol.Extent}
   */
  this.maxSourceExtent_ = sourceProj.getExtent();
  var maxTargetExtent = targetProj.getExtent();

  var limitedTargetExtent = maxTargetExtent ? _extent2.default.getIntersection(targetExtent, maxTargetExtent) : targetExtent;

  var targetCenter = _extent2.default.getCenter(limitedTargetExtent);
  var sourceResolution = _reproj2.default.calculateSourceResolution(sourceProj, targetProj, targetCenter, targetResolution);

  var errorThresholdInPixels = _index2.default.DEFAULT_RASTER_REPROJECTION_ERROR_THRESHOLD;

  /**
   * @private
   * @type {!ol.reproj.Triangulation}
   */
  this.triangulation_ = new _triangulation2.default(sourceProj, targetProj, limitedTargetExtent, this.maxSourceExtent_, sourceResolution * errorThresholdInPixels);

  /**
   * @private
   * @type {number}
   */
  this.targetResolution_ = targetResolution;

  /**
   * @private
   * @type {ol.Extent}
   */
  this.targetExtent_ = targetExtent;

  var sourceExtent = this.triangulation_.calculateSourceExtent();

  /**
   * @private
   * @type {ol.ImageBase}
   */
  this.sourceImage_ = getImageFunction(sourceExtent, sourceResolution, pixelRatio);

  /**
   * @private
   * @type {number}
   */
  this.sourcePixelRatio_ = this.sourceImage_ ? this.sourceImage_.getPixelRatio() : 1;

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

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

  var state = _imagestate2.default.LOADED;

  if (this.sourceImage_) {
    state = _imagestate2.default.IDLE;
  }

  _imagebase2.default.call(this, targetExtent, targetResolution, this.sourcePixelRatio_, state);
};

_index2.default.inherits(_ol_reproj_Image_, _imagebase2.default);

/**
 * @inheritDoc
 */
_ol_reproj_Image_.prototype.disposeInternal = function () {
  if (this.state == _imagestate2.default.LOADING) {
    this.unlistenSource_();
  }
  _imagebase2.default.prototype.disposeInternal.call(this);
};

/**
 * @inheritDoc
 */
_ol_reproj_Image_.prototype.getImage = function () {
  return this.canvas_;
};

/**
 * @return {ol.proj.Projection} Projection.
 */
_ol_reproj_Image_.prototype.getProjection = function () {
  return this.targetProj_;
};

/**
 * @private
 */
_ol_reproj_Image_.prototype.reproject_ = function () {
  var sourceState = this.sourceImage_.getState();
  if (sourceState == _imagestate2.default.LOADED) {
    var width = _extent2.default.getWidth(this.targetExtent_) / this.targetResolution_;
    var height = _extent2.default.getHeight(this.targetExtent_) / this.targetResolution_;

    this.canvas_ = _reproj2.default.render(width, height, this.sourcePixelRatio_, this.sourceImage_.getResolution(), this.maxSourceExtent_, this.targetResolution_, this.targetExtent_, this.triangulation_, [{
      extent: this.sourceImage_.getExtent(),
      image: this.sourceImage_.getImage()
    }], 0);
  }
  this.state = sourceState;
  this.changed();
};

/**
 * @inheritDoc
 */
_ol_reproj_Image_.prototype.load = function () {
  if (this.state == _imagestate2.default.IDLE) {
    this.state = _imagestate2.default.LOADING;
    this.changed();

    var sourceState = this.sourceImage_.getState();
    if (sourceState == _imagestate2.default.LOADED || sourceState == _imagestate2.default.ERROR) {
      this.reproject_();
    } else {
      this.sourceListenerKey_ = _events2.default.listen(this.sourceImage_, _eventtype2.default.CHANGE, function (e) {
        var sourceState = this.sourceImage_.getState();
        if (sourceState == _imagestate2.default.LOADED || sourceState == _imagestate2.default.ERROR) {
          this.unlistenSource_();
          this.reproject_();
        }
      }, this);
      this.sourceImage_.load();
    }
  }
};

/**
 * @private
 */
_ol_reproj_Image_.prototype.unlistenSource_ = function () {
  _events2.default.unlistenByKey( /** @type {!ol.EventsKey} */this.sourceListenerKey_);
  this.sourceListenerKey_ = null;
};
exports.default = _ol_reproj_Image_;
module.exports = exports['default'];