text: "use strict";
  Object.defineProperty(exports, "__esModule", { value: true });
  var tslib_1 = require("tslib");
  var util_1 = require("@antv/util");
  // 暂未发包
  // @ts-ignore
  var component_1 = require("@antv/component");
  var animate_1 = require("../../animate");
  var base_1 = tslib_1.__importDefault(require("../../base"));
  var graphics_1 = require("../../util/graphics");
  var constant_1 = require("../../constant");
  var constant_2 = require("../shape/constant");
  /**
   * Element 图形元素。
   * 定义：在 G2 中，我们会将数据通过图形语法映射成不同的图形，比如点图，数据集中的每条数据会对应一个点，柱状图每条数据对应一个柱子，线图则是一组数据对应一条折线，Element 即一条/一组数据对应的图形元素，它代表一条数据或者一个数据集，在图形层面，它可以是单个 Shape 也可以是多个 Shape，我们称之为图形元素。
   */
  var Element = /** @class */ (function (_super) {
      tslib_1.__extends(Element, _super);
      function Element(cfg) {
          var _this = _super.call(this, cfg) || this;
          // 存储当前开启的状态
          _this.states = [];
          var shapeFactory = cfg.shapeFactory, container = cfg.container, offscreenGroup = cfg.offscreenGroup, _a = cfg.visible, visible = _a === void 0 ? true : _a;
          _this.shapeFactory = shapeFactory;
          _this.container = container;
          _this.offscreenGroup = offscreenGroup;
          _this.visible = visible;
          return _this;
      }
      /**
       * 绘制图形。
       * @param model 绘制数据。
       * @param isUpdate 可选，是否是更新发生后的绘制。
       */
      Element.prototype.draw = function (model, isUpdate) {
          if (isUpdate === void 0) { isUpdate = false; }
          this.model = model;
          this.data = model.data; // 存储原始数据
          this.shapeType = this.getShapeType(model);
          // 绘制图形
          this.drawShape(model, isUpdate);
          if (this.visible === false) {
              // 用户在初始化的时候声明 visible: false
              this.changeVisible(false);
          }
      };
      /**
       * 更新图形。
       * @param model 更新的绘制数据。
       */
      Element.prototype.update = function (model) {
          var _a = this, shapeFactory = _a.shapeFactory, shape = _a.shape;
          if (!shape) {
              return;
          }
          // 更新数据
          this.model = model;
          this.data = model.data;
          this.shapeType = this.getShapeType(model);
          // step 1: 更新 shape 携带的信息
          this.setShapeInfo(shape, model);
          // step 2: 使用虚拟 Group 重新绘制 shape，然后更新当前 shape
          var offscreenGroup = this.getOffscreenGroup();
          var newShape = shapeFactory.drawShape(this.shapeType, model, offscreenGroup);
          // @ts-ignore
          newShape.cfg.data = this.data;
          // @ts-ignore
          newShape.cfg.origin = model;
          // label 需要使用
          newShape.cfg.element = this;
          // step 3: 同步 shape 样式
          this.syncShapeStyle(shape, newShape, this.getStates(), this.getAnimateCfg('update'));
      };
      /**
       * 销毁 element 实例。
       */
      Element.prototype.destroy = function () {
          var _a = this, shapeFactory = _a.shapeFactory, shape = _a.shape;
          if (shape) {
              var animateCfg = this.getAnimateCfg('leave');
              if (animateCfg) {
                  // 指定了动画配置则执行销毁动画
                  animate_1.doAnimate(shape, animateCfg, {
                      coordinate: shapeFactory.coordinate,
                      toAttrs: tslib_1.__assign({}, shape.attr()),
                  });
              }
              else {
                  // 否则直接销毁
                  shape.remove(true);
              }
          }
          // reset
          this.states = [];
          this.shapeFactory = undefined;
          this.container = undefined;
          this.shape = undefined;
          this.animate = undefined;
          this.geometry = undefined;
          this.labelShape = undefined;
          this.model = undefined;
          this.data = undefined;
          this.offscreenGroup = undefined;
          this.statesStyle = undefined;
          _super.prototype.destroy.call(this);
      };
      /**
       * 显示或者隐藏 element。
       * @param visible 是否可见。
       */
      Element.prototype.changeVisible = function (visible) {
          _super.prototype.changeVisible.call(this, visible);
          if (visible) {
              if (this.shape) {
                  this.shape.show();
              }
              if (this.labelShape) {
                  this.labelShape.forEach(function (label) {
                      label.show();
                  });
              }
          }
          else {
              if (this.shape) {
                  this.shape.hide();
              }
              if (this.labelShape) {
                  this.labelShape.forEach(function (label) {
                      label.hide();
                  });
              }
          }
      };
      /**
       * 设置 Element 的状态。
       *
       * 目前 Element 开放三种状态：
       * 1. active
       * 2. selected
       * 3. inactive
       *
       * 这三种状态相互独立，可以进行叠加。
       *
       * 这三种状态的样式可在 [[Theme]] 主题中或者通过 `geometry.state()` 接口进行配置。
       *
       * ```ts
       * // 激活 active 状态
       * setState('active', true);
       * ```
       *
       * @param stateName 状态名
       * @param stateStatus 是否开启状态
       */
      Element.prototype.setState = function (stateName, stateStatus) {
          var _a = this, states = _a.states, shapeFactory = _a.shapeFactory, model = _a.model, shape = _a.shape, shapeType = _a.shapeType;
          var index = states.indexOf(stateName);
          if (stateStatus) {
              // 开启状态
              if (index > -1) {
                  // 该状态已经开启，则返回
                  return;
              }
              states.push(stateName);
              if (stateName === 'active' || stateName === 'selected') {
                  shape.toFront();
              }
          }
          else {
              if (index === -1) {
                  // 关闭状态，但是状态未设置过
                  return;
              }
              states.splice(index, 1);
              if (stateName === 'active' || stateName === 'selected') {
                  shape.toBack();
              }
          }
          // 使用虚拟 group 重新绘制 shape，然后对这个 shape 应用状态样式后，更新当前 shape。
          var offscreenShape = shapeFactory.drawShape(shapeType, model, this.getOffscreenGroup());
          if (states.length) {
              // 应用当前状态
              this.syncShapeStyle(shape, offscreenShape, states, null);
          }
          else {
              // 如果没有状态，则需要恢复至原始状态
              this.syncShapeStyle(shape, offscreenShape, ['reset'], null);
          }
          offscreenShape.remove(true); // 销毁，减少内存占用
          var eventObject = {
              state: stateName,
              stateStatus: stateStatus,
              element: this,
              target: this.container,
          };
          this.container.emit('statechange', eventObject);
          // @ts-ignore
          component_1.propagationDelegate(this.shape, 'statechange', eventObject);
      };
      /**
       * 清空状量态，恢复至初始状态。
       */
      Element.prototype.clearStates = function () {
          var _this = this;
          var states = this.states;
          util_1.each(states, function (state) {
              _this.setState(state, false);
          });
          this.states = [];
      };
      /**
       * 查询当前 Element 上是否已设置 `stateName` 对应的状态。
       * @param stateName 状态名称。
       * @returns true 表示存在，false 表示不存在。
       */
      Element.prototype.hasState = function (stateName) {
          return this.states.includes(stateName);
      };
      /**
       * 获取当前 Element 上所有的状态。
       * @returns 当前 Element 上所有的状态数组。
       */
      Element.prototype.getStates = function () {
          return this.states;
      };
      /**
       * 获取 Element 对应的原始数据。
       * @returns 原始数据。
       */
      Element.prototype.getData = function () {
          return this.data;
      };
      /**
       * 获取 Element 对应的图形绘制数据。
       * @returns 图形绘制数据。
       */
      Element.prototype.getModel = function () {
          return this.model;
      };
      /**
       * 返回 Element 元素整体的 bbox，包含文本及文本连线（有的话）。
       * @returns 整体包围盒。
       */
      Element.prototype.getBBox = function () {
          var _a = this, shape = _a.shape, labelShape = _a.labelShape;
          var bbox = {
              x: 0,
              y: 0,
              minX: 0,
              minY: 0,
              maxX: 0,
              maxY: 0,
              width: 0,
              height: 0,
          };
          if (shape) {
              bbox = shape.getCanvasBBox();
          }
          if (labelShape) {
              labelShape.forEach(function (label) {
                  var labelBBox = label.getCanvasBBox();
                  bbox.x = Math.min(labelBBox.x, bbox.x);
                  bbox.y = Math.min(labelBBox.y, bbox.y);
                  bbox.minX = Math.min(labelBBox.minX, bbox.minX);
                  bbox.minY = Math.min(labelBBox.minY, bbox.minY);
                  bbox.maxX = Math.max(labelBBox.maxX, bbox.maxX);
                  bbox.maxY = Math.max(labelBBox.maxY, bbox.maxY);
              });
          }
          bbox.width = bbox.maxX - bbox.minX;
          bbox.height = bbox.maxY - bbox.minY;
          return bbox;
      };
      Element.prototype.getStatesStyle = function () {
          if (!this.statesStyle) {
              var _a = this, shapeType = _a.shapeType, geometry = _a.geometry, shapeFactory = _a.shapeFactory;
              var stateOption = geometry.stateOption;
              var defaultShapeType = shapeFactory.defaultShapeType;
              var stateTheme = shapeFactory.theme[shapeType] || shapeFactory.theme[defaultShapeType];
              this.statesStyle = util_1.deepMix({}, stateTheme, stateOption);
          }
          return this.statesStyle;
      };
      // 从主题中获取对应状态量的样式
      Element.prototype.getStateStyle = function (stateName, shapeKey) {
          var statesStyle = this.getStatesStyle();
          var stateCfg = util_1.get(statesStyle, [stateName, 'style'], {});
          var shapeStyle = stateCfg[shapeKey] || stateCfg;
          if (util_1.isFunction(shapeStyle)) {
              return shapeStyle(this);
          }
          return shapeStyle;
      };
      // 获取动画配置
      Element.prototype.getAnimateCfg = function (animateType) {
          var _this = this;
          var animate = this.animate;
          if (animate) {
              var cfg_1 = animate[animateType];
              if (cfg_1) {
                  // 增加动画的回调函数，如果外部传入了，则先执行外部，然后发射 geometry 的 animate 事件
                  return tslib_1.__assign(tslib_1.__assign({}, cfg_1), { callback: function () {
                          var _a;
                          util_1.isFunction(cfg_1.callback) && cfg_1.callback();
                          (_a = _this.geometry) === null || _a === void 0 ? void 0 : _a.emit(constant_1.GEOMETRY_LIFE_CIRCLE.AFTER_DRAW_ANIMATE);
                      } });
              }
              return cfg_1;
          }
          return null;
      };
      // 绘制图形
      Element.prototype.drawShape = function (model, isUpdate) {
          var _a;
          if (isUpdate === void 0) { isUpdate = false; }
          var _b = this, shapeFactory = _b.shapeFactory, container = _b.container, shapeType = _b.shapeType;
          // 自定义 shape 有可能返回空 shape
          this.shape = shapeFactory.drawShape(shapeType, model, container);
          if (this.shape) {
              this.setShapeInfo(this.shape, model); // 存储绘图数据
              // @ts-ignore
              var name_1 = this.shape.cfg.name;
              // 附加 element 的 name, name 现在支持数组了，很好用了
              if (!name_1) {
                  // 这个地方如果用户添加了 name, 则附加 name ，否则就添加自己的 name
                  // @ts-ignore
                  this.shape.cfg.name = ['element', this.shapeFactory.geometryType];
              }
              else if (util_1.isString(name_1)) {
                  // @ts-ignore
                  this.shape.cfg.name = ['element', name_1];
              }
              // 执行入场动画
              var animateType = isUpdate ? 'enter' : 'appear';
              var animateCfg = this.getAnimateCfg(animateType);
              if (animateCfg) {
                  // 开始执行动画的生命周期
                  (_a = this.geometry) === null || _a === void 0 ? void 0 : _a.emit(constant_1.GEOMETRY_LIFE_CIRCLE.BEFORE_DRAW_ANIMATE);
                  animate_1.doAnimate(this.shape, animateCfg, {
                      coordinate: shapeFactory.coordinate,
                      toAttrs: tslib_1.__assign({}, this.shape.attr()),
                  });
              }
          }
      };
      // 获取虚拟 Group
      Element.prototype.getOffscreenGroup = function () {
          if (!this.offscreenGroup) {
              var GroupCtor = this.container.getGroupBase(); // 获取分组的构造函数
              this.offscreenGroup = new GroupCtor({});
          }
          return this.offscreenGroup;
      };
      // 设置 shape 上需要携带的信息
      Element.prototype.setShapeInfo = function (shape, data) {
          var _this = this;
          // @ts-ignore
          shape.cfg.origin = data;
          // @ts-ignore
          shape.cfg.element = this;
          if (shape.isGroup()) {
              var children = shape.get('children');
              children.forEach(function (child) {
                  _this.setShapeInfo(child, data);
              });
          }
      };
      // 更新当前 shape 的样式
      Element.prototype.syncShapeStyle = function (sourceShape, targetShape, states, animateCfg, index) {
          var _this = this;
          var _a;
          if (states === void 0) { states = []; }
          if (index === void 0) { index = 0; }
          if (!sourceShape || !targetShape) {
              return;
          }
          // 所有的 shape 都需要同步 clip
          var clip = sourceShape.get('clipShape');
          var newClip = targetShape.get('clipShape');
          this.syncShapeStyle(clip, newClip, states, animateCfg);
          if (sourceShape.isGroup()) {
              var children = sourceShape.get('children');
              var newChildren = targetShape.get('children');
              for (var i = 0; i < children.length; i++) {
                  this.syncShapeStyle(children[i], newChildren[i], states, animateCfg, index + i);
              }
          }
          else {
              if (!util_1.isEmpty(states) && !util_1.isEqual(states, ['reset'])) {
                  var name_2 = sourceShape.get('name');
                  if (util_1.isArray(name_2)) {
                      // 会附加 element 的 name
                      name_2 = name_2[1];
                  }
                  util_1.each(states, function (state) {
                      // background shape 不进行状态样式设置
                      if (targetShape.get('name') !== constant_2.BACKGROUND_SHAPE) {
                          var style = _this.getStateStyle(state, name_2 || index); // 如果用户没有设置 name，则默认根据索引值
                          targetShape.attr(style);
                      }
                  });
              }
              var newAttrs = graphics_1.getReplaceAttrs(sourceShape, targetShape);
              if (this.animate) {
                  if (animateCfg) {
                      (_a = this.geometry) === null || _a === void 0 ? void 0 : _a.emit(constant_1.GEOMETRY_LIFE_CIRCLE.BEFORE_DRAW_ANIMATE);
                      // 需要进行动画
                      animate_1.doAnimate(sourceShape, animateCfg, {
                          coordinate: this.shapeFactory.coordinate,
                          toAttrs: newAttrs,
                          shapeModel: this.model,
                      });
                  }
                  else if (util_1.isEmpty(states)) {
                      sourceShape.stopAnimate();
                      sourceShape.animate(newAttrs, {
                          duration: 300,
                      });
                  }
                  else {
                      sourceShape.attr(newAttrs);
                  }
              }
              else {
                  sourceShape.attr(newAttrs);
              }
          }
      };
      Element.prototype.getShapeType = function (model) {
          var shape = util_1.get(model, 'shape');
          return util_1.isArray(shape) ? shape[0] : shape;
      };
      return Element;
  }(base_1.default));
  exports.default = Element;
  //# sourceMappingURL=index.js.map