function _inheritsLoose(subClass, superClass) { subClass.prototype = Object.create(superClass.prototype); subClass.prototype.constructor = subClass; _setPrototypeOf(subClass, superClass); }

function _setPrototypeOf(o, p) { _setPrototypeOf = Object.setPrototypeOf || function _setPrototypeOf(o, p) { o.__proto__ = p; return o; }; return _setPrototypeOf(o, p); }

/**
 * @fileOverview heatmap
 * @author leungwensen@gmail.com
 */
var _require = require('@antv/attr/lib'),
    ColorUtil = _require.ColorUtil; // TODO: ColorUtil 独立成包，从 attr 包中抽离


var GeomBase = require('./base');

var Util = require('../util');

var ORIGIN_FIELD = '_origin';
var SHADOW_CANVAS = 'shadowCanvas';
var VALUE_RANGE = 'valueRange';
var IMAGE_SHAPE = 'imageShape';
var MAPPED_DATA = 'mappedData';
var GRAY_SCALE_BLURRED_CANVAS = 'grayScaleBlurredCanvas';
var HEATMAP_SIZE = 'heatmapSize';

var Heatmap = /*#__PURE__*/function (_GeomBase) {
  _inheritsLoose(Heatmap, _GeomBase);

  function Heatmap() {
    return _GeomBase.apply(this, arguments) || this;
  }

  var _proto = Heatmap.prototype;

  /**
   * get default configuration
   * @protected
   * @return {Object} configuration
   */
  _proto.getDefaultCfg = function getDefaultCfg() {
    var cfg = _GeomBase.prototype.getDefaultCfg.call(this);

    cfg.type = 'heatmap';
    cfg.paletteCache = {}; // cfg.shapeType = 'heatmap';

    return cfg;
  };

  _proto._prepareRange = function _prepareRange() {
    var self = this;
    var data = self.get(MAPPED_DATA);
    var colorAttr = self.getAttr('color');
    var colorField = colorAttr.field;
    var min = Infinity;
    var max = -Infinity;
    data.forEach(function (row) {
      var value = row[ORIGIN_FIELD][colorField];

      if (value > max) {
        max = value;
      }

      if (value < min) {
        min = value;
      }
    });

    if (min === max) {
      min = max - 1;
    }

    var range = [min, max];
    self.set(VALUE_RANGE, range);
  };

  _proto._prepareSize = function _prepareSize() {
    var self = this;
    var radius = self.getDefaultValue('size');

    if (!Util.isNumber(radius)) {
      radius = self._getDefaultSize();
    }

    var styleOptions = self.get('styleOptions');
    var blur = styleOptions && Util.isObject(styleOptions.style) ? styleOptions.style.blur : null;

    if (!Util.isFinite(blur) || blur === null) {
      blur = radius / 2;
    }

    self.set(HEATMAP_SIZE, {
      blur: blur,
      radius: radius
    });
  };

  _proto._getDefaultSize = function _getDefaultSize() {
    var self = this;
    var position = self.getAttr('position');
    var coord = self.get('coord');
    var radius = Math.min(coord.width / (position.scales[0].ticks.length * 4), coord.height / (position.scales[1].ticks.length * 4));
    return radius;
  };

  _proto._colorize = function _colorize(img) {
    var self = this;
    var colorAttr = self.getAttr('color');
    var pixels = img.data;
    var paletteCache = self.get('paletteCache');

    for (var i = 3; i < pixels.length; i += 4) {
      var alpha = pixels[i]; // get gradient color from opacity value

      if (alpha) {
        var palette = void 0;

        if (paletteCache[alpha]) {
          palette = paletteCache[alpha];
        } else {
          palette = ColorUtil.rgb2arr(colorAttr.gradient(alpha / 256));
          paletteCache[alpha] = palette;
        } // const palette = colorUtil.rgb2arr(colorAttr.gradient(alpha / 256));


        pixels[i - 3] = palette[0];
        pixels[i - 2] = palette[1];
        pixels[i - 1] = palette[2];
        pixels[i] = alpha;
      }
    }
  };

  _proto._prepareGreyScaleBlurredCircle = function _prepareGreyScaleBlurredCircle(r, blur) {
    var self = this;
    var circleCanvas = self.get(GRAY_SCALE_BLURRED_CANVAS);

    if (!circleCanvas) {
      circleCanvas = document.createElement('canvas');
      self.set(GRAY_SCALE_BLURRED_CANVAS, circleCanvas);
    }

    var r2 = r + blur;
    var ctx = circleCanvas.getContext('2d');
    circleCanvas.width = circleCanvas.height = r2 * 2;
    ctx.clearRect(0, 0, circleCanvas.width, circleCanvas.height); // ctx.shadowOffsetX = ctx.shadowOffsetY = r2 * 2;

    ctx.shadowOffsetX = ctx.shadowOffsetY = r2 * 2;
    ctx.shadowBlur = blur;
    ctx.shadowColor = 'black';
    ctx.beginPath();
    ctx.arc(-r2, -r2, r, 0, Math.PI * 2, true);
    ctx.closePath();
    ctx.fill();
  };

  _proto._drawGrayScaleBlurredCircle = function _drawGrayScaleBlurredCircle(x, y, r, alpha, ctx) {
    var self = this;
    var circleCanvas = self.get(GRAY_SCALE_BLURRED_CANVAS);
    ctx.globalAlpha = alpha;
    ctx.drawImage(circleCanvas, x - r, y - r);
  };

  _proto._getShadowCanvasCtx = function _getShadowCanvasCtx() {
    var self = this;
    var canvas = self.get(SHADOW_CANVAS);

    if (!canvas) {
      canvas = document.createElement('canvas');
      self.set(SHADOW_CANVAS, canvas);
    }

    var coord = self.get('coord');

    if (coord) {
      canvas.width = coord.width;
      canvas.height = coord.height;
    }

    return canvas.getContext('2d');
  };

  _proto._clearShadowCanvasCtx = function _clearShadowCanvasCtx() {
    var ctx = this._getShadowCanvasCtx();

    ctx.clearRect(0, 0, ctx.canvas.width, ctx.canvas.height);
  };

  _proto._getImageShape = function _getImageShape() {
    var self = this;
    var imageShape = self.get(IMAGE_SHAPE);

    if (imageShape) {
      return imageShape;
    }

    var container = self.get('container');
    imageShape = container.addShape('Image', {});
    self.set(IMAGE_SHAPE, imageShape);
    return imageShape;
  };

  _proto.clear = function clear() {
    // @2019-02-28 by blue.lb 由于设置了SHADOW_CANVAS作为像素缓存canvas，每次销毁chart时，也需要清除该缓冲区
    this._clearShadowCanvasCtx();

    _GeomBase.prototype.clear.call(this);
  };

  _proto.drawWithRange = function drawWithRange(range) {
    var self = this; // canvas size

    var _self$get = self.get('coord'),
        start = _self$get.start,
        end = _self$get.end,
        width = _self$get.width,
        height = _self$get.height; // value, range, etc


    var valueField = self.getAttr('color').field;
    var size = self.get(HEATMAP_SIZE); // prepare shadow canvas context

    self._clearShadowCanvasCtx();

    var ctx = self._getShadowCanvasCtx(); // filter data


    var data = self.get(MAPPED_DATA);

    if (range) {
      data = data.filter(function (row) {
        return row[ORIGIN_FIELD][valueField] <= range[1] && row[ORIGIN_FIELD][valueField] >= range[0];
      });
    } // step1. draw points with shadow


    var scale = self._getScale(valueField);

    for (var i = 0; i < data.length; i++) {
      var obj = data[i];
      var cfg = self.getDrawCfg(obj);
      var alpha = scale.scale(obj[ORIGIN_FIELD][valueField]);

      self._drawGrayScaleBlurredCircle(cfg.x - start.x, cfg.y - end.y, size.radius + size.blur, alpha, ctx);
    } // step2. convert pixels


    var colored = ctx.getImageData(0, 0, width, height);

    self._clearShadowCanvasCtx();

    self._colorize(colored);

    ctx.putImageData(colored, 0, 0);

    var imageShape = self._getImageShape();

    imageShape.attr('x', start.x);
    imageShape.attr('y', end.y);
    imageShape.attr('width', width);
    imageShape.attr('height', height);
    imageShape.attr('img', ctx.canvas);
  };

  _proto.draw = function draw(data
  /* , container, shapeFactory, index */
  ) {
    var self = this;
    self.set(MAPPED_DATA, data);

    self._prepareRange();

    self._prepareSize();

    var size = self.get(HEATMAP_SIZE);

    self._prepareGreyScaleBlurredCircle(size.radius, size.blur);

    var range = self.get(VALUE_RANGE);
    self.drawWithRange(range); // super.draw(data, container, shapeFactory, index);
  };

  return Heatmap;
}(GeomBase);

GeomBase.Heatmap = Heatmap;
module.exports = Heatmap;