<script setup lang="ts">
import { magicApi } from "@/utils/database/magic-api-request";
import { useResizeObserver } from "@vueuse/core";
import { stringIsBlank } from "@/utils/blank-utils";

defineOptions({
  name: "RenderTable",
});

const props = defineProps<{
  htmlData: string;
  wardCode: string;
}>();

const store = reactive({
  htmlData: "",
  data: [],
  spans: [] as { span: HTMLSpanElement; code: string }[],
  business: new Set(),

  businessData: {},
});

const divRaf = ref<HTMLDivElement>();

useResizeObserver(divRaf, () => {
  if (stringIsBlank(props.htmlData)) return;
  nextTick(() => {
    if (props.htmlData) renderTable(false);
  });
});

async function replace(query = true) {
  if (query) {
    store.businessData = await magicApi({
      url: "/public/dashboard/dataSource",
      method: "post",
      data: {
        isSource: false,
        business: Array.from(store.business.values()),
        wardCode: props.wardCode,
      },
    })
      .then(res => {
        return res;
      })
      .catch(() => {
        return {};
      });
  }

  store.spans.forEach(item => {
    item.span.innerHTML = store.businessData[item.code] ?? "";
  });

  await nextTick();
  store.spans.forEach(item => {
    const td = (item.span as Element).closest("td");
    if (td == null) {
      return;
    }
    if (!(td.className as string).includes("td-text_hidden")) {
      td.className += " td-text_hidden " + td.className;
    }

    if (td.clientWidth !== td.scrollWidth) {
      const marqueeDiv = document.createElement("div");
      marqueeDiv.className = "marquee";
      marqueeDiv.style.setProperty(
        "--translate-scroll-px",
        `-${td.scrollWidth}px`
      );
      marqueeDiv.innerHTML = td.innerHTML;
      td.innerHTML = "";
      td.appendChild(marqueeDiv);
    }
  });
}

function getBusiness(spans: HTMLSpanElement[]) {
  spans.forEach(span => {
    const code = span.getAttribute("data-element-code");
    span.innerHTML = "";
    store.business.add(code);
    store.spans.push({
      span,
      code,
    });
  });
}

async function renderTable(query = true) {
  await nextTick();
  store.business = new Set();
  store.spans = [];
  divRaf.value.innerHTML = store.htmlData;

  const table = divRaf.value.querySelector("table");
  const trs = table.querySelectorAll("tr");

  trs.forEach(tr => {
    const tds = tr.querySelectorAll("td");
    tds.forEach(td => {
      const business = td.querySelectorAll("span[data-element-code]");
      if (business.length > 0) {
        // @ts-ignore
        getBusiness(business);
      }
    });
  });
  replace(query);
}

watch(
  () => props.htmlData,
  async () => {
    await nextTick();
    store.htmlData = props.htmlData;
    renderTable();
  }
);

defineExpose({
  reloadData() {
    renderTable();
  },
});
</script>

<template>
  <div class="layout_container render-table" ref="divRaf"></div>
</template>

<style lang="scss">
.render-table {
  background: #0f1628;
  font-size: 1.13rem;

  table {
    width: 100%;
    border-collapse: collapse;
    border: 1px solid white;
    height: 100% !important;
    table-layout: fixed;
    color: white;
  }

  td {
    border: 1px solid white;
    text-align: center !important;
  }

  .td-text_hidden {
    white-space: nowrap;
    text-overflow: ellipsis;
    overflow: hidden;
  }

  .marquee {
    white-space: nowrap; /* 不换行 */
    animation: marquee 10s linear infinite; /* 动画效果 */
    line-height: 100%;
    text-align: center;
  }

  @keyframes marquee {
    0% {
      transform: translateX(0px);
    }
    100% {
      transform: translateX(var(--translate-scroll-px));
    }
  }
}
</style>
