<template>
  <v-chart
    class="chart"
    :option="option"
    style="height: 100%; width: 100%"
    ref="chart"
    @click="handleNodeClick"
    lazy
  />
</template>

<script>
import searchApis from "~/apis/searchApi";
import { use } from "echarts/core";
import { CanvasRenderer } from "echarts/renderers";
import { GraphChart } from "echarts/charts";
import {
  TitleComponent,
  TooltipComponent,
  LegendComponent,
} from "echarts/components";
// import VChart from "vue-echarts";

use([
  CanvasRenderer,
  GraphChart,
  TitleComponent,
  TooltipComponent,
  LegendComponent,
]);

export default {
  props: {
    dataChart: {
      type: Object,
      default() {
        return {};
      },
    },
    selectedFilter: {
      type: Object,
      default() {
        return {};
      },
    },
  },
  data() {
    return {
      option: {
        title: {},
        tooltip: {
          position: "bottom",
          extraCssText:
            'max-width: 400px; max-height:100px; white-space: pre-wrap;text-align: justify;font-family: "sahel"; ',
        },
        animationDurationUpdate: 1500,
        animationEasingUpdate: "quadraticIn",
        series: [
          {
            type: "graph",
            layout: "force",

            symbolSize: [250, 60],
            itemStyle: {
              color: "rgb(25, 183, 207)",
              shadowBlur: 10,
              shadowColor: "rgba(25, 100, 150, 0.5)",
              shadowOffsetY: 5,
            },

            emphasis: {
              focus: "adjacency",
            },
            force: {
              repulsion: 3000,
              gravity: 0.1,
              edgeLength: 250,
              layoutAnimation: true,
            },
            axisPointer: {
              type: "cross",
              label: {
                backgroundColor: "#6a7985",
                fontSize: 14,
                fontFamily: "sahel",
              },
            },
            // roam: true,
            zoom: 0.6,
            label: {
              show: true,
              position: "inside",
              fontSize: 14,
              color: "#fff",
              fontFamily: "sahel",
              formatter: function (params) {
                const maxLength = 30;
                const text =
                  params.name.length > maxLength
                    ? params.name.substring(0, maxLength) + "..."
                    : params.name;
                return text;
              },
            },
            draggable: true,
            edgeSymbol: ["circle", "arrow"],
            edgeSymbolSize: [8, 12],
            edgeLabel: {
              fontSize: 12,
            },
            data: [],
            links: [],
            lineStyle: {
              opacity: 0.8,
              width: 2,
              curveness: 0,
            },
          },
        ],
      },

      selectedNodeChildren: [],
      graphCountLimit: 1000,
    };
  },
  watch: {
    dataChart: {
      handler(newValue) {
        if (Object.keys(newValue).length) {
          this.$nextTick(() => {
            this.updateChart(newValue);
          });
        }
      },
      immediate: true,
    },
    selectedFilter: {
      handler(newFilter) {
        // به‌روزرسانی نمودار با توجه به فیلتر جدید
        if (this.dataChart && Object.keys(this.dataChart).length) {
          this.$nextTick(() => {
            this.updateChart(this.dataChart);
          });
        }
      },
      deep: true,
    },
  },

  methods: {
    /**
     * به‌روزرسانی داده‌های نمودار با استفاده از داده‌های جدید.
     * @param {Object} data - داده‌های جدید برای به‌روزرسانی نمودار
     */
    updateChart(data) {
      // console.log(this.selectedFilter.relation_type.title);
      // ایجاد یک Map برای پیگیری محتویات نودهای دیده شده
      const seenNodesMap = new Map();

      // تابع برای تولید کلید منحصر به فرد از محتویات نود
      const generateNodeKey = (node) => {
        return `${node.name}-${node.symbol}-${node.itemStyle.color}-${node.to_type}`;
      };

      const addNodeIfValid = (node) => {
        if (node && node.name && node.name.trim() !== "") {
          //اگر نودی خالی باشد حذفش میکند تا نود خالی نمایش داده نشود

          const key = generateNodeKey(node); //بررسی میکند که اگر متن تکراری باشد حذفش میکند
          if (!seenNodesMap.has(key)) {
            seenNodesMap.set(key, node);
            return node;
          }
        }
        return null;
      };

      const nodesData = [
        addNodeIfValid({
          id: data.id,
          name: data.title,
          symbol: "rect",
          itemStyle: {
            color: "#21325e",
          },
        }),
        ...(this.selectedFilter?.relation_from?.title === "قانون جاری" &&
        this.selectedFilter?.relation_to?.title === "رای و نظر"
          ? data.opinion_relations
              .filter((relation) => {
                if (this.selectedFilter.relation_type.title === "همه موارد") {
                  return true;
                } else if (
                  this.selectedFilter.relation_type.title === "ارتباط عادی"
                ) {
                  return relation.rel_type === "عادی";
                } else if (
                  this.selectedFilter.relation_type.title === "استناد دهی"
                ) {
                  return relation.rel_type === "استناد";
                }
                return false;
              })
              .map((relation, index) =>
                addNodeIfValid({
                  id: relation.from_section_id,
                  name: relation.from_section_title,
                  symbol: "circle",
                  key: relation.to_type,
                  itemStyle: {
                    color: "#f3708f",
                  },
                })
              )
              .filter((node) => node !== null) // حذف نودهای null
          : []),
        ...(this.selectedFilter?.relation_from?.title === "قانون جاری" &&
        this.selectedFilter?.relation_to?.title === "مقررات دیگر"
          ? data.qanon_relations
              .filter((relation) => {
                if (this.selectedFilter.relation_type.title === "همه موارد") {
                  return true;
                } else if (
                  this.selectedFilter.relation_type.title === "ارتباط عادی"
                ) {
                  return relation.rel_type === "عادی";
                } else if (
                  this.selectedFilter.relation_type.title === "استناد دهی"
                ) {
                  return relation.rel_type === "استناد";
                }
                return false;
              })
              .map((relation, index) =>
                addNodeIfValid({
                  id: relation.from_section_id,
                  name: relation.from_section_title,
                  symbol: "roundRect",
                  key: relation.to_type,
                  itemStyle: {
                    color: "#3a9ff5",
                  },
                })
              )
              .filter((node) => node !== null) // حذف نودهای null
          : []),
      ];

      const linksData = [
        ...(this.selectedFilter?.relation_to?.title === "رای و نظر"
          ? data.opinion_relations.map((relation, index) => ({
              source: data.id,
              target: relation.from_section_id,
            }))
          : []),
        ...(this.selectedFilter?.relation_to?.title === "مقررات دیگر"
          ? data.qanon_relations.map((relation, index) => ({
              source: data.id,
              target: relation.from_section_id,
            }))
          : []),
      ];

      // تنظیم داده‌ها به گزینه‌های نمودار
      this.option.series[0].data = nodesData;
      this.option.series[0].links = linksData;
      this.$refs?.chart?.setOption(this.option);
    },
    /**
     * پردازش کلیک روی یک گره در نمودار.
     * @param {object} params - اطلاعات مربوط به گره کلیک شده .
     */
    handleNodeClick(params) {
      // console.log("params", params.data);

      const dataNode = params.data;
      // if (dataNode.children && dataNode.children.length > 0) {
      //     this.handleNodeWithChildren(dataNode);
      // }
      try {
        this.getChildrenNode(dataNode.id, dataNode.key).then((list) => {
          if (!list) return;
          list.forEach((element, index) => {
            // console.log(element);
            var node = {
              name: element.title,
              id: element.id,
              children: [],
              // label: {
              //   backgroundColor: dataColor,
              // },
              itemStyle: {},
            };
            dataNode.children.push(node);
            if (dataNode.id === 0) {
              this.option.series[0].data[0].children.push(node);
            } else {
              this.addChildToParent(
                this.option.series[0].data[0],
                dataNode.id,
                node
              );
            }
          });
        });
      } catch (error) {
        console.error("Error fetching children nodes:", error);
      }
    },
    /**
     * این تابع مسئول دریافت لیست آیتم‌های زیر یک آیتم پدر از سرور است.
     * @param {string} parentId - شناسه آیتم پدر
     * @returns {Promise} - لیست آیتم‌های زیر آیتم پدر
     */
    async getChildrenNode(id, key) {
      let index_key = this.$route.params.key;
      // if (
      //   key === "نشست قضایی" ||
      //   key === "رای وحدت رویه" ||
      //   key === "رای دیوان عدالت اداری" ||
      //   key === "نظر ریاست مجلس"
      // ) {
      //   index_key = "qaopinion";
      // } else if (key === "قانون") {
      //   index_key = "qasection";
      // } else if (key === "مقرره") {
      //   index_key = "rgsection";
      // }

      const payload = {
        id: id,
        key: index_key, //type
      };
      let url = searchApis.chart.graph;
      url = url.replace("{{to_key}}", index_key);
      // ارسال درخواست به سرور و بازگشت پاسخ به صورت Promise

      try {
        const { $api } = useNuxtApp();
        const res = await $api(url, {
          method: "post",
          baseURL: repoUrl(),
          body: payload,
        });

        return res.data;
      } catch (err) {}
    },
    /**
     * این تابع مسئول اضافه کردن یک آیتم فرزند به آیتم پدر می‌باشد.
     * @param {Object} node - آیتم پدر
     * @param {string} parentId - شناسه آیتم پدر
     * @param {Object} newChild - آیتم فرزند جدید
     * @returns {boolean} - مقدار منطقی True در صورت موفقیت آمیز بودن اضافه کردن، در غیر این صورت False
     */
    addChildToParent(node, parentId, newChild) {
      if (node.id === parentId) {
        node.children.push(newChild);
        return true;
      }
      if (node.children) {
        for (let child of node.children) {
          if (this.addChildToParent(child, parentId, newChild)) {
            return true;
          }
        }
      }
      return false;
    },
    showModalTree(event) {
      const itemSelected = { name: event.name, y: event.value };
      this.$emit("list", itemSelected);
    },
    /**
     * پردازش کلیک روی یک گره که دارای فرزندان است.
     * @param {object} dataNode - اطلاعات گره‌ای که کلیک شده است.
     */
    handleNodeWithChildren(dataNode) {
      if (this.selectedNodeChildren.length > 0) {
        this.selectedNodeChildren = [];
        this.removeAllChildren(dataNode);
      } else {
        this.selectedNodeChildren = dataNode.children;
        this.addNodesAndLinks(dataNode.children, dataNode.id);
      }
      this.$refs?.chart?.setOption(this.option);
    },
    /**
     * حذف گره‌های فرزند فرزندان.
     * @param {object} node - اطلاعات گره‌ای که کلیک شده است.
     */
    removeAllChildren(node) {
      if (node.children && node.children.length > 0) {
        node.children.forEach((child) => {
          this.removeAllChildren(child);
        });

        this.removeNodesAndLinks(node.children);
      }
    },
    /**
     * حذف گره‌ها و لینک‌های مربوط به لیست فرزندان.
     * @param {array} children - لیست فرزندان برای حذف گره‌ها و لینک‌ها.
     */
    removeNodesAndLinks(children) {
      this.option.series[0].data = this.option.series[0].data.filter(
        (node) => !children.find((child) => child.id === node.id)
      );
      this.option.series[0].links = this.option.series[0].links.filter(
        (link) => !children.find((child) => child.id === link.target)
      );
    },
    /**
     * اضافه کردن گره‌ها و لینک‌های مربوط به لیست فرزندان به همراه گره والد.
     * @param {array} children - لیست فرزندان برای اضافه کردن گره‌ها و لینک‌ها.
     * @param {string} parentNodeId - نام گره والد.
     */
    addNodesAndLinks(children, parentNodeId) {
      if (this.option.series[0].data.length < this.graphCountLimit) {
        children.forEach((child) => {
          if (
            !this.option.series[0].data.find((node) => node.id === child.id)
          ) {
            this.option.series[0].data.push(child);
          }
          const sourceId = parentNodeId;
          const targetId = child.id;
          const isLink = this.option.series[0].links.find(
            (link) => link.source === sourceId && link.target === targetId
          );
          if (!isLink) {
            this.option.series[0].links.push({
              source: sourceId,
              target: targetId,
            });
          }
        });
      } else {
        // alert("حداکثر تعداد نمایش گراف‌ها!");
      }
    },

    //با کلیک بر روی هر نود نود جدید میساازد
    // handleNodeClick(params) {
    //   console.log("نود کلیک شده",params.data)
    //   console.log("رای",this.dataChart.qanon_relations[2].from_section_id)
    //   const clickedNode = params.data;
    //   const newNode = {
    //     id: `new_${Date.now()}`,
    //     name: "نود جدید",
    //     symbol: "triangle",
    //     itemStyle: {
    //       color: "#ffa500",
    //     },
    //   };

    //   const newLink = {
    //     source: clickedNode.id,
    //     target: newNode.id,
    //   };

    //   // اضافه کردن نود و لینک جدید به داده‌های موجود
    //   this.option.series[0].data.push(newNode);
    //   this.option.series[0].links.push(newLink);

    //   // به‌روزرسانی نمودار
    //   this.$refs.chart.setOption(this.option);
    // },
  },
};
</script>

<style scoped>
.chart {
  height: 850px;
}
</style>