function _assertThisInitialized(self) { if (self === void 0) { throw new ReferenceError("this hasn't been initialised - super() hasn't been called"); } return self; }

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); }

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

var Interaction = require('./base'); // const G2 = require('../core.js');


var BRUSH_TYPES = ['X', 'Y', 'XY', 'POLYGON'];
var DEFAULT_TYPE = 'XY';

var Brush = /*#__PURE__*/function (_Interaction) {
  _inheritsLoose(Brush, _Interaction);

  var _proto = Brush.prototype;

  _proto.getDefaultCfg = function getDefaultCfg() {
    var cfg = _Interaction.prototype.getDefaultCfg.call(this);

    return Util.mix({}, cfg, {
      type: DEFAULT_TYPE,
      startPoint: null,
      brushing: false,
      dragging: false,
      brushShape: null,
      container: null,
      polygonPath: null,
      style: {
        fill: '#C5D4EB',
        opacity: 0.3,
        lineWidth: 1,
        stroke: '#82A6DD'
      },
      draggable: false,
      dragOffX: 0,
      dragOffY: 0,
      inPlot: true,
      xField: null,
      yField: null
    });
  };

  function Brush(cfg, view) {
    var _this;

    _this = _Interaction.call(this, cfg, view) || this;

    var me = _assertThisInitialized(_this);

    me.filter = !me.draggable;
    me.type = me.type.toUpperCase();
    me.chart = view;

    if (!BRUSH_TYPES.includes(me.type)) {
      me.type = DEFAULT_TYPE;
    }

    var canvas = me.canvas;

    if (canvas) {
      var plotRange;
      canvas.get('children').map(function (child) {
        if (child.get('type') === 'plotBack') {
          plotRange = child.get('plotRange');
          return false;
        }

        return child;
      });
      me.plot = {
        start: plotRange.bl,
        end: plotRange.tr
      };
    }

    if (view) {
      var coord = view.get('coord');
      me.plot = {
        start: coord.start,
        end: coord.end
      };
      view.on('afterrender', function () {
        me.plot = {
          start: coord.start,
          end: coord.end
        };
      });
      me.isTransposed = coord.isTransposed;

      var xScales = view._getScales('x');

      var yScales = view._getScales('y');

      me.xScale = me.xField ? xScales[me.xField] : view.getXScale();
      me.yScale = me.yField ? yScales[me.yField] : view.getYScales()[0];
    }

    return _this;
  } // onBurshstart() { }
  // onBrushmove() { }
  // onBrushend() {}
  // onDragstart() {}
  // onDragmove() {}
  // onDragend() {}


  _proto.start = function start(ev) {
    var me = this;
    var canvas = me.canvas,
        type = me.type,
        brushShape = me.brushShape;
    if (!type) return;

    if (me.brushing) {
      // 鼠标移动到图表外up, 回到图表内点击即结束绘制，mousedown的时候却正在绘制中
      me.end(ev);
    }

    var startPoint = {
      x: ev.offsetX,
      y: ev.offsetY
    };
    if (!startPoint.x) return;
    var isInPlot = me.plot && me.inPlot;
    var canvasDOM = canvas.get('canvasDOM');
    var pixelRatio = canvas.get('pixelRatio');
    if (me.selection) me.selection = null;

    if (me.draggable && brushShape && !brushShape.get('destroyed')) {
      // allow drag the brushShape
      if (brushShape.isHit(startPoint.x * pixelRatio, startPoint.y * pixelRatio)) {
        canvasDOM.style.cursor = 'move';
        me.selection = brushShape;
        me.dragging = true;

        if (type === 'X') {
          me.dragoffX = startPoint.x - brushShape.attr('x');
          me.dragoffY = 0;
        } else if (type === 'Y') {
          me.dragoffX = 0;
          me.dragoffY = startPoint.y - brushShape.attr('y');
        } else if (type === 'XY') {
          me.dragoffX = startPoint.x - brushShape.attr('x');
          me.dragoffY = startPoint.y - brushShape.attr('y');
        } else if (type === 'POLYGON') {
          var box = brushShape.getBBox();
          me.dragoffX = startPoint.x - box.minX;
          me.dragoffY = startPoint.y - box.minY;
        }

        if (isInPlot) {// me.selection.attr('clip', canvas.addShape('rect', {
          //   attrs: {
          //     x: this.plot.start.x,
          //     y: this.plot.end.y,
          //     width: this.plot.end.x - this.plot.start.x,
          //     height: this.plot.start.y - this.plot.end.y,
          //     fill: '#fff',
          //     fillOpacity: 0
          //   }
          // }));
        }

        me.onDragstart && me.onDragstart(ev);
      }

      me.prePoint = startPoint;
    }

    if (!me.dragging) {
      // brush start
      me.onBrushstart && me.onBrushstart(startPoint);
      var container = me.container;

      if (isInPlot) {
        var _me$plot = me.plot,
            start = _me$plot.start,
            end = _me$plot.end;
        if (startPoint.x < start.x || startPoint.x > end.x || startPoint.y < end.y || startPoint.y > start.y) return;
      }

      canvasDOM.style.cursor = 'crosshair';
      me.startPoint = startPoint;
      me.brushShape = null;
      me.brushing = true;

      if (!container) {
        container = canvas.addGroup({
          zIndex: 5 // upper

        });
        container.initTransform();
      } else {
        container.clear();
      }

      me.container = container;
      if (type === 'POLYGON') me.polygonPath = "M " + startPoint.x + " " + startPoint.y;
    }
  };

  _proto.process = function process(ev) {
    var me = this;
    var brushing = me.brushing,
        dragging = me.dragging,
        type = me.type,
        plot = me.plot,
        startPoint = me.startPoint,
        xScale = me.xScale,
        yScale = me.yScale,
        canvas = me.canvas;

    if (!brushing && !dragging) {
      return;
    }

    var currentPoint = {
      x: ev.offsetX,
      y: ev.offsetY
    };
    var canvasDOM = canvas.get('canvasDOM');

    if (brushing) {
      canvasDOM.style.cursor = 'crosshair';
      var start = plot.start,
          end = plot.end;
      var polygonPath = me.polygonPath;
      var brushShape = me.brushShape;
      var container = me.container;

      if (me.plot && me.inPlot) {
        currentPoint = me._limitCoordScope(currentPoint);
      }

      var rectStartX;
      var rectStartY;
      var rectWidth;
      var rectHeight;

      if (type === 'Y') {
        rectStartX = start.x;
        rectStartY = currentPoint.y >= startPoint.y ? startPoint.y : currentPoint.y;
        rectWidth = Math.abs(start.x - end.x);
        rectHeight = Math.abs(startPoint.y - currentPoint.y);
      } else if (type === 'X') {
        rectStartX = currentPoint.x >= startPoint.x ? startPoint.x : currentPoint.x;
        rectStartY = end.y;
        rectWidth = Math.abs(startPoint.x - currentPoint.x);
        rectHeight = Math.abs(end.y - start.y);
      } else if (type === 'XY') {
        if (currentPoint.x >= startPoint.x) {
          rectStartX = startPoint.x;
          rectStartY = currentPoint.y >= startPoint.y ? startPoint.y : currentPoint.y;
        } else {
          rectStartX = currentPoint.x;
          rectStartY = currentPoint.y >= startPoint.y ? startPoint.y : currentPoint.y;
        }

        rectWidth = Math.abs(startPoint.x - currentPoint.x);
        rectHeight = Math.abs(startPoint.y - currentPoint.y);
      } else if (type === 'POLYGON') {
        polygonPath += "L " + currentPoint.x + " " + currentPoint.y;
        me.polygonPath = polygonPath;

        if (!brushShape) {
          brushShape = container.addShape('path', {
            attrs: Util.mix(me.style, {
              path: polygonPath
            })
          });
        } else {
          !brushShape.get('destroyed') && brushShape.attr(Util.mix({}, brushShape._attrs, {
            path: polygonPath
          }));
        }
      }

      if (type !== 'POLYGON') {
        if (!brushShape) {
          brushShape = container.addShape('rect', {
            attrs: Util.mix(me.style, {
              x: rectStartX,
              y: rectStartY,
              width: rectWidth,
              height: rectHeight
            })
          });
        } else {
          !brushShape.get('destroyed') && brushShape.attr(Util.mix({}, brushShape._attrs, {
            x: rectStartX,
            y: rectStartY,
            width: rectWidth,
            height: rectHeight
          }));
        }
      }

      me.brushShape = brushShape;
    } else if (dragging) {
      canvasDOM.style.cursor = 'move';
      var selection = me.selection;

      if (selection && !selection.get('destroyed')) {
        if (type === 'POLYGON') {
          var prePoint = me.prePoint;
          me.selection.translate(currentPoint.x - prePoint.x, currentPoint.y - prePoint.y);
        } else {
          me.dragoffX && selection.attr('x', currentPoint.x - me.dragoffX);
          me.dragoffY && selection.attr('y', currentPoint.y - me.dragoffY);
        }
      }
    }

    me.prePoint = currentPoint;
    canvas.draw();

    var _me$_getSelected = me._getSelected(),
        data = _me$_getSelected.data,
        shapes = _me$_getSelected.shapes,
        xValues = _me$_getSelected.xValues,
        yValues = _me$_getSelected.yValues;

    var eventObj = {
      data: data,
      shapes: shapes
    };

    if (xScale) {
      eventObj[xScale.field] = xValues;
    }

    if (yScale) {
      eventObj[yScale.field] = yValues;
    } // 将框选的数据传递给 ev，供 onEnd 钩子使用


    Util.mix(ev, eventObj);
    eventObj.x = currentPoint.x;
    eventObj.y = currentPoint.y;
    me.onDragmove && me.onDragmove(eventObj);
    me.onBrushmove && me.onBrushmove(eventObj);
  };

  _proto.end = function end(ev) {
    var me = this;

    if (!me.brushing && !me.dragging) {
      return;
    }

    var data = me.data,
        shapes = me.shapes,
        xValues = me.xValues,
        yValues = me.yValues,
        canvas = me.canvas,
        type = me.type,
        startPoint = me.startPoint,
        chart = me.chart,
        container = me.container,
        xScale = me.xScale,
        yScale = me.yScale;
    var offsetX = ev.offsetX,
        offsetY = ev.offsetY;
    var canvasDOM = canvas.get('canvasDOM');
    canvasDOM.style.cursor = 'default';

    if (startPoint === null) {
      return;
    }

    if (Math.abs(startPoint.x - offsetX) <= 1 && Math.abs(startPoint.y - offsetY) <= 1) {
      // 防止点击事件
      me.brushing = false;
      me.dragging = false;
      container.clear();
      canvas.draw();
      return;
    }

    var eventObj = {
      data: data,
      shapes: shapes
    };

    if (xScale) {
      eventObj[xScale.field] = xValues;
    }

    if (yScale) {
      eventObj[yScale.field] = yValues;
    } // 将框选的数据传递给 ev，供 onEnd 钩子使用


    Util.mix(ev, eventObj);
    eventObj.x = offsetX;
    eventObj.y = offsetY;

    if (me.dragging) {
      me.dragging = false;
      me.onDragend && me.onDragend(eventObj);
    } else if (me.brushing) {
      me.brushing = false;
      var brushShape = me.brushShape;
      var polygonPath = me.polygonPath;

      if (type === 'POLYGON') {
        polygonPath += 'z';
        brushShape && !brushShape.get('destroyed') && brushShape.attr(Util.mix({}, brushShape._attrs, {
          path: polygonPath
        }));
        me.polygonPath = polygonPath;
        canvas.draw();
      }

      if (me.onBrushend) {
        me.onBrushend(eventObj);
      } else if (chart && me.filter) {
        container.clear(); // clear the brush
        // filter data

        if (!me.isTransposed && type === 'X' || me.isTransposed && type === 'Y') {
          xScale && chart.filter(xScale.field, function (val) {
            return xValues.indexOf(val) > -1;
          });
        } else if (!me.isTransposed && type === 'Y' || me.isTransposed && type === 'X') {
          yScale && chart.filter(yScale.field, function (val) {
            return yValues.indexOf(val) > -1;
          });
        } else {
          xScale && chart.filter(xScale.field, function (val) {
            return xValues.indexOf(val) > -1;
          });
          yScale && chart.filter(yScale.field, function (val) {
            return yValues.indexOf(val) > -1;
          });
        }

        chart.repaint();
      }
    }
  };

  _proto.reset = function reset() {
    var me = this;
    var chart = me.chart,
        filter = me.filter,
        brushShape = me.brushShape,
        canvas = me.canvas;

    this._init(); // 重置各种参考值


    if (chart && filter) {
      chart.get('options').filters = {};
      chart.repaint();
    }

    if (brushShape) {
      brushShape.destroy();
      canvas.draw();
    }
  };

  _proto._limitCoordScope = function _limitCoordScope(point) {
    var plot = this.plot;
    var start = plot.start,
        end = plot.end;

    if (point.x < start.x) {
      point.x = start.x;
    }

    if (point.x > end.x) {
      point.x = end.x;
    }

    if (point.y < end.y) {
      point.y = end.y;
    }

    if (point.y > start.y) {
      point.y = start.y;
    }

    return point;
  };

  _proto._getSelected = function _getSelected() {
    var me = this;
    var chart = me.chart,
        xScale = me.xScale,
        yScale = me.yScale,
        brushShape = me.brushShape,
        canvas = me.canvas;
    var pixelRatio = canvas.get('pixelRatio');
    var selectedShapes = [];
    var xValues = [];
    var yValues = [];
    var selectedData = [];

    if (chart) {
      var geoms = chart.get('geoms');
      geoms.map(function (geom) {
        var shapes = geom.getShapes();
        shapes.map(function (shape) {
          var shapeData = shape.get('origin');

          if (!Array.isArray(shapeData)) {
            // 线图、区域图等
            shapeData = [shapeData];
          }

          shapeData.map(function (each) {
            if (brushShape.isHit(each.x * pixelRatio, each.y * pixelRatio)) {
              selectedShapes.push(shape);
              var origin = each._origin;
              selectedData.push(origin);
              xScale && xValues.push(origin[xScale.field]);
              yScale && yValues.push(origin[yScale.field]);
            }

            return each;
          });
          return shape;
        });
        return geom;
      });
    }

    me.shapes = selectedShapes;
    me.xValues = xValues;
    me.yValues = yValues;
    me.data = selectedData;
    canvas.draw();
    return {
      data: selectedData,
      xValues: xValues,
      yValues: yValues,
      shapes: selectedShapes
    };
  };

  return Brush;
}(Interaction); // G2.registerInteraction('brush', Brush);
// G2.registerInteraction('Brush', Brush);


module.exports = Brush;