"use strict";
Object.defineProperties(exports, { __esModule: { value: true }, [Symbol.toStringTag]: { value: "Module" } });
const tslib_es6 = require("../../../node_modules/tslib/tslib.es6.js");
const util = require("../../../../../../zrender@5.4.4/node_modules/zrender/lib/core/util.js");
const innerStore = require("../../util/innerStore.js");
const Symbol$1 = require("../helper/Symbol.js");
const layoutHelper = require("./layoutHelper.js");
const bbox = require("../../../../../../zrender@5.4.4/node_modules/zrender/lib/core/bbox.js");
const View = require("../../coord/View.js");
const roamHelper = require("../../component/helper/roamHelper.js");
const RoamController = require("../../component/helper/RoamController.js");
const cursorHelper = require("../../component/helper/cursorHelper.js");
const number = require("../../util/number.js");
const Chart = require("../../view/Chart.js");
const Path = require("../../../../../../zrender@5.4.4/node_modules/zrender/lib/graphic/Path.js");
const states = require("../../util/states.js");
const Group = require("../../../../../../zrender@5.4.4/node_modules/zrender/lib/graphic/Group.js");
const basicTransition = require("../../animation/basicTransition.js");
const BezierCurve = require("../../../../../../zrender@5.4.4/node_modules/zrender/lib/graphic/shape/BezierCurve.js");
var TreeEdgeShape = (
  /** @class */
  function() {
    function TreeEdgeShape2() {
      this.parentPoint = [];
      this.childPoints = [];
    }
    return TreeEdgeShape2;
  }()
);
var TreePath = (
  /** @class */
  function(_super) {
    tslib_es6.__extends(TreePath2, _super);
    function TreePath2(opts) {
      return _super.call(this, opts) || this;
    }
    TreePath2.prototype.getDefaultStyle = function() {
      return {
        stroke: "#000",
        fill: null
      };
    };
    TreePath2.prototype.getDefaultShape = function() {
      return new TreeEdgeShape();
    };
    TreePath2.prototype.buildPath = function(ctx, shape) {
      var childPoints = shape.childPoints;
      var childLen = childPoints.length;
      var parentPoint = shape.parentPoint;
      var firstChildPos = childPoints[0];
      var lastChildPos = childPoints[childLen - 1];
      if (childLen === 1) {
        ctx.moveTo(parentPoint[0], parentPoint[1]);
        ctx.lineTo(firstChildPos[0], firstChildPos[1]);
        return;
      }
      var orient = shape.orient;
      var forkDim = orient === "TB" || orient === "BT" ? 0 : 1;
      var otherDim = 1 - forkDim;
      var forkPosition = number.parsePercent(shape.forkPosition, 1);
      var tmpPoint = [];
      tmpPoint[forkDim] = parentPoint[forkDim];
      tmpPoint[otherDim] = parentPoint[otherDim] + (lastChildPos[otherDim] - parentPoint[otherDim]) * forkPosition;
      ctx.moveTo(parentPoint[0], parentPoint[1]);
      ctx.lineTo(tmpPoint[0], tmpPoint[1]);
      ctx.moveTo(firstChildPos[0], firstChildPos[1]);
      tmpPoint[forkDim] = firstChildPos[forkDim];
      ctx.lineTo(tmpPoint[0], tmpPoint[1]);
      tmpPoint[forkDim] = lastChildPos[forkDim];
      ctx.lineTo(tmpPoint[0], tmpPoint[1]);
      ctx.lineTo(lastChildPos[0], lastChildPos[1]);
      for (var i = 1; i < childLen - 1; i++) {
        var point = childPoints[i];
        ctx.moveTo(point[0], point[1]);
        tmpPoint[forkDim] = point[forkDim];
        ctx.lineTo(tmpPoint[0], tmpPoint[1]);
      }
    };
    return TreePath2;
  }(Path.default)
);
var TreeView = (
  /** @class */
  function(_super) {
    tslib_es6.__extends(TreeView2, _super);
    function TreeView2() {
      var _this = _super !== null && _super.apply(this, arguments) || this;
      _this.type = TreeView2.type;
      _this._mainGroup = new Group.default();
      return _this;
    }
    TreeView2.prototype.init = function(ecModel, api) {
      this._controller = new RoamController.default(api.getZr());
      this._controllerHost = {
        target: this.group
      };
      this.group.add(this._mainGroup);
    };
    TreeView2.prototype.render = function(seriesModel, ecModel, api) {
      var data = seriesModel.getData();
      var layoutInfo = seriesModel.layoutInfo;
      var group = this._mainGroup;
      var layout = seriesModel.get("layout");
      if (layout === "radial") {
        group.x = layoutInfo.x + layoutInfo.width / 2;
        group.y = layoutInfo.y + layoutInfo.height / 2;
      } else {
        group.x = layoutInfo.x;
        group.y = layoutInfo.y;
      }
      this._updateViewCoordSys(seriesModel, api);
      this._updateController(seriesModel, ecModel, api);
      var oldData = this._data;
      data.diff(oldData).add(function(newIdx) {
        if (symbolNeedsDraw(data, newIdx)) {
          updateNode(data, newIdx, null, group, seriesModel);
        }
      }).update(function(newIdx, oldIdx) {
        var symbolEl = oldData.getItemGraphicEl(oldIdx);
        if (!symbolNeedsDraw(data, newIdx)) {
          symbolEl && removeNode(oldData, oldIdx, symbolEl, group, seriesModel);
          return;
        }
        updateNode(data, newIdx, symbolEl, group, seriesModel);
      }).remove(function(oldIdx) {
        var symbolEl = oldData.getItemGraphicEl(oldIdx);
        if (symbolEl) {
          removeNode(oldData, oldIdx, symbolEl, group, seriesModel);
        }
      }).execute();
      this._nodeScaleRatio = seriesModel.get("nodeScaleRatio");
      this._updateNodeAndLinkScale(seriesModel);
      if (seriesModel.get("expandAndCollapse") === true) {
        data.eachItemGraphicEl(function(el, dataIndex) {
          el.off("click").on("click", function() {
            api.dispatchAction({
              type: "treeExpandAndCollapse",
              seriesId: seriesModel.id,
              dataIndex
            });
          });
        });
      }
      this._data = data;
    };
    TreeView2.prototype._updateViewCoordSys = function(seriesModel, api) {
      var data = seriesModel.getData();
      var points = [];
      data.each(function(idx) {
        var layout = data.getItemLayout(idx);
        if (layout && !isNaN(layout.x) && !isNaN(layout.y)) {
          points.push([+layout.x, +layout.y]);
        }
      });
      var min = [];
      var max = [];
      bbox.fromPoints(points, min, max);
      var oldMin = this._min;
      var oldMax = this._max;
      if (max[0] - min[0] === 0) {
        min[0] = oldMin ? oldMin[0] : min[0] - 1;
        max[0] = oldMax ? oldMax[0] : max[0] + 1;
      }
      if (max[1] - min[1] === 0) {
        min[1] = oldMin ? oldMin[1] : min[1] - 1;
        max[1] = oldMax ? oldMax[1] : max[1] + 1;
      }
      var viewCoordSys = seriesModel.coordinateSystem = new View.default();
      viewCoordSys.zoomLimit = seriesModel.get("scaleLimit");
      viewCoordSys.setBoundingRect(min[0], min[1], max[0] - min[0], max[1] - min[1]);
      viewCoordSys.setCenter(seriesModel.get("center"), api);
      viewCoordSys.setZoom(seriesModel.get("zoom"));
      this.group.attr({
        x: viewCoordSys.x,
        y: viewCoordSys.y,
        scaleX: viewCoordSys.scaleX,
        scaleY: viewCoordSys.scaleY
      });
      this._min = min;
      this._max = max;
    };
    TreeView2.prototype._updateController = function(seriesModel, ecModel, api) {
      var _this = this;
      var controller = this._controller;
      var controllerHost = this._controllerHost;
      var group = this.group;
      controller.setPointerChecker(function(e, x, y) {
        var rect = group.getBoundingRect();
        rect.applyTransform(group.transform);
        return rect.contain(x, y) && !cursorHelper.onIrrelevantElement(e, api, seriesModel);
      });
      controller.enable(seriesModel.get("roam"));
      controllerHost.zoomLimit = seriesModel.get("scaleLimit");
      controllerHost.zoom = seriesModel.coordinateSystem.getZoom();
      controller.off("pan").off("zoom").on("pan", function(e) {
        roamHelper.updateViewOnPan(controllerHost, e.dx, e.dy);
        api.dispatchAction({
          seriesId: seriesModel.id,
          type: "treeRoam",
          dx: e.dx,
          dy: e.dy
        });
      }).on("zoom", function(e) {
        roamHelper.updateViewOnZoom(controllerHost, e.scale, e.originX, e.originY);
        api.dispatchAction({
          seriesId: seriesModel.id,
          type: "treeRoam",
          zoom: e.scale,
          originX: e.originX,
          originY: e.originY
        });
        _this._updateNodeAndLinkScale(seriesModel);
        api.updateLabelLayout();
      });
    };
    TreeView2.prototype._updateNodeAndLinkScale = function(seriesModel) {
      var data = seriesModel.getData();
      var nodeScale = this._getNodeGlobalScale(seriesModel);
      data.eachItemGraphicEl(function(el, idx) {
        el.setSymbolScale(nodeScale);
      });
    };
    TreeView2.prototype._getNodeGlobalScale = function(seriesModel) {
      var coordSys = seriesModel.coordinateSystem;
      if (coordSys.type !== "view") {
        return 1;
      }
      var nodeScaleRatio = this._nodeScaleRatio;
      var groupZoom = coordSys.scaleX || 1;
      var roamZoom = coordSys.getZoom();
      var nodeScale = (roamZoom - 1) * nodeScaleRatio + 1;
      return nodeScale / groupZoom;
    };
    TreeView2.prototype.dispose = function() {
      this._controller && this._controller.dispose();
      this._controllerHost = null;
    };
    TreeView2.prototype.remove = function() {
      this._mainGroup.removeAll();
      this._data = null;
    };
    TreeView2.type = "tree";
    return TreeView2;
  }(Chart.default)
);
function symbolNeedsDraw(data, dataIndex) {
  var layout = data.getItemLayout(dataIndex);
  return layout && !isNaN(layout.x) && !isNaN(layout.y);
}
function updateNode(data, dataIndex, symbolEl, group, seriesModel) {
  var isInit = !symbolEl;
  var node = data.tree.getNodeByDataIndex(dataIndex);
  var itemModel = node.getModel();
  var visualColor = node.getVisual("style").fill;
  var symbolInnerColor = node.isExpand === false && node.children.length !== 0 ? visualColor : "#fff";
  var virtualRoot = data.tree.root;
  var source = node.parentNode === virtualRoot ? node : node.parentNode || node;
  var sourceSymbolEl = data.getItemGraphicEl(source.dataIndex);
  var sourceLayout = source.getLayout();
  var sourceOldLayout = sourceSymbolEl ? {
    x: sourceSymbolEl.__oldX,
    y: sourceSymbolEl.__oldY,
    rawX: sourceSymbolEl.__radialOldRawX,
    rawY: sourceSymbolEl.__radialOldRawY
  } : sourceLayout;
  var targetLayout = node.getLayout();
  if (isInit) {
    symbolEl = new Symbol$1.default(data, dataIndex, null, {
      symbolInnerColor,
      useNameLabel: true
    });
    symbolEl.x = sourceOldLayout.x;
    symbolEl.y = sourceOldLayout.y;
  } else {
    symbolEl.updateData(data, dataIndex, null, {
      symbolInnerColor,
      useNameLabel: true
    });
  }
  symbolEl.__radialOldRawX = symbolEl.__radialRawX;
  symbolEl.__radialOldRawY = symbolEl.__radialRawY;
  symbolEl.__radialRawX = targetLayout.rawX;
  symbolEl.__radialRawY = targetLayout.rawY;
  group.add(symbolEl);
  data.setItemGraphicEl(dataIndex, symbolEl);
  symbolEl.__oldX = symbolEl.x;
  symbolEl.__oldY = symbolEl.y;
  basicTransition.updateProps(symbolEl, {
    x: targetLayout.x,
    y: targetLayout.y
  }, seriesModel);
  var symbolPath = symbolEl.getSymbolPath();
  if (seriesModel.get("layout") === "radial") {
    var realRoot = virtualRoot.children[0];
    var rootLayout = realRoot.getLayout();
    var length_1 = realRoot.children.length;
    var rad = void 0;
    var isLeft = void 0;
    if (targetLayout.x === rootLayout.x && node.isExpand === true && realRoot.children.length) {
      var center = {
        x: (realRoot.children[0].getLayout().x + realRoot.children[length_1 - 1].getLayout().x) / 2,
        y: (realRoot.children[0].getLayout().y + realRoot.children[length_1 - 1].getLayout().y) / 2
      };
      rad = Math.atan2(center.y - rootLayout.y, center.x - rootLayout.x);
      if (rad < 0) {
        rad = Math.PI * 2 + rad;
      }
      isLeft = center.x < rootLayout.x;
      if (isLeft) {
        rad = rad - Math.PI;
      }
    } else {
      rad = Math.atan2(targetLayout.y - rootLayout.y, targetLayout.x - rootLayout.x);
      if (rad < 0) {
        rad = Math.PI * 2 + rad;
      }
      if (node.children.length === 0 || node.children.length !== 0 && node.isExpand === false) {
        isLeft = targetLayout.x < rootLayout.x;
        if (isLeft) {
          rad = rad - Math.PI;
        }
      } else {
        isLeft = targetLayout.x > rootLayout.x;
        if (!isLeft) {
          rad = rad - Math.PI;
        }
      }
    }
    var textPosition = isLeft ? "left" : "right";
    var normalLabelModel = itemModel.getModel("label");
    var rotate = normalLabelModel.get("rotate");
    var labelRotateRadian = rotate * (Math.PI / 180);
    var textContent = symbolPath.getTextContent();
    if (textContent) {
      symbolPath.setTextConfig({
        position: normalLabelModel.get("position") || textPosition,
        rotation: rotate == null ? -rad : labelRotateRadian,
        origin: "center"
      });
      textContent.setStyle("verticalAlign", "middle");
    }
  }
  var focus = itemModel.get(["emphasis", "focus"]);
  var focusDataIndices = focus === "relative" ? util.concatArray(node.getAncestorsIndices(), node.getDescendantIndices()) : focus === "ancestor" ? node.getAncestorsIndices() : focus === "descendant" ? node.getDescendantIndices() : null;
  if (focusDataIndices) {
    innerStore.getECData(symbolEl).focus = focusDataIndices;
  }
  drawEdge(seriesModel, node, virtualRoot, symbolEl, sourceOldLayout, sourceLayout, targetLayout, group);
  if (symbolEl.__edge) {
    symbolEl.onHoverStateChange = function(toState) {
      if (toState !== "blur") {
        var parentEl = node.parentNode && data.getItemGraphicEl(node.parentNode.dataIndex);
        if (!(parentEl && parentEl.hoverState === states.HOVER_STATE_BLUR)) {
          states.setStatesFlag(symbolEl.__edge, toState);
        }
      }
    };
  }
}
function drawEdge(seriesModel, node, virtualRoot, symbolEl, sourceOldLayout, sourceLayout, targetLayout, group) {
  var itemModel = node.getModel();
  var edgeShape = seriesModel.get("edgeShape");
  var layout = seriesModel.get("layout");
  var orient = seriesModel.getOrient();
  var curvature = seriesModel.get(["lineStyle", "curveness"]);
  var edgeForkPosition = seriesModel.get("edgeForkPosition");
  var lineStyle = itemModel.getModel("lineStyle").getLineStyle();
  var edge = symbolEl.__edge;
  if (edgeShape === "curve") {
    if (node.parentNode && node.parentNode !== virtualRoot) {
      if (!edge) {
        edge = symbolEl.__edge = new BezierCurve.default({
          shape: getEdgeShape(layout, orient, curvature, sourceOldLayout, sourceOldLayout)
        });
      }
      basicTransition.updateProps(edge, {
        shape: getEdgeShape(layout, orient, curvature, sourceLayout, targetLayout)
      }, seriesModel);
    }
  } else if (edgeShape === "polyline") {
    if (layout === "orthogonal") {
      if (node !== virtualRoot && node.children && node.children.length !== 0 && node.isExpand === true) {
        var children = node.children;
        var childPoints = [];
        for (var i = 0; i < children.length; i++) {
          var childLayout = children[i].getLayout();
          childPoints.push([childLayout.x, childLayout.y]);
        }
        if (!edge) {
          edge = symbolEl.__edge = new TreePath({
            shape: {
              parentPoint: [targetLayout.x, targetLayout.y],
              childPoints: [[targetLayout.x, targetLayout.y]],
              orient,
              forkPosition: edgeForkPosition
            }
          });
        }
        basicTransition.updateProps(edge, {
          shape: {
            parentPoint: [targetLayout.x, targetLayout.y],
            childPoints
          }
        }, seriesModel);
      }
    } else {
      if (process.env.NODE_ENV !== "production") {
        throw new Error("The polyline edgeShape can only be used in orthogonal layout");
      }
    }
  }
  if (edge && !(edgeShape === "polyline" && !node.isExpand)) {
    edge.useStyle(util.defaults({
      strokeNoScale: true,
      fill: null
    }, lineStyle));
    states.setStatesStylesFromModel(edge, itemModel, "lineStyle");
    states.setDefaultStateProxy(edge);
    group.add(edge);
  }
}
function removeNodeEdge(node, data, group, seriesModel, removeAnimationOpt) {
  var virtualRoot = data.tree.root;
  var _a = getSourceNode(virtualRoot, node), source = _a.source, sourceLayout = _a.sourceLayout;
  var symbolEl = data.getItemGraphicEl(node.dataIndex);
  if (!symbolEl) {
    return;
  }
  var sourceSymbolEl = data.getItemGraphicEl(source.dataIndex);
  var sourceEdge = sourceSymbolEl.__edge;
  var edge = symbolEl.__edge || (source.isExpand === false || source.children.length === 1 ? sourceEdge : void 0);
  var edgeShape = seriesModel.get("edgeShape");
  var layoutOpt = seriesModel.get("layout");
  var orient = seriesModel.get("orient");
  var curvature = seriesModel.get(["lineStyle", "curveness"]);
  if (edge) {
    if (edgeShape === "curve") {
      basicTransition.removeElement(edge, {
        shape: getEdgeShape(layoutOpt, orient, curvature, sourceLayout, sourceLayout),
        style: {
          opacity: 0
        }
      }, seriesModel, {
        cb: function() {
          group.remove(edge);
        },
        removeOpt: removeAnimationOpt
      });
    } else if (edgeShape === "polyline" && seriesModel.get("layout") === "orthogonal") {
      basicTransition.removeElement(edge, {
        shape: {
          parentPoint: [sourceLayout.x, sourceLayout.y],
          childPoints: [[sourceLayout.x, sourceLayout.y]]
        },
        style: {
          opacity: 0
        }
      }, seriesModel, {
        cb: function() {
          group.remove(edge);
        },
        removeOpt: removeAnimationOpt
      });
    }
  }
}
function getSourceNode(virtualRoot, node) {
  var source = node.parentNode === virtualRoot ? node : node.parentNode || node;
  var sourceLayout;
  while (sourceLayout = source.getLayout(), sourceLayout == null) {
    source = source.parentNode === virtualRoot ? source : source.parentNode || source;
  }
  return {
    source,
    sourceLayout
  };
}
function removeNode(data, dataIndex, symbolEl, group, seriesModel) {
  var node = data.tree.getNodeByDataIndex(dataIndex);
  var virtualRoot = data.tree.root;
  var sourceLayout = getSourceNode(virtualRoot, node).sourceLayout;
  var removeAnimationOpt = {
    duration: seriesModel.get("animationDurationUpdate"),
    easing: seriesModel.get("animationEasingUpdate")
  };
  basicTransition.removeElement(symbolEl, {
    x: sourceLayout.x + 1,
    y: sourceLayout.y + 1
  }, seriesModel, {
    cb: function() {
      group.remove(symbolEl);
      data.setItemGraphicEl(dataIndex, null);
    },
    removeOpt: removeAnimationOpt
  });
  symbolEl.fadeOut(null, data.hostModel, {
    fadeLabel: true,
    animation: removeAnimationOpt
  });
  node.children.forEach(function(childNode) {
    removeNodeEdge(childNode, data, group, seriesModel, removeAnimationOpt);
  });
  removeNodeEdge(node, data, group, seriesModel, removeAnimationOpt);
}
function getEdgeShape(layoutOpt, orient, curvature, sourceLayout, targetLayout) {
  var cpx1;
  var cpy1;
  var cpx2;
  var cpy2;
  var x1;
  var x2;
  var y1;
  var y2;
  if (layoutOpt === "radial") {
    x1 = sourceLayout.rawX;
    y1 = sourceLayout.rawY;
    x2 = targetLayout.rawX;
    y2 = targetLayout.rawY;
    var radialCoor1 = layoutHelper.radialCoordinate(x1, y1);
    var radialCoor2 = layoutHelper.radialCoordinate(x1, y1 + (y2 - y1) * curvature);
    var radialCoor3 = layoutHelper.radialCoordinate(x2, y2 + (y1 - y2) * curvature);
    var radialCoor4 = layoutHelper.radialCoordinate(x2, y2);
    return {
      x1: radialCoor1.x || 0,
      y1: radialCoor1.y || 0,
      x2: radialCoor4.x || 0,
      y2: radialCoor4.y || 0,
      cpx1: radialCoor2.x || 0,
      cpy1: radialCoor2.y || 0,
      cpx2: radialCoor3.x || 0,
      cpy2: radialCoor3.y || 0
    };
  } else {
    x1 = sourceLayout.x;
    y1 = sourceLayout.y;
    x2 = targetLayout.x;
    y2 = targetLayout.y;
    if (orient === "LR" || orient === "RL") {
      cpx1 = x1 + (x2 - x1) * curvature;
      cpy1 = y1;
      cpx2 = x2 + (x1 - x2) * curvature;
      cpy2 = y2;
    }
    if (orient === "TB" || orient === "BT") {
      cpx1 = x1;
      cpy1 = y1 + (y2 - y1) * curvature;
      cpx2 = x2;
      cpy2 = y2 + (y1 - y2) * curvature;
    }
  }
  return {
    x1,
    y1,
    x2,
    y2,
    cpx1,
    cpy1,
    cpx2,
    cpy2
  };
}
const TreeView$1 = TreeView;
exports.default = TreeView$1;
