import { StructureType, MindmapConnectorType, TopicType } from "@/enum";
import { TopicItem } from "@/types";
import { Edge, Graph, Path } from "@antv/x6";
import { getTheme } from "./theme";

// 曲线
Graph.registerConnector(
  "curve-branch-connector",
  (sourcePoint, targetPoint, routerPoints, options) => {
    const midX = sourcePoint.x;
    const ctrX = (targetPoint.x - midX) / 5 + midX;
    const ctrY = targetPoint.y;
    const pathData = `
     M ${sourcePoint.x} ${sourcePoint.y}
     Q ${ctrX} ${ctrY} ${targetPoint.x} ${targetPoint.y}
    `;
    return options.raw ? Path.parse(pathData) : pathData;
  },
  true
);
Graph.registerConnector(
  "curve-sub-connector",
  (sourcePoint, targetPoint, routerPoints, options) => {
    const midX = sourcePoint.x + (sourcePoint.x < targetPoint.x ? 10 : -10);
    const midY = sourcePoint.y;
    const ctrX = (targetPoint.x - midX) / 5 + midX;
    const ctrY = targetPoint.y;
    const pathData = `
     M ${sourcePoint.x} ${sourcePoint.y}
     L ${midX} ${midY}
     Q ${ctrX} ${ctrY} ${targetPoint.x} ${targetPoint.y}
    `;
    return options.raw ? Path.parse(pathData) : pathData;
  },
  true
);
// 直线
Graph.registerConnector(
  "straight-branch-connector",
  function (sourcePoint, targetPoint, routerPoints, options) {
    const halfWidth = this.sourceBBox.width / 2;
    const midX =
      sourcePoint.x +
      (sourcePoint.x < targetPoint.x ? halfWidth + 10 : -halfWidth - 10);
    const midY = sourcePoint.y;
    const pathData = `
     M ${sourcePoint.x} ${sourcePoint.y}
     L ${midX} ${midY}
     L ${targetPoint.x} ${targetPoint.y}
    `;
    return options.raw ? Path.parse(pathData) : pathData;
  },
  true
);
Graph.registerConnector(
  "straight-sub-connector",
  function (sourcePoint, targetPoint, routerPoints, options) {
    const midX = sourcePoint.x + (sourcePoint.x < targetPoint.x ? 10 : -10);
    const midY = sourcePoint.y;
    const pathData = `
     M ${sourcePoint.x} ${sourcePoint.y}
     L ${midX} ${midY}
     L ${targetPoint.x} ${targetPoint.y}
    `;
    return options.raw ? Path.parse(pathData) : pathData;
  },
  true
);
// 圆角折线
Graph.registerConnector(
  "rounded-branch-connector",
  function (sourcePoint, targetPoint, routerPoints, options) {
    const halfWidth = this.sourceBBox.width / 2;
    const midX =
      sourcePoint.x +
      (sourcePoint.x < targetPoint.x ? halfWidth + 10 : -halfWidth - 10);
    const midY = sourcePoint.y;
    const pathData = `
     M ${sourcePoint.x} ${sourcePoint.y}
     L ${midX} ${midY}
     L ${midX} ${targetPoint.y + (targetPoint.y < sourcePoint.y ? 5 : targetPoint.y === sourcePoint.y ? 0 : -5)}
     Q ${midX} ${targetPoint.y} ${midX + (targetPoint.x < sourcePoint.x ? -5 : 5)} ${targetPoint.y}
     L ${targetPoint.x} ${targetPoint.y}
    `;
    return options.raw ? Path.parse(pathData) : pathData;
  },
  true
);
Graph.registerConnector(
  "rounded-sub-connector",
  (sourcePoint, targetPoint, routerPoints, options) => {
    const midX =
      sourcePoint.x < targetPoint.x ? sourcePoint.x + 10 : sourcePoint.x - 10;
    const midY = sourcePoint.y;
    // 可能存在误差
    const deviationY = Math.abs(targetPoint.y - sourcePoint.y);
    const pathData = `
     M ${sourcePoint.x} ${sourcePoint.y}
     L ${midX} ${midY}
     L ${midX} ${targetPoint.y + (deviationY < 10 ? 0 : targetPoint.y < sourcePoint.y ? 5 : -5)}
     Q ${midX} ${targetPoint.y} ${midX + (targetPoint.x < sourcePoint.x ? -5 : 5)} ${targetPoint.y}
     L ${targetPoint.x} ${targetPoint.y}
    `;
    return options.raw ? Path.parse(pathData) : pathData;
  },
  true
);
// 折线
Graph.registerConnector(
  "poly-branch-connector",
  function (sourcePoint, targetPoint, routerPoints, options) {
    const halfWidth = this.sourceBBox.width / 2;
    const midX =
      sourcePoint.x +
      (sourcePoint.x < targetPoint.x ? halfWidth + 10 : -halfWidth - 10);
    const midY = sourcePoint.y;
    const pathData = `
     M ${sourcePoint.x} ${sourcePoint.y}
     L ${midX} ${midY}
     L ${midX} ${targetPoint.y}
     L ${targetPoint.x} ${targetPoint.y}
    `;
    return options.raw ? Path.parse(pathData) : pathData;
  },
  true
);
Graph.registerConnector(
  "poly-sub-connector",
  function (sourcePoint, targetPoint, routerPoints, options) {
    const midX = sourcePoint.x + (sourcePoint.x < targetPoint.x ? 10 : -10);
    const midY = sourcePoint.y;
    const pathData = `
     M ${sourcePoint.x} ${sourcePoint.y}
     L ${midX} ${midY}
     L ${midX} ${targetPoint.y}
     L ${targetPoint.x} ${targetPoint.y}
    `;
    return options.raw ? Path.parse(pathData) : pathData;
  },
  true
);

// 树形
Graph.registerConnector(
  "tree-branch-connector",
  function (sourcePoint, targetPoint, routerPoints, options) {
    const pathData = `
     M ${sourcePoint.x} ${sourcePoint.y}
     L ${sourcePoint.x} ${sourcePoint.y + 10}
     L ${targetPoint.x} ${sourcePoint.y + 10}
     L ${targetPoint.x} ${targetPoint.y}
    `;
    return options.raw ? Path.parse(pathData) : pathData;
  },
  true
);
Graph.registerConnector(
  "tree-sub-connector",
  function (sourcePoint, targetPoint, routerPoints, options) {
    const pathData = `
     M ${sourcePoint.x} ${sourcePoint.y}
     L ${sourcePoint.x} ${targetPoint.y}
     L ${targetPoint.x} ${targetPoint.y}
    `;
    return options.raw ? Path.parse(pathData) : pathData;
  },
  true
);

// 组织结构
Graph.registerConnector(
  "organization-branch-connector",
  function (sourcePoint, targetPoint, routerPoints, options) {
    const pathData = `
     M ${sourcePoint.x} ${sourcePoint.y}
     L ${sourcePoint.x} ${sourcePoint.y + 10}
     L ${targetPoint.x} ${sourcePoint.y + 10}
     L ${targetPoint.x} ${targetPoint.y}
    `;
    return options.raw ? Path.parse(pathData) : pathData;
  },
  true
);
Graph.registerConnector(
  "organization-sub-connector",
  function (sourcePoint, targetPoint, routerPoints, options) {
    const pathData = `
     M ${sourcePoint.x} ${sourcePoint.y}
     L ${sourcePoint.x} ${sourcePoint.y + 10}
     L ${targetPoint.x} ${sourcePoint.y + 10}
     L ${targetPoint.x} ${targetPoint.y}
    `;
    return options.raw ? Path.parse(pathData) : pathData;
  },
  true
);

// 括号
Graph.registerConnector(
  "bracket-branch-connector",
  function (sourcePoint, targetPoint, routerPoints, options) {
    const midX =
      sourcePoint.x +
      (sourcePoint.x < targetPoint.x ? 20 : -20);
    const midY = sourcePoint.y;
    const pathData = `
     M ${sourcePoint.x} ${sourcePoint.y}
     Q ${midX} ${midY} ${midX} ${sourcePoint.y + (sourcePoint.y < targetPoint.y ? 20 : -20)}
     L ${midX} ${targetPoint.y + (targetPoint.y < sourcePoint.y ? 20 : targetPoint.y === sourcePoint.y ? 0 : -20)}
     Q ${midX} ${targetPoint.y} ${midX + (targetPoint.x < sourcePoint.x ? -20 : 20)} ${targetPoint.y}
    `;
    return options.raw ? Path.parse(pathData) : pathData;
  },
  true
);
Graph.registerConnector(
  "bracket-sub-connector",
  function (sourcePoint, targetPoint, routerPoints, options) {
    const midX =
      sourcePoint.x +
      (sourcePoint.x < targetPoint.x ? 10 : -10);
    const midY = sourcePoint.y;
    const pathData = `
     M ${sourcePoint.x} ${sourcePoint.y}
     Q ${midX} ${midY} ${midX} ${sourcePoint.y + (sourcePoint.y < targetPoint.y ? 10 : -10)}
     L ${midX} ${targetPoint.y + (targetPoint.y < sourcePoint.y ? 10 : targetPoint.y === sourcePoint.y ? 0 : -10)}
     Q ${midX} ${targetPoint.y} ${midX + (targetPoint.x < sourcePoint.x ? -10 : 10)} ${targetPoint.y}
    `;
    return options.raw ? Path.parse(pathData) : pathData;
  },
  true
);

const getConnector = (
  structure: StructureType,
  theme: string,
  type: TopicType
) => {
  // TODO根据结构处理连接线
  if (structure === StructureType.tree) {
    return `tree-${type}-connector`;
  }
  if (structure === StructureType.organization) {
    return `organization-${type}-connector`;
  }
  if ([StructureType.leftBracket, StructureType.rightBracket].includes(structure)) {
    return `bracket-${type}-connector`;
  }
  const themeObj = getTheme(theme);
  if (type === TopicType.branch) {
    return `${themeObj.branchConnector}-${type}-connector`;
  } else {
    return `${themeObj.subConnector}-${type}-connector`;
  }
};

const getSourceAnchor = (type: TopicType, structure: StructureType) => {
  switch (structure) {
    case StructureType.left: {
      return type === TopicType.branch
        ? {
            name: "center",
          }
        : {
            name: "left",
          };
    }
    case StructureType.right: {
      return type === TopicType.branch
        ? {
            name: "center",
          }
        : {
            name: "right",
          };
    }
    case StructureType.leftRight: {
    }
    case StructureType.tree: {
      return type === TopicType.branch
        ? {
            name: "bottom",
            args: {
              dy: -5,
            },
          }
        : {
            name: "bottomLeft",
            args: {
              dx: 10,
            },
          };
    }
    case StructureType.organization: {
      return {
        name: "bottom",
      };
    }
    case StructureType.leftBracket: {
      return {
        name: "left",
        args: {
          dx: -10,
        },
      };
    }
    case StructureType.rightBracket: {
      return {
        name: "right",
        args: {
          dx: 10,
        },
      };
    }
    case StructureType.leftFishbone:
    case StructureType.leftTreeShape:
    case StructureType.rightFishbone:
    case StructureType.rightTreeShape:
      return {
        name: "center",
      };
  }
  return {
    name: "center",
  };
};

const getTargetAnchor = (type: TopicType, structure: StructureType) => {
  switch (structure) {
    case StructureType.left: {
      return {
        name: "right",
      };
    }
    case StructureType.right: {
      return {
        name: "left",
      };
    }
    case StructureType.tree: {
      return type === TopicType.branch
        ? {
            name: "top",
          }
        : {
            name: "left",
          };
    }
    case StructureType.organization: {
      return {
        name: "top",
      };
    }
    case StructureType.leftBracket: {
      return {
        name: "right",
        args: {
          dx: 10,
        },
      };
    }
    case StructureType.rightBracket: {
      return {
        name: "left",
        args: {
          dx: 10,
        },
      };
    }
    case StructureType.leftFishbone:
    case StructureType.leftTreeShape:
    case StructureType.rightFishbone:
    case StructureType.rightTreeShape:
      return {
        name: "center",
        args: {
          dx: "25%",
        },
      };
  }
  return {
    name: "center",
    args: {
      dx: "25%",
    },
  };
};

/**
 * 创建连线
 * @param graph
 * @param sourceId
 * @param item
 * @param structure
 * @param theme
 * @returns
 */
export const createEdge = (
  graph: Graph,
  sourceId: string,
  item: { id: string; data: TopicItem },
  structure: StructureType,
  theme: string
): Edge => {
  return graph.createEdge({
    id: item.id + "-edge",
    inherit: "edge",
    connector: {
      name: getConnector(structure, theme, item.data.type),
    },
    zIndex: 0,
    source: {
      cell: sourceId,
      anchor: getSourceAnchor(item.data.type, structure),
    },
    target: {
      cell: item.id,
      anchor: getTargetAnchor(item.data.type, structure),
    },
    attrs: {
      line: {
        targetMarker: "",
        stroke: item.data.edge?.color || "#A2B1C3",
        strokeWidth: item.data?.edge?.width || 3,
      },
    },
  });
};
