<template>
  <Header :action-groups="actions" :title="title" no-back :draw="draw">
    <template #saves>
      <el-button type="primary" @click="saveHandler" :disabled="draw.drawing">
        保存
      </el-button>
      <el-button @click="gotoTabulation" color="#E6E6E6" :disabled="draw.drawing">
        图纸
      </el-button>
    </template>
  </Header>
</template>

<script lang="ts" setup>
import Header from "../../../components/header/index.vue";
import { ElButton } from "element-plus";
import { useDraw } from "../../../components/container/use-draw.ts";
import { selectScene } from "../../../dialog/vr/index.ts";
import { Scene } from "../../../platform/platform-resource.ts";
import { getHeaderActions, getImage } from "../../../components/header/actions.ts";
import {
  tabulationData,
  refreshTabulationData,
  tableCoverWidth,
  tableCoverHeight,
  overviewData,
} from "../../store.ts";
import { nextTick, onUnmounted } from "vue";
import { DataGroupId } from "@/constant/index.ts";
import { Group } from "konva/lib/Group";
import { Mode } from "@/constant/mode.ts";
import { lineLen } from "@/utils/math.ts";
import { repTabulationStore } from "../tabulation/gen-tab.ts";
import { router } from "../../router.ts";
import { overviewId, params, tabulationId } from "@/example/env.ts";
import { listener } from "@/utils/event.ts";
import { repeatedlyOnly } from "@/utils/shared.ts";

const props = defineProps<{ title: string }>();
const draw = useDraw();
const emit = defineEmits<{
  (e: "selectVR", v: Scene): void;
}>();

const baseActions = getHeaderActions(draw);
const actions = [
  [baseActions.undo, baseActions.redo],
  [
    baseActions.clear,
    baseActions.rotateView,
    { ...baseActions.initViewport, handler: () => draw.initViewport(40) },
    baseActions.toggleShow,
  ],
  [
    {
      handler: async () => {
        const scene = await selectScene();
        emit("selectVR", scene);
      },
      text: "VR辅助",
      icon: "VR",
    },
  ],
  [
    {
      ...baseActions.expose,
      children: baseActions.expose.children.map((item) => ({
        ...item,
        handler() {
          return item.handler(props.title);
        },
      })),
    },
  ],
];

const setViewToTableCover = async () => {
  const oldViewMat = draw.viewer.viewMat;
  const oldShowGrid = draw.config.showGrid;
  const oldSize = draw.config.size;
  const oldBack = draw.config.back;
  const oldShowCompass = draw.config.showCompass;
  const oldLabelLineConfig = { ...draw.config.labelLineConfig };
  const oldShowOffset = draw.config.labelLineConfig.showOffset;
  const getRect = () => draw.stage!.findOne<Group>(`#${DataGroupId}`)!.getClientRect();

  const pop = draw.mode.push(Mode.readonly);
  const rect = getRect();
  const rectScale = (rect.width || 1080) / (rect.height || 850);
  const tableCoverScale = tableCoverWidth / tableCoverHeight;
  const padding = 70;

  let width: number, height: number;
  if (rectScale > tableCoverScale) {
    width = 1080;
    height = width / rectScale;
  } else {
    height = 850;
    width = rectScale * height;
  }
  if (width < padding * 2) {
    width += padding * 2;
  }
  if (height < padding * 2) {
    height += padding * 2;
  }

  draw.config.size = { width, height };
  draw.config.showGrid = false;
  draw.config.back = undefined;
  draw.config.showCompass = false;

  draw.config.labelLineConfig.type = "auto";
  draw.config.labelLineConfig.strokeWidth = 2;
  draw.config.labelLineConfig.fontSize = 10;

  await nextTick();
  draw.config.labelLineConfig.showOffset = padding;
  draw.initViewport(padding);
  await nextTick();

  return [
    {
      width,
      height,
    },
    () => {
      pop();
      draw.config.size = oldSize;
      draw.config.showGrid = oldShowGrid;
      draw.config.back = oldBack;
      draw.config.showCompass = oldShowCompass;
      draw.config.labelLineConfig = oldLabelLineConfig;
      draw.config.labelLineConfig.showOffset = oldShowOffset;
      draw.viewer.setViewMat(oldViewMat);
    },
  ] as const;
};

const saveHandler = repeatedlyOnly(async () => {
  const storeData = draw.getData();
  const [blob, scale, rect] = await draw.enterTemp(async () => {
    const [rect, recover] = await setViewToTableCover();
    await nextTick();
    const mat = draw.viewer.transform.invert();
    const scale =
      lineLen(mat.point({ x: 1, y: 0 }), mat.point({ x: 0, y: 0 })) *
      draw.store.config.proportion.scale;
    const blob = await getImage(draw, "image/png");
    recover();
    await nextTick();
    return [blob, scale, rect] as const;
  });

  const url = await window.platform.uploadResourse(
    new File([blob], `tabulation-cover.png`)
  );
  overviewId.value = await window.platform.saveOverviewData(overviewId.value, {
    ...overviewData.value,
    listCover: url,
    store: storeData,
    viewport: draw!.viewer.transform.m,
  });

  const cover = {
    url,
    width: rect.width,
    height: rect.height,
    proportion: { ...draw.store.config.proportion, scale },
  };

  tabulationId.value = await window.platform.getTabulationId(overviewId.value);
  await refreshTabulationData();
  const tabStore = await repTabulationStore(
    tabulationData.value.paperKey,
    storeData.config.compass.rotation,
    cover,
    tabulationData.value.isAutoGen ? undefined : tabulationData.value.store
  );

  tabStore.config.compass = storeData.config.compass;
  tabulationId.value = await window.platform.saveTabulationData(tabulationId.value, {
    ...tabulationData.value,
    title: overviewData.value.title,
    cover,
    store: tabStore,
    overviewId: overviewId.value,
  });
  console.log("保存完毕");
});

onUnmounted(
  listener(document.documentElement, "keydown", (ev) => {
    if (ev.ctrlKey && ev.key.toUpperCase() === "S") {
      saveHandler();
    }
  })
);

const gotoTabulation = repeatedlyOnly(async () => {
  await saveHandler();
  router.push({
    ...router.currentRoute.value,
    name: "tabulation",
    query: params.value,
  } as any);
});

defineExpose({ gotoTabulation, saveHandler });
</script>
