<template>
  <div class="containers">
    <canvas :id="canvasId" :width="width" :height="height"></canvas>
  </div>
</template>

<script>
import { v4 as uuidv4 } from 'uuid';
export default {
  props: {
    processFlow: {
      type: Array,
      required: true
    }
  },
  data() {
    return {
      width: '400',
      height: '400',
      showAllBranch: true,//是否显示所有分支(不管是否执行)
      canvasId: `process-${uuidv4()}`,
      colors: {
        Created: '#FFD700',
        Updated: '#FFD700',
        Pending: '#FFA500',
        Completed: '#32CD32',
        Rejected: '#FF0000',
        Default: '#000000'
      },
      text: {
        Updated: '进行中',
        Created: '进行中',
        Pending: '待处理',
        Completed: '已完成',
        Rejected: '已拒绝',
        Default: '未开始'
      },
      nodeWidth: 150,
      nodeHeight: 50,
      horizontalSpacing: 50,
      verticalSpacing: 150,
      depthCounts: []
    };
  },
  watch: {
    processFlow: {
      handler: function(newVal) {
        if(newVal) {
          this.depthBranchCount()
          this.initCanvas()
          // this.draw()
        }
      }
    }
  },
  methods: {
    depthBranchCount(){
      const depthCounts = [];
      const depthIndexes = [];

      const depth = (node, level = 0) => {
        if (!depthCounts[level]) {
          depthCounts[level] = 0;
          depthIndexes[level] = 0;
        }
        depthCounts[level]++;
        node.index = depthIndexes[level]++;
        node.depth = level;
        
        if (node.next && node.next.length > 0) {
          node.next.forEach(child => depth(child, level + 1));
        }
      };

      this.processFlow.forEach(node => depth(node));
      this.depthCounts = depthCounts;
    },
    draw() {
      //处理分支,如果有分支已经执行了,则不再显示其他分支
      const filterBranches = (node) => {
          if (node.next && node.next.length > 1) {
              const executedBranch = node.next.find(child => child.status);
              if (executedBranch) {
                  node.next = [executedBranch];
              }
          }
          if (node.next) {
              node.next.forEach(child => filterBranches(child));
          }
      };
      // 过滤分支
      if(!this.showAllBranch) this.processFlow.forEach(node => filterBranches(node));
      let _this = this;
      const flow = this.processFlow;
      // 遍历 flow 数据，提取节点信息并构建层次结构
      const layers = [];
      function buildLayers(node, layer = 0) {
        if (!layers[layer]) layers[layer] = [];
        if (!layers[layer].includes(node)) {
          layers[layer].push(node);

          if (node.next) {
            node.next.forEach(child => {
              if (child && child.id) {
                buildLayers(child, layer + 1);
              }
            });
          }
        }
      }

      // 初始化层次结构
      buildLayers(flow[0]);

      // 设置每层节点的布局
      function positionNodes(layers, canvasWidth, nodeWidth, horizontalSpacing, verticalSpacing) {
        layers.forEach((layer, layerIndex) => {
          const totalWidth = layer.length * nodeWidth + (layer.length - 1) * horizontalSpacing;
          let startX = (canvasWidth - totalWidth) / 2;

          layer.forEach((node, index) => {
            node.x = startX + index * (nodeWidth + horizontalSpacing);
            node.y = layerIndex * verticalSpacing;
          });
        });
      }

      // Canvas 配置
      // const canvasWidth = 600;
      // const nodeWidth = 150;
      // const nodeHeight = 60;
      // const horizontalSpacing = 80;
      // const verticalSpacing = 150;
      const canvasWidth = this.width;
      const nodeWidth = this.nodeWidth;
      const nodeHeight = this.nodeHeight;
      const horizontalSpacing = this.horizontalSpacing;
      const verticalSpacing = this.verticalSpacing;

      positionNodes(layers, canvasWidth, nodeWidth, horizontalSpacing, verticalSpacing);

      // 绘制流程图
      function renderFlowchart(ctx, layers, nodeWidth, nodeHeight) {
        layers.forEach(layer => {
          layer.forEach(node => {
            // 绘制节点类型
            // 绘制节点
            if (node.type === 'gateway') {
              const radius = nodeHeight / 2;
              ctx.fillStyle = "#fff";
              ctx.beginPath();
              ctx.arc(node.x + nodeWidth / 2, node.y + radius, radius, 0, 2 * Math.PI);
              ctx.fill();
              
              ctx.strokeStyle = "#000";
              ctx.stroke();
              ctx.fillStyle = "#000";
              ctx.textAlign = "center"; // 水平居中
              ctx.textBaseline = "middle"; // 垂直居中
              ctx.fillText('分支', node.x + nodeWidth / 2, node.y + radius);
            
            } else {
              ctx.fillStyle = "#fff";
              ctx.fillRect(node.x + nodeWidth / 2 - nodeWidth / 2, node.y, nodeWidth, nodeHeight);
              ctx.strokeStyle = "#000";
              ctx.strokeRect(node.x + nodeWidth / 2 - nodeWidth / 2, node.y, nodeWidth, nodeHeight);
              ctx.fillStyle = "#000";
              ctx.textAlign = "center"; // 水平居中
              ctx.textBaseline = "middle"; // 垂直居中
              ctx.fillText(node.name, node.x + nodeWidth / 2, node.y + nodeHeight / 3);
              //绘制状态
              ctx.fillStyle = _this.colors[node.status?.taskState || 'Default'];
              ctx.beginPath();
              ctx.arc(node.x  + nodeWidth / 2 - ctx.measureText(_this.text[node.status?.taskState]).width / 2 - 10, node.y + nodeHeight * 2 / 3, 5, 0, 2 * Math.PI);
              ctx.fill();
              ctx.fillStyle = "#000";
              ctx.fillText(_this.text[node.status?.taskState || 'Default'], node.x + nodeWidth / 2, node.y + nodeHeight * 2 / 3);
              //绘制审批结果
              if(node.comment && node.comment.length > 0) {
                ctx.fillStyle = "#000";
                ctx.fillText(node.comment[0].message, node.x + nodeWidth / 2, node.y + nodeHeight * 2 / 3 + 20);
              }
            }
            // ctx.fillText(node.type || 'unknown', node.x + nodeWidth / 2, node.y + (2 * nodeHeight) / 3);
            
            // 绘制连线到下一个节点
            if (node.next) {
              node.next.forEach(child => {
                if (child && child.x !== undefined && child.y !== undefined) {
                  ctx.beginPath();
                  ctx.moveTo(node.x + nodeWidth / 2, node.y + nodeHeight);
                  ctx.lineTo(child.x + nodeWidth / 2, child.y);
                  ctx.stroke();
                  if(child.condition){
                    ctx.textAlign = "center"; // 水平居中
                    ctx.textBaseline = "middle"; // 垂直居中
                    let text = child.condition._text == '${approvalResult == \'approved\'}' ? '同意' : '拒绝';
                    ctx.fillStyle = text == '同意' ? '#32CD32' : '#FF0000';
                    ctx.fillText(text, (node.x + nodeWidth / 2 + child.x + nodeWidth / 2) / 2, (node.y + nodeHeight + child.y) / 2);
                  }
                }
              });
            }
          });
        });
      }

      // 创建并渲染到画布
      const canvas = document.getElementById(this.canvasId);
      canvas.width = canvasWidth;
      canvas.height = this.height;
      // document.body.appendChild(canvas);

      const ctx = canvas.getContext('2d');
      renderFlowchart(ctx, layers, nodeWidth, nodeHeight);

    },
    initCanvas() {
      //理论应该取最大的宽度，但是一般情况下，最外层只有一个节点
      const totalWidth = this.calculateSubtreeWidth(this.processFlow[0]);
      this.width = totalWidth + 100;
      this.height = ( this.depthCounts.length - 2 ) * (this.nodeHeight + this.verticalSpacing);
      this.$nextTick(() => {
        this.draw();
      });
    },
    calculateSubtreeWidth(node) {
      if (!node.next || node.next.length === 0) {
        return this.nodeWidth;
      }
      return node.next.reduce((width, child) => {
        return width + this.calculateSubtreeWidth(child) + this.horizontalSpacing;
      }, -this.horizontalSpacing);
    },
    initProcess() {//可绘制复杂流程图，但第一个子节点向右偏移来保证不重叠
      const canvas = document.getElementById(this.canvasId);
      const ctx = canvas.getContext("2d");
      // 清空画布
      ctx.clearRect(0, 0, canvas.width, canvas.height);

      // 设置初始位置
      const nodeWidth = this.nodeWidth;
      const nodeHeight = this.nodeHeight;
      const verticalSpacing = this.verticalSpacing;

      // 计算总宽度
      const startX = canvas.width / 2;
      const startY = 30;

      // 计算子树的宽度
      // const calculateSubtreeWidth = (node) => {
      //   if (!node.next || node.next.length === 0) {
      //     return nodeWidth;
      //   }
      //   return node.next.reduce((width, child) => {
      //     return width + calculateSubtreeWidth(child) + horizontalSpacing;
      //   }, -horizontalSpacing);
      // };

      const drawNode = (node, x, y, parentX = null, parentY = null, depth = 0) => {
        if (!node.type) {
        return;
      }
      // 计算子树的总宽度
      const totalChildWidth = node.next ? this.calculateSubtreeWidth(node) : 0;
      const childX = x - totalChildWidth / 2 + this.nodeWidth / 2;
      console.log('222222222 :>> ', 222222222);

      // 绘制节点
      if (node.type === 'gateway') {
        const radius = this.nodeHeight / 2;
        this.ctx.fillStyle = "#fff";
        this.ctx.beginPath();
        this.ctx.arc(x, y + radius, radius, 0, 2 * Math.PI);
        this.ctx.fill();
        
        this.ctx.strokeStyle = "#000";
        this.ctx.stroke();
        this.ctx.fillStyle = "#000";
        this.ctx.textAlign = "center"; // 水平居中
        this.ctx.textBaseline = "middle"; // 垂直居中
        this.ctx.fillText('分支', x, y + radius);
      } else {
        this.ctx.fillStyle = "#fff";
        this.ctx.fillRect(x - this.nodeWidth / 2, y, this.nodeWidth, this.nodeHeight);
        this.ctx.strokeStyle = "#000";
        this.ctx.strokeRect(x - this.nodeWidth / 2, y, this.nodeWidth, this.nodeHeight);
        this.ctx.fillStyle = "#000";
        this.ctx.textAlign = "center"; // 水平居中
        this.ctx.textBaseline = "middle"; // 垂直居中
        this.ctx.fillText(node.name, x, y + this.nodeHeight / 3);
        // 绘制状态
        this.ctx.fillStyle = this.colors[node.status?.taskState || 'Default'];
        this.ctx.beginPath();
        this.ctx.arc(x - this.ctx.measureText(this.text[node.status?.taskState]).width / 2 - 10, y + this.nodeHeight * 2 / 3, 5, 0, 2 * Math.PI);
        this.ctx.fill();
        this.ctx.fillStyle = "#000";
        this.ctx.fillText(this.text[node.status?.taskState || 'Default'], x, y + this.nodeHeight * 2 / 3);
      }

      // 根据状态增加文本显示
      if (parentX !== null && parentY !== null) {
        this.drawLine(parentX, parentY + this.nodeHeight, x, y, node.condition);
      }

      // 根据分支的condition，来显示分支的判断条件
      if (node.next && node.next.length > 0) {
        let currentChildX = childX;
        node.next.forEach((child, index) => {
          const childSubtreeWidth = this.calculateSubtreeWidth(child);
          drawNode(child, currentChildX + childSubtreeWidth / 2, y + this.nodeHeight + this.verticalSpacing, x, y, depth + 1);
          currentChildX += childSubtreeWidth + this.horizontalSpacing;
        });
        }
      };

      const drawLine = (startX, startY, endX, endY,condition) => {
        ctx.beginPath();
        ctx.moveTo(startX, startY);
        ctx.lineTo(endX, endY);
        ctx.stroke();
        if(condition){
          ctx.textAlign = "center"; // 水平居中
          ctx.textBaseline = "middle"; // 垂直居中
          let text = condition._text == '${approvalResult == \'approved\'}' ? '同意' : '拒绝';
          ctx.fillStyle = text == '同意' ? '#32CD32' : '#FF0000';
          ctx.fillText(text, (startX + endX) / 2, (startY + endY) / 2);
        }
      };

      //处理分支,如果有分支已经执行了,则不再显示其他分支
      const filterBranches = (node) => {
          if (node.next && node.next.length > 1) {
              const executedBranch = node.next.find(child => child.status);
              if (executedBranch) {
                  node.next = [executedBranch];
              }
          }
          if (node.next) {
              node.next.forEach(child => filterBranches(child));
          }
      };
      // 过滤分支
      if(!this.showAllBranch) this.processFlow.forEach(node => filterBranches(node));
      // 绘制流程图
      this.processFlow.forEach((node, index) => {
        const totalWidth = this.calculateSubtreeWidth(node);
        drawNode(node, startX - totalWidth / 2 + nodeWidth / 2, startY);
      });
    }
  }
};
</script>

<style scoped>
.containers {
  display: flex;
  justify-content: center;
  align-items: center;
  height: 100%;
}
</style>