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

/**
 * @fileOverview 所有 Geometry 的基类
 * @author dxq613@gmail.com
 */
var Attr = require('@antv/attr/lib');

var Adjust = require('@antv/adjust/lib');

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

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

var Global = require('../global');

var Labels = require('./label/index');

var Shape = require('./shape/shape');

var TooltipMixin = require('./mixin/tooltip');

var ActiveMixin = require('./mixin/active');

var SelectMixin = require('./mixin/select');

var parseFields = require('./util/parse-fields');

var GROUP_ATTRS = ['color', 'shape', 'size'];
var FIELD_ORIGIN = '_origin'; // 转换成对象的数组 [{type: 'adjust'}]

function parseAdjusts(adjusts) {
  // 如果是字符串或者对象转换成数组
  if (Util.isString(adjusts) || Util.isPlainObject(adjusts)) {
    adjusts = [adjusts];
  }

  Util.each(adjusts, function (adjust, index) {
    if (!Util.isObject(adjust)) {
      adjusts[index] = {
        type: adjust
      };
    }
  });
  return adjusts;
}
/**
 * 几何标记
 * @class Geom
 */


var GeomBase = /*#__PURE__*/function (_Base) {
  _inheritsLoose(GeomBase, _Base);

  var _proto = GeomBase.prototype;

  /**
   * 获取默认的配置属性
   * @protected
   * @return {Object} 默认属性
   */
  _proto.getDefaultCfg = function getDefaultCfg() {
    return {
      /**
       * 标记 _id 用于区分执行动画
       * @type {String}
       */
      _id: null,

      /**
       * 类型
       * @type {String}
       */
      type: 'base',

      /**
       * 坐标系
       * @type {Object}
       */
      coord: null,

      /**
       * 属性映射集
       * @protected
       * @type {Object}
       */
      attrs: {},

      /**
       * 所属的View
       * @type {View}
       */
      view: null,

      /**
       * 几何标记显示的数据
       * @type {Array}
       */
      data: [],

      /**
       * 相关的度量
       * @type {Object}
       */
      scales: {},

      /**
       * 绘图容器
       * @type {Object}
       */
      container: null,

      /**
       * 文本容器
       * @type {Object}
       */
      labelContainer: null,

      /**
       * 图形容器
       * @type {Object}
       */
      shapeContainer: null,

      /**
       * 几何标记的一些配置项，用于延迟生成图表
       * @type {Object}
       */
      attrOptions: {},
      // 样式配置项
      styleOptions: null,
      // 选中时的配置项
      selectedOptions: null,
      // active 时的配置项
      activedOptions: null,

      /**
       * 某些类存在默认的adjust，不能更改 adjust
       * @type {Boolean}
       */
      hasDefaultAdjust: false,
      // 数据调整类型
      adjusts: null,

      /**
       * 使用形状的类型
       * @protected
       * @type {String}
       */
      shapeType: null,

      /**
       * 是否生成多个点来绘制图形
       * @protected
       * @type {Boolean}
       */
      generatePoints: false,

      /**
       * 数据是否进行排序
       * @type {Boolean}
       */
      sortable: false,
      labelCfg: null,

      /**
       * 是否共享 tooltip
       * @type {Boolean}
       */
      shareTooltip: true,
      tooltipCfg: null,

      /**
       * 是否执行动画，默认执行
       * @type {Boolean}
       */
      animate: true,

      /**
       * 动画配置
       * @type {[type]}
       */
      animateCfg: null,
      visible: true
    };
  };

  function GeomBase(cfg) {
    var _this;

    _this = _Base.call(this, cfg) || this;
    _this.viewTheme = _this.get('viewTheme');
    Util.assign(_assertThisInitialized(_this), TooltipMixin, ActiveMixin, SelectMixin);

    if (_this.get('container')) {
      _this._initContainer();
    }

    _this._initOptions();

    return _this;
  } // 初始化时对配置项的格式化


  _proto._initOptions = function _initOptions() {
    var adjusts = this.get('adjusts');

    if (adjusts) {
      adjusts = parseAdjusts(adjusts);
      this.set('adjusts', adjusts);
    }
  };

  _proto._createScale = function _createScale(field, data) {
    var scales = this.get('scales');
    var scale = scales[field];

    if (!scale) {
      scale = this.get('view').createScale(field, data);
      scales[field] = scale;
    }

    return scale;
  };

  _proto._setAttrOptions = function _setAttrOptions(attrName, attrCfg) {
    var options = this.get('attrOptions');
    options[attrName] = attrCfg;
  };

  _proto._createAttrOption = function _createAttrOption(attrName, field, cfg, defaultValues) {
    var attrCfg = {};
    attrCfg.field = field;

    if (cfg) {
      if (Util.isFunction(cfg)) {
        attrCfg.callback = cfg;
      } else {
        attrCfg.values = cfg;
      }
    } else if (attrName !== 'color') {
      attrCfg.values = defaultValues;
    }

    this._setAttrOptions(attrName, attrCfg);
  }
  /**
   * 位置属性映射
   * @chainable
   * @param  {String} field 字段名
   * @return {Geom} geom 当前几何标记
   */
  ;

  _proto.position = function position(field) {
    this._setAttrOptions('position', {
      field: field
    });

    return this;
  }
  /**
   * 颜色属性映射
   * @chainable
   * @param  {String} field 字段名
   * @param  {Array|Function} values 颜色的数组或者回调函数
   * @return {Geom} geom 当前几何标记
   */
  ;

  _proto.color = function color(field, values) {
    var viewTheme = this.viewTheme || Global;

    this._createAttrOption('color', field, values, viewTheme.colors);

    return this;
  }
  /**
   * 大小属性映射
   * @chainable
   * @param  {String} field 字段名
   * @param  {Array|Function} values 大小的数组或者回调函数
   * @return {Geom} geom 当前几何标记
   */
  ;

  _proto.size = function size(field, values) {
    var viewTheme = this.viewTheme || Global;

    this._createAttrOption('size', field, values, viewTheme.sizes);

    return this;
  }
  /**
   * 形状属性映射
   * @chainable
   * @param  {String} field 字段名
   * @param  {Array|Function} values 大小的数组或者回调函数
   * @return {Geom} geom 当前几何标记
   */
  ;

  _proto.shape = function shape(field, values) {
    var viewTheme = this.viewTheme || Global;
    var type = this.get('type');
    var shapes = viewTheme.shapes[type] || [];

    this._createAttrOption('shape', field, values, shapes);

    return this;
  }
  /**
   * 透明度属性映射
   * @chainable
   * @param  {String} field 字段名
   * @param  {Array|Function} values 透明度的数组或者回调函数
   * @return {Geom} geom 当前几何标记
   */
  ;

  _proto.opacity = function opacity(field, values) {
    var viewTheme = this.viewTheme || Global;

    this._createAttrOption('opacity', field, values, viewTheme.opacities);

    return this;
  };

  _proto.style = function style(field, cfg) {
    var styleOptions = this.get('styleOptions');

    if (!styleOptions) {
      styleOptions = {};
      this.set('styleOptions', styleOptions);
    }

    if (Util.isObject(field)) {
      cfg = field;
      field = null;
    }

    var fields;

    if (field) {
      fields = parseFields(field);
    }

    styleOptions.fields = fields;
    styleOptions.style = cfg;
    return this;
  };

  _proto.label = function label(field, callback, cfg) {
    var self = this;
    var labelCfg = self.get('labelCfg'); // const scales = Util.map(self.get('labelCfg').fields, field => self._createScale(field));

    if (!labelCfg) {
      labelCfg = {};
      self.set('labelCfg', labelCfg);
    }

    var fields;

    if (field) {
      fields = parseFields(field);
    }

    labelCfg.fields = fields; // 如果存在回调函数

    if (Util.isFunction(callback)) {
      if (!cfg) {
        cfg = {};
      }

      labelCfg.callback = callback;
    } else if (Util.isObject(callback)) {
      // 如果没有设置回调函数
      cfg = callback;
    }

    labelCfg.globalCfg = cfg;
    return this;
  };

  _proto.tooltip = function tooltip(field, cfg) {
    var tooltipCfg = this.get('tooltipCfg');

    if (!tooltipCfg) {
      tooltipCfg = {};
    }

    if (field === false) {
      // geom 关闭 tooltip
      this.set('tooltipCfg', false);
    } else {
      var tooltipFields;

      if (field) {
        tooltipFields = parseFields(field);
      }

      tooltipCfg.fields = tooltipFields;
      tooltipCfg.cfg = cfg;
    }

    this.set('tooltipCfg', tooltipCfg);
    return this;
  };

  _proto.animate = function animate(cfg) {
    this.set('animateCfg', cfg);
    return this;
  }
  /**
   * 是否允许使用默认的图形激活交互
   * @param  {Boolean} enable 是否允许激活开关
   * @param {Object} cfg 激活的配置项
   * @return {Geom}    返回 geom 自身
   */
  ;

  _proto.active = function active(enable, cfg) {
    if (enable === false) {
      this.set('allowActive', false);
    } else if (Util.isObject(enable)) {
      this.set('allowActive', true);
      this.set('activedOptions', enable);
    } else {
      this.set('allowActive', true);
      this.set('activedOptions', cfg);
    }

    return this;
  }
  /**
   * 对 geometry 进行数据调整
   * @chainable
   * @param  {String|Array|null} adjusts 数据调整的类型
   * @return {Object} geometry 对象
   */
  ;

  _proto.adjust = function adjust(adjusts) {
    if (!this.get('hasDefaultAdjust')) {
      if (adjusts) {
        adjusts = parseAdjusts(adjusts);
      }

      this.set('adjusts', adjusts);
    }

    return this;
  }
  /**
   * 设置图形的选中模式
   * @param  {Boolean|Object} enable 布尔类型用于模式开关，对象类型用于配置
   * @param  {Object} cfg    选中配置项
   * @return {Geom}          返回 geom 自身
   */
  ;

  _proto.select = function select(enable, cfg) {
    if (enable === false) {
      this.set('allowSelect', false);
    } else if (Util.isObject(enable)) {
      this.set('allowSelect', true);
      this.set('selectedOptions', enable);
    } else {
      this.set('allowSelect', true);
      this.set('selectedOptions', cfg);
    }

    return this;
  };

  _proto.hasAdjust = function hasAdjust(adjustType) {
    var self = this;
    var adjusts = self.get('adjusts');

    if (!adjustType) {
      return false;
    }

    var rst = false;
    Util.each(adjusts, function (adjust) {
      if (adjust.type === adjustType) {
        rst = true;
        return false;
      }
    });
    return rst;
  };

  _proto.hasStack = function hasStack() {
    var isStacked = this.get('isStacked');

    if (Util.isNil(isStacked)) {
      isStacked = this.hasAdjust('stack');
      this.set('isStacked', isStacked);
    }

    return isStacked;
  };

  _proto.isInCircle = function isInCircle() {
    var coord = this.get('coord');
    return coord && coord.isPolar;
  };

  _proto._initContainer = function _initContainer() {
    var self = this;
    var shapeContainer = self.get('shapeContainer');

    if (!shapeContainer) {
      var container = self.get('container');
      var view = self.get('view');
      var viewId = view && view.get('_id');
      shapeContainer = container.addGroup({
        viewId: viewId,
        visible: self.get('visible')
      });
      self.set('shapeContainer', shapeContainer);
    }
  };

  _proto.init = function init() {
    var self = this;

    self._initContainer();

    self._initAttrs();

    if (self.get('tooltipCfg') && self.get('tooltipCfg').fields) {
      var tooltipFields = self.get('tooltipCfg').fields;
      Util.each(tooltipFields, function (field) {
        self._createScale(field);
      });
    }

    var dataArray = self._processData();

    if (self.get('adjusts')) {
      self._adjust(dataArray);
    }

    self.set('dataArray', dataArray);
  } // step 1: init attrs
  ;

  _proto._initAttrs = function _initAttrs() {
    var self = this;
    var attrs = self.get('attrs');
    var attrOptions = self.get('attrOptions');
    var coord = self.get('coord');
    var viewTheme = self.viewTheme || Global;
    var isPie = false;

    for (var type in attrOptions) {
      if (attrOptions.hasOwnProperty(type)) {
        var option = attrOptions[type];
        var className = Util.upperFirst(type);
        var fields = parseFields(option.field);

        if (type === 'position') {
          option.coord = coord; // 饼图坐标系下，填充一维

          if (fields.length === 1 && coord.type === 'theta') {
            fields.unshift('1');
            isPie = true;
          }
        }

        var scales = [];

        for (var i = 0; i < fields.length; i++) {
          var field = fields[i];

          var scale = self._createScale(field);

          if (type === 'color' && Util.isNil(option.values)) {
            // 设置 color 的默认色值
            if (scale.values.length <= 8) {
              option.values = isPie ? viewTheme.colors_pie : viewTheme.colors;
            } else if (scale.values.length <= 16) {
              option.values = isPie ? viewTheme.colors_pie_16 : viewTheme.colors_16;
            } else {
              option.values = viewTheme.colors_24;
            }

            if (Util.isNil(option.values)) {
              option.values = viewTheme.colors; // 防止主题没有声明诸如 colors_pie 的属性
            }
          }

          scales.push(scale);
        } // 饼图需要填充满整个空间


        if (coord.type === 'theta' && type === 'position' && scales.length > 1) {
          var yScale = scales[1];
          var min = 0;
          var max = Math.max.apply(null, yScale.values);

          if (!isFinite(max)) {
            max = 1;
          }

          yScale.change({
            nice: false,
            min: min,
            max: max
          });
        }

        option.scales = scales;
        var attr = new Attr[className](option);
        attrs[type] = attr;
      }
    }
  } // step 2: 处理数据
  ;

  _proto._processData = function _processData() {
    var self = this;
    var data = this.get('data');
    var dataArray = [];

    var groupedArray = this._groupData(data);

    for (var i = 0; i < groupedArray.length; i++) {
      var subData = groupedArray[i];

      var tempData = self._saveOrigin(subData);

      dataArray.push(self._numberic(tempData));
    }

    return dataArray;
  } // step 2.1 数据分组
  ;

  _proto._groupData = function _groupData(data) {
    var groupScales = this._getGroupScales();

    var fields = groupScales.map(function (scale) {
      return scale.field;
    });
    return Util.Array.group(data, fields);
  } // step 2.2 数据调整前保存原始数据
  ;

  _proto._saveOrigin = function _saveOrigin(data) {
    var rst = [];

    for (var i = 0; i < data.length; i++) {
      var origin = data[i];
      var obj = {};

      for (var k in origin) {
        obj[k] = origin[k];
      } // const obj = Util.mix({}, origin);


      obj[FIELD_ORIGIN] = origin;
      rst.push(obj);
    }

    return rst;
  } // step 2.3 将分类数据翻译成数据, 仅对位置相关的度量进行数字化处理
  ;

  _proto._numberic = function _numberic(data) {
    var positionAttr = this.getAttr('position');
    var scales = positionAttr.scales;
    var result = [];

    for (var j = 0; j < data.length; j++) {
      var obj = data[j];
      var isValidate = true;

      for (var i = 0; i < Math.min(2, scales.length); i++) {
        var scale = scales[i];

        if (scale.isCategory) {
          var field = scale.field;
          obj[field] = scale.translate(obj[field]);

          if (Number.isNaN(obj[field])) {
            // 当分类为 NaN 时，说明该条数据不在定义域内，需要过滤掉
            isValidate = false;
          }
        }
      }

      if (isValidate) {
        result.push(obj);
      }
    }

    return result;
  };

  _proto._getGroupScales = function _getGroupScales() {
    var self = this;
    var scales = self.get('groupScales');

    if (!scales) {
      scales = [];
      var attrs = self.get('attrs');
      Util.each(attrs, function (attr) {
        if (GROUP_ATTRS.includes(attr.type)) {
          var attrScales = attr.scales;
          Util.each(attrScales, function (scale) {
            if (scale.isCategory && Util.indexOf(scales, scale) === -1) {
              scales.push(scale);
            }
          });
        }
      });
      self.set('groupScales', scales);
    }

    return scales;
  };

  _proto._updateStackRange = function _updateStackRange(field, scale, dataArray) {
    var mergeArray = Util.Array.merge(dataArray);
    var min = scale.min;
    var max = scale.max;

    for (var i = 0; i < mergeArray.length; i++) {
      var obj = mergeArray[i]; // 过滤掉非法数据

      if (!Util.isArray(obj[field])) {
        continue;
      }

      var tmpMin = Math.min.apply(null, obj[field]);
      var tmpMax = Math.max.apply(null, obj[field]);

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

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

    if (min < scale.min || max > scale.max) {
      scale.change({
        min: min,
        max: max
      });
    }
  } // step 2.2 调整数据
  ;

  _proto._adjust = function _adjust(dataArray) {
    // 当数据为空的时候，就不需要对数据进行调整了
    if (!dataArray || !dataArray.length) {
      return;
    }

    var self = this;
    var adjusts = self.get('adjusts');
    var viewTheme = this.viewTheme || Global;
    var yScale = self.getYScale();
    var xScale = self.getXScale();
    var xField = xScale.field;
    var yField = yScale ? yScale.field : null;
    Util.each(adjusts, function (adjust) {
      var adjustCfg = Util.mix({
        xField: xField,
        yField: yField
      }, adjust);
      var adjustType = Util.upperFirst(adjust.type);

      if (adjustType === 'Dodge') {
        var adjustNames = [];

        if (xScale.isCategory || xScale.isIdentity) {
          adjustNames.push('x');
        } else if (!yScale) {
          adjustNames.push('y');
        } else {
          throw new Error('dodge is not support linear attribute, please use category attribute!');
        }

        adjustCfg.adjustNames = adjustNames;
        adjustCfg.dodgeRatio = adjustCfg.dodgeRatio || viewTheme.widthRatio.column;
        /* if (self.isInCircle()) {
          adjustCfg.dodgeRatio = 1;
          adjustCfg.marginRatio = 0;
        }*/
      } else if (adjustType === 'Stack') {
        var coord = self.get('coord');

        if (!yScale) {
          // 一维的情况下获取高度和默认size
          adjustCfg.height = coord.getHeight();
          var size = self.getDefaultValue('size') || 3;
          adjustCfg.size = size;
        } // 不进行 transpose 时，用户又没有设置这个参数时，默认从上向下


        if (!coord.isTransposed && Util.isNil(adjustCfg.reverseOrder)) {
          adjustCfg.reverseOrder = true;
        }
      }

      var adjustElement = new Adjust[adjustType](adjustCfg);
      adjustElement.processAdjust(dataArray);

      if (adjustType === 'Stack' && yScale) {
        self._updateStackRange(yField, yScale, dataArray);
      }
    });
  }
  /**
   * @internal 设置coord，通常外部容器变化时，coord 会发生变化
   * @param {Object} coord 坐标系
   */
  ;

  _proto.setCoord = function setCoord(coord) {
    this.set('coord', coord);
    var position = this.getAttr('position');
    var shapeContainer = this.get('shapeContainer');
    shapeContainer.setMatrix(coord.matrix);

    if (position) {
      position.coord = coord;
    }
  } // step 3 绘制
  ;

  _proto.paint = function paint() {
    var self = this;
    var dataArray = self.get('dataArray');
    var mappedArray = [];
    var shapeFactory = self.getShapeFactory();
    shapeFactory.setCoord(self.get('coord'));
    self.set('shapeFactory', shapeFactory);
    var shapeContainer = self.get('shapeContainer');

    self._beforeMapping(dataArray);

    for (var i = 0; i < dataArray.length; i++) {
      var data = dataArray[i];
      var index = i;
      data = self._mapping(data);
      mappedArray.push(data);
      self.draw(data, shapeContainer, shapeFactory, index);
    }

    if (self.get('labelCfg')) {
      self._addLabels(Util.union.apply(null, mappedArray), shapeContainer.get('children'));
    }

    if (!self.get('sortable')) {
      self._sort(mappedArray); // 便于数据的查找，需要对数据进行排序，用于 geom.findPoint()

    } else {
      self.set('dataArray', mappedArray);
    }
  };

  _proto._sort = function _sort(mappedArray) {
    var self = this;
    var xScale = self.getXScale();
    var xField = xScale.field;
    Util.each(mappedArray, function (itemArr) {
      itemArr.sort(function (obj1, obj2) {
        return xScale.translate(obj1[FIELD_ORIGIN][xField]) - xScale.translate(obj2[FIELD_ORIGIN][xField]);
      });
    });
    self.set('dataArray', mappedArray);
  } // step 3.1 before mapping
  ;

  _proto._beforeMapping = function _beforeMapping(dataArray) {
    var self = this;

    if (self.get('sortable')) {
      var xScale = self.getXScale();
      var field = xScale.field;
      Util.each(dataArray, function (data) {
        data.sort(function (v1, v2) {
          return xScale.translate(v1[field]) - xScale.translate(v2[field]);
        });
      });
    }

    if (self.get('generatePoints')) {
      Util.each(dataArray, function (data) {
        self._generatePoints(data);
      });
      Util.each(dataArray, function (data, index) {
        var nextData = dataArray[index + 1];

        if (nextData) {
          data[0].nextPoints = nextData[0].points;
        }
      });
    }
  } // step 3.2 add labels
  ;

  _proto._addLabels = function _addLabels(points, shapes) {
    var self = this;
    var type = self.get('type');
    var viewTheme = self.get('viewTheme') || Global;
    var coord = self.get('coord');
    var C = Labels.getLabelsClass(coord.type, type);
    var container = self.get('container');
    var scales = Util.map(self.get('labelCfg').fields, function (field) {
      return self._createScale(field);
    });
    var labelContainer = container.addGroup(C, {
      _id: this.get('_id'),
      labelCfg: Util.mix({
        scales: scales
      }, self.get('labelCfg')),
      coord: coord,
      geom: self,
      geomType: type,
      yScale: self.getYScale(),
      viewTheme: viewTheme,
      visible: self.get('visible')
    });
    labelContainer.showLabels(points, shapes);
    self.set('labelContainer', labelContainer);
  }
  /**
   * @protected
   * 获取图形的工厂类
   * @return {Object} 工厂类对象
   */
  ;

  _proto.getShapeFactory = function getShapeFactory() {
    var shapeFactory = this.get('shapeFactory');

    if (!shapeFactory) {
      var shapeType = this.get('shapeType');
      shapeFactory = Shape.getShapeFactory(shapeType);
      this.set('shapeFactory', shapeFactory);
    }

    return shapeFactory;
  } // step 3.2 generate points
  ;

  _proto._generatePoints = function _generatePoints(data) {
    var self = this;
    var shapeFactory = self.getShapeFactory();
    var shapeAttr = self.getAttr('shape');

    for (var i = 0; i < data.length; i++) {
      var obj = data[i];
      var cfg = self.createShapePointsCfg(obj);
      var shape = shapeAttr ? self._getAttrValues(shapeAttr, obj) : null;
      var points = shapeFactory.getShapePoints(shape, cfg);
      obj.points = points;
    }
  }
  /**
   * 获取图形对应点的配置项
   * @protected
   * @param  {Object} obj 数据对象
   * @return {Object} cfg 获取图形对应点的配置项
   */
  ;

  _proto.createShapePointsCfg = function createShapePointsCfg(obj) {
    var xScale = this.getXScale();
    var yScale = this.getYScale();

    var x = this._normalizeValues(obj[xScale.field], xScale);

    var y; // 存在没有 y 的情况

    if (yScale) {
      y = this._normalizeValues(obj[yScale.field], yScale);
    } else {
      y = obj.y ? obj.y : 0.1;
    }

    return {
      x: x,
      y: y,
      y0: yScale ? yScale.scale(this.getYMinValue()) : undefined
    };
  }
  /**
   * @protected
   * 如果y轴的最小值小于0则返回0，否则返回最小值
   * @return {Number} y轴上的最小值
   */
  ;

  _proto.getYMinValue = function getYMinValue() {
    var yScale = this.getYScale();
    var min = yScale.min,
        max = yScale.max;
    var value;

    if (min >= 0) {
      value = min;
    } else if (max <= 0) {
      // 当值全位于负区间时，需要保证 ymin 在区域内，不可为 0
      value = max;
    } else {
      value = 0;
    }

    return value;
  } // 将数据归一化
  ;

  _proto._normalizeValues = function _normalizeValues(values, scale) {
    var rst = [];

    if (Util.isArray(values)) {
      for (var i = 0; i < values.length; i++) {
        var v = values[i];
        rst.push(scale.scale(v));
      }
    } else {
      rst = scale.scale(values);
    }

    return rst;
  } // step 3.2 mapping
  ;

  _proto._mapping = function _mapping(data) {
    var self = this;
    var attrs = self.get('attrs');
    var mappedData = [];

    for (var i = 0; i < data.length; i++) {
      var record = data[i];
      var newRecord = {};
      newRecord[FIELD_ORIGIN] = record[FIELD_ORIGIN];
      newRecord.points = record.points;
      newRecord.nextPoints = record.nextPoints;

      for (var k in attrs) {
        if (attrs.hasOwnProperty(k)) {
          var attr = attrs[k];
          var names = attr.names;

          var values = self._getAttrValues(attr, record);

          if (names.length > 1) {
            // position 之类的生成多个字段的属性
            for (var j = 0; j < values.length; j++) {
              var val = values[j];
              var name = names[j];
              newRecord[name] = Util.isArray(val) && val.length === 1 ? val[0] : val; // 只有一个值时返回第一个属性值
            }
          } else {
            newRecord[names[0]] = values.length === 1 ? values[0] : values;
          }
        }
      }

      mappedData.push(newRecord);
    }

    return mappedData;
  } // 获取属性映射的值
  ;

  _proto._getAttrValues = function _getAttrValues(attr, record) {
    var scales = attr.scales;
    var params = [];

    for (var i = 0; i < scales.length; i++) {
      var scale = scales[i];
      var field = scale.field;

      if (scale.type === 'identity') {
        params.push(scale.value);
      } else {
        params.push(record[field]);
      }
    }

    var values = attr.mapping.apply(attr, params);
    return values;
  };

  _proto.getAttrValue = function getAttrValue(attrName, record) {
    var attr = this.getAttr(attrName);
    var rst = null;

    if (attr) {
      var values = this._getAttrValues(attr, record);

      rst = values[0];
    }

    return rst;
  };

  _proto.getDefaultValue = function getDefaultValue(attrName) {
    var value = this.get(attrName);
    var attr = this.getAttr(attrName);

    if (attr) {
      var scale = attr.getScale(attrName);

      if (scale.type === 'identity') {
        value = scale.value;
      }
    }

    return value;
  }
  /**
   * step 3.3 draw
   * @protected
   * @param  {Array} data 绘制图形
   * @param {Object} container 绘图容器
   * @param {Object} shapeFactory 绘制图形的工厂类
   * @param {Number} index 每个 shape 的索引值
   */
  ;

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

    for (var i = 0; i < data.length; i++) {
      var obj = data[i];
      self.drawPoint(obj, container, shapeFactory, index + i);
    }
  };

  _proto.getCallbackCfg = function getCallbackCfg(fields, cfg, origin) {
    if (!fields) {
      return cfg;
    }

    var tmpCfg = {};
    var params = fields.map(function (field) {
      return origin[field];
    });
    Util.each(cfg, function (v, k) {
      if (Util.isFunction(v)) {
        tmpCfg[k] = v.apply(null, params);
      } else {
        tmpCfg[k] = v;
      }
    });
    return tmpCfg;
  };

  _proto._getShapeId = function _getShapeId(dataObj) {
    var id = this.get('_id');
    var keyFields = this.get('keyFields');

    if (keyFields && keyFields.length > 0) {
      Util.each(keyFields, function (key) {
        id += '-' + dataObj[key];
      });
    } else {
      var type = this.get('type');
      var xScale = this.getXScale();
      var yScale = this.getYScale();
      var xField = xScale.field || 'x';
      var yField = yScale.field || 'y';
      var yVal = dataObj[yField];
      var xVal;

      if (xScale.isIdentity) {
        xVal = xScale.value;
      } else {
        xVal = dataObj[xField];
      }

      if (type === 'interval' || type === 'schema') {
        id += '-' + xVal;
      } else if (type === 'line' || type === 'area' || type === 'path') {
        id += '-' + type;
      } else {
        id += '-' + xVal + '-' + yVal;
      }

      var groupScales = this._getGroupScales();

      if (!Util.isEmpty(groupScales)) {
        Util.each(groupScales, function (groupScale) {
          var field = groupScale.field;

          if (groupScale.type !== 'identity') {
            id += '-' + dataObj[field];
          }
        });
      }
    }

    return id;
  };

  _proto.getDrawCfg = function getDrawCfg(obj) {
    var self = this;
    var cfg = {
      origin: obj,
      x: obj.x,
      y: obj.y,
      color: obj.color,
      size: obj.size,
      shape: obj.shape,
      isInCircle: self.isInCircle(),
      opacity: obj.opacity
    };
    var styleOptions = self.get('styleOptions');

    if (styleOptions && styleOptions.style) {
      cfg.style = self.getCallbackCfg(styleOptions.fields, styleOptions.style, obj[FIELD_ORIGIN]);
    }

    if (self.get('generatePoints')) {
      cfg.points = obj.points;
      cfg.nextPoints = obj.nextPoints;
    }

    if (self.get('animate')) {
      // _id 字段仅用于动画
      cfg._id = self._getShapeId(obj[FIELD_ORIGIN]);
    }

    return cfg;
  };

  _proto.appendShapeInfo = function appendShapeInfo(shape, index) {
    if (shape) {
      shape.setSilent('index', index);
      shape.setSilent('coord', this.get('coord'));

      if (this.get('animate') && this.get('animateCfg')) {
        shape.setSilent('animateCfg', this.get('animateCfg'));
      }
    }
  };

  _proto._applyViewThemeShapeStyle = function _applyViewThemeShapeStyle(cfg, shape, shapeFactory) {
    // applying view theme
    var self = this;
    var viewTheme = self.viewTheme || Global;
    var shapeName = shapeFactory.name;

    if (shape) {
      if (shape && (shape.indexOf('hollow') > -1 || shape.indexOf('liquid') > -1)) {
        shapeName = "hollow" + Util.upperFirst(shapeName);
      }
    } else if (shapeFactory.defaultShapeType.indexOf('hollow') > -1) {
      shapeName = "hollow" + Util.upperFirst(shapeName);
    }

    var defaultStyle = viewTheme.shape[shapeName] || {};
    cfg.style = Util.mix({}, defaultStyle, cfg.style);
  };

  _proto.drawPoint = function drawPoint(obj, container, shapeFactory, index) {
    var self = this;
    var shape = obj.shape;
    var cfg = self.getDrawCfg(obj);

    self._applyViewThemeShapeStyle(cfg, shape, shapeFactory);

    var geomShape = shapeFactory.drawShape(shape, cfg, container);
    self.appendShapeInfo(geomShape, index);
  }
  /**
   * 获取属性
   * @protected
   * @param {String} name 属性名
   * @return {Scale} 度量
   */
  ;

  _proto.getAttr = function getAttr(name) {
    return this.get('attrs')[name];
  }
  /**
   * 获取 x 对应的度量
   * @return {Scale} x 对应的度量
   */
  ;

  _proto.getXScale = function getXScale() {
    return this.getAttr('position').scales[0];
  }
  /**
   * 获取 y 对应的度量
   * @return {Scale} y 对应的度量
   */
  ;

  _proto.getYScale = function getYScale() {
    return this.getAttr('position').scales[1];
  };

  _proto.getShapes = function getShapes() {
    var result = [];
    var shapeContainer = this.get('shapeContainer');
    var children = shapeContainer.get('children');
    Util.each(children, function (child) {
      if (child.get('origin')) {
        // 过滤 label
        result.push(child);
      }
    });
    return result;
  };

  _proto.getAttrsForLegend = function getAttrsForLegend() {
    var attrs = this.get('attrs');
    var rst = [];
    Util.each(attrs, function (attr) {
      if (GROUP_ATTRS.includes(attr.type)) {
        rst.push(attr);
      }
    });
    return rst;
  };

  _proto.getFieldsForLegend = function getFieldsForLegend() {
    var fields = [];
    var attrOptions = this.get('attrOptions');
    Util.each(GROUP_ATTRS, function (attrName) {
      var attrCfg = attrOptions[attrName];

      if (attrCfg && attrCfg.field && Util.isString(attrCfg.field)) {
        fields = fields.concat(attrCfg.field.split('*'));
      }
    });
    return Util.uniq(fields);
  };

  _proto.changeVisible = function changeVisible(visible, stopDraw) {
    var me = this;
    me.set('visible', visible);
    var shapeContainer = this.get('shapeContainer');

    if (shapeContainer) {
      shapeContainer.set('visible', visible);
    }

    var labelContainer = this.get('labelContainer');

    if (labelContainer) {
      labelContainer.set('visible', visible);
    }

    if (!stopDraw && shapeContainer) {
      var canvas = shapeContainer.get('canvas');
      canvas.draw();
    }
  };

  _proto.reset = function reset() {
    this.set('attrOptions', {});
    this.clearInner();
  };

  _proto.clearInner = function clearInner() {
    this.clearActivedShapes();
    this.clearSelected();
    var shapeContainer = this.get('shapeContainer');
    shapeContainer && shapeContainer.clear(); // 由于 Labels 对应的模块需要生成group，所以这个地方需要删除

    var labelContainer = this.get('labelContainer');
    labelContainer && labelContainer.remove();
    this.set('attrs', {});
    this.set('groupScales', null); // if (!this.get('hasDefaultAdjust')) {
    //   this.set('adjusts', null);
    // }

    this.set('labelContainer', null);
    this.set('xDistance', null);
    this.set('isStacked', null);
  };

  _proto.clear = function clear() {
    this.clearInner();
    this.set('scales', {});
  };

  _proto.destroy = function destroy() {
    this.clear();
    var shapeContainer = this.get('shapeContainer');
    shapeContainer && shapeContainer.remove();
    this.offEvents();

    _Base.prototype.destroy.call(this);
  };

  _proto.bindEvents = function bindEvents() {
    if (this.get('view')) {
      this._bindActiveAction();

      this._bindSelectedAction();
    }
  };

  _proto.offEvents = function offEvents() {
    if (this.get('view')) {
      this._offActiveAction();

      this._offSelectedAction();
    }
  };

  return GeomBase;
}(Base);

module.exports = GeomBase;