<template>
  <div class="meta2d">
    <div class="tools">
      <t-tooltip content="新建" placement="bottom">
        <a><t-icon name="add" @click="newFile" /></a>
      </t-tooltip>
      <t-tooltip content="保存" placement="bottom">
        <a>
          <t-badge dot :showZero="false" :count="dot ? 1 : 0">
            <t-icon name="save" @click="save(SaveType.Save)" /></t-badge
        ></a>
      </t-tooltip>
      <t-tooltip content="保存为我的组件" placement="bottom">
        <a><t-icon name="layers" @click="save(SaveType.Save, true)" /></a>
      </t-tooltip>
      <t-tooltip content="格式化（双击可连续使用）" placement="bottom">
        <a
          @click="oneFormat"
          @dblclick="alwaysFormat"
          :style="{
            color: one || always ? ' #1677ff' : '',
          }"
        >
          <svg
            width="1em"
            height="1em"
            viewBox="0 0 256 256"
            xmlns="http://www.w3.org/2000/svg"
            xmlns:xlink="http://www.w3.org/1999/xlink"
          >
            <defs><path id="77456364" d="M0 0h256v256H0z"></path></defs>
            <g fill="none" fill-rule="evenodd">
              <mask id="3804093554b" fill="#fff">
                <use xlink:href="#77456364"></use>
              </mask>
              <path
                d="M213 77c0 14.36-11.64 26-26 26H69c-14.36 0-26-11.64-26-26V51c0-14.36 11.64-26 26-26h118c14.36 0 26 11.64 26 26v2h9.125c9.83 0 17.82 7.88 17.997 17.67l.003.33v50c0 9.83-7.88 17.82-17.67 17.997l-.33.003h-84.626v18H139c9.83 0 17.82 7.88 17.997 17.67l.003.33v35c0 16.016-12.984 29-29 29-15.856 0-28.74-12.725-28.996-28.52L99 210v-35c0-9.83 7.88-17.82 17.67-17.997L117 157h.499l.001-20c0-9.83 7.88-17.82 17.67-17.997l.33-.003h84.625V73H213Zm-76 100h-18v33a9 9 0 0 0 8.471 8.985l.264.011.265.004a9 9 0 0 0 8.996-8.735L137 210v-33Zm50-132H69a6 6 0 0 0-6 6v26a6 6 0 0 0 6 6h118a6 6 0 0 0 6-6V51a6 6 0 0 0-6-6Z"
                fill="currentColor"
                fill-rule="nonzero"
                mask="url(#3804093554b)"
              ></path>
            </g>
          </svg>
        </a>
      </t-tooltip>
      <t-tooltip content="清除格式" placement="bottom">
        <a @click="clearFormat">
          <svg
            width="1em"
            height="1em"
            viewBox="0 0 1024 1024"
            xmlns="http://www.w3.org/2000/svg"
          >
            <path
              d="M889.186 384.07 677.671 172.56c-53.063-53.063-139.094-53.063-192.157 0L134.617 523.457c-53.063 53.063-53.063 139.099 0 192.158l170.196 170.2a41.354 41.354 0 0 0 29.243 12.11h215.001a41.354 41.354 0 0 0 29.184-12.05L889.155 576.26c53.094-53.09 53.094-139.126.031-192.19zM830.7 442.558c20.48 20.472 20.764 53.492.855 74.319l-.961.984-298.618 297.358H351.185l-158.09-158.086c-20.76-20.763-20.76-54.43 0-75.193l350.901-350.897c20.764-20.764 54.43-20.764 75.193 0l211.515 211.511z"
              fill="currentColor"
            ></path>
            <path
              d="m685.505 678.754-58.19 58.77-317.587-314.43 58.191-58.774zm197.55 136.508c23.46 0 42.483 18.514 42.483 41.353 0 22.45-18.38 40.724-41.294 41.338l-1.19.016h-454.6c-23.462 0-42.485-18.514-42.485-41.354 0-22.449 18.381-40.723 41.295-41.338l1.19-.015h454.6z"
              fill="currentColor"
            ></path>
          </svg>
        </a>
      </t-tooltip>
      <div class="flex-grow"></div>

      <t-tooltip content="直线" placement="bottom">
        <a
          :draggable="true"
          @dragstart="onAddShape($event, 'line')"
          @click.stop="onAddShape($event, 'line')"
          ><t-icon name="slash"
        /></a>
      </t-tooltip>
      <t-tooltip content="文字" placement="bottom">
        <a
          :draggable="true"
          @dragstart="onAddShape($event, 'text')"
          @click.stop="onAddShape($event, 'text')"
          >T</a
        >
      </t-tooltip>
      <t-tooltip content="连线（双击可连续使用）" placement="bottom">
        <a
          @click="oneDraw"
          @dblclick="alwaysDraw"
          :style="{
            color: oneD || alwaysD ? ' #1677ff' : '',
          }"
        >
          <svg
            width="1em"
            height="1em"
            viewBox="0 0 1024 1024"
            xmlns="http://www.w3.org/2000/svg"
          >
            <path
              d="M192 64a128 128 0 0 1 123.968 96H384a160 160 0 0 1 159.68 149.504L544 320v384a96 96 0 0 0 86.784 95.552L640 800h68.032a128 128 0 1 1 0 64.064L640 864a160 160 0 0 1-159.68-149.504L480 704V320a96 96 0 0 0-86.784-95.552L384 224l-68.032 0.064A128 128 0 1 1 192 64z m640 704a64 64 0 1 0 0 128 64 64 0 0 0 0-128zM192 128a64 64 0 1 0 0 128 64 64 0 0 0 0-128z"
              fill="currentColor"
            ></path>
          </svg>
        </a>
      </t-tooltip>
      <!-- <t-tooltip content="连线" placement="top"> -->
      <t-dropdown
        :minColumnWidth="200"
        :maxHeight="560"
        :delay2="[10, 150]"
        overlayClassName="header-dropdown"
      >
        <a>
          <svg class="l-icon" aria-hidden="true">
            <use
              :xlink:href="
                lineTypes.find((item) => item.value === currentLineType)?.icon
              "
            ></use>
          </svg>
        </a>
        <t-dropdown-menu>
          <t-dropdown-item v-for="item in lineTypes">
            <div class="flex middle" @click="changeLineType(item.value)">
              {{ item.name }} <span class="flex-grow"></span>
              <!-- <t-icon v-show="item.value === currentLineType" name="check" /> -->
              <svg class="l-icon" aria-hidden="true">
                <use :xlink:href="item.icon"></use>
              </svg>
            </div>
          </t-dropdown-item>
        </t-dropdown-menu>
      </t-dropdown>
      <t-dropdown
        :minColumnWidth="200"
        :maxHeight="560"
        :delay2="[10, 150]"
        overlayClassName="header-dropdown"
      >
        <a>
          <svg class="l-icon" aria-hidden="true">
            <use
              :xlink:href="
                fromArrows.find((item) => item.value === fromArrow)?.icon
              "
            ></use>
          </svg>
        </a>
        <t-dropdown-menu>
          <t-dropdown-item v-for="item in fromArrows">
            <div class="flex middle" style="height: 30px;" @click="changeFromArrow(item.value)">
              <svg class="l-icon" aria-hidden="true">
                <use :xlink:href="item.icon"></use>
              </svg>
            </div>
          </t-dropdown-item>
        </t-dropdown-menu>
      </t-dropdown>
      <t-dropdown
        :minColumnWidth="200"
        :maxHeight="560"
        :delay2="[10, 150]"
        overlayClassName="header-dropdown"
      >
        <a>
          <svg class="l-icon" aria-hidden="true">
            <use
              :xlink:href="
                toArrows.find((item) => item.value === toArrow)?.icon
              "
            ></use>
          </svg>
        </a>
        <t-dropdown-menu>
          <t-dropdown-item v-for="item in toArrows">
            <div class="flex middle" style="height: 30px;" @click="changeToArrow(item.value)">
              <svg class="l-icon" aria-hidden="true">
                <use :xlink:href="item.icon"></use>
              </svg>
            </div>
          </t-dropdown-item>
        </t-dropdown-menu>
      </t-dropdown>
      <!-- </t-tooltip> -->
      <t-tooltip content="视图大小" placement="bottom">
        <div style="line-height: 40px; margin-left: 8px">{{ scale }}%</div>
      </t-tooltip>

      <t-tooltip content="100%视图" placement="bottom">
        <a @click="onScaleView"><t-icon name="refresh" /></a>
      </t-tooltip>
      <t-tooltip content="窗口大小" placement="bottom">
        <a @click="onScaleWindow"><t-icon name="minus-rectangle" /></a>
      </t-tooltip>
      <t-tooltip content="数据源" placement="bottom">
        <a @click="connectShow"><t-icon name="server" /></a>
      </t-tooltip>

      <div class="flex-grow"></div>
      <t-tooltip
        :content="isLock === 2 ? '锁定' : isLock === 1 ? '预览' : '编辑'"
        placement="bottom"
      >
        <a>
          <!-- <t-icon name="caret-right" /> -->
          <svg
            v-if="isLock === 1"
            class="l-icon"
            aria-hidden="true"
            @click="onLock"
          >
            <use xlink:href="#l-lock"></use>
          </svg>
          <svg
            v-else-if="isLock === 2"
            class="l-icon"
            aria-hidden="true"
            @click="onLock"
          >
            <use xlink:href="#l-wufayidong"></use>
          </svg>
          <svg v-else class="l-icon" aria-hidden="true" @click="onLock">
            <use xlink:href="#l-unlock"></use>
          </svg>
        </a>
      </t-tooltip>
      <t-tooltip content="运行（在新页面全屏查看）" placement="bottom">
        <a @click="preview"><t-icon name="caret-right" /></a>
      </t-tooltip>

      <t-tooltip content="手机查看" placement="bottom">
        <a><t-icon name="qrcode" /></a>
      </t-tooltip>
      <t-tooltip content="分享" placement="bottom">
        <a><t-icon name="share" /></a>
      </t-tooltip>
      <t-tooltip content="发布" placement="bottom">
        <a><t-icon name="cloud" /></a>
      </t-tooltip>
    </div>
    <div id="meta2d"></div>

    <t-dialog v-model:visible="connectVisible">
      <p>这是通信对话框</p>
    </t-dialog>
  </div>
</template>

<script lang="ts" setup>
import {
  Meta2d,
  Options,
  Pen,
  deepClone,
  LockState,
  PenType,
} from "@meta2d/core";
import { onMounted, onUnmounted, watch, ref, reactive } from "vue";
import { registerBasicDiagram } from "@/services/register";
import { useRouter, useRoute } from "vue-router";
import { useUser } from "@/services/user";
import { getLe5le2d } from "@/services/api";
import { useDot } from "@/services/common";
import {
  save,
  newFile,
  SaveType,
  onScaleView,
  onScaleWindow,
} from "@/services/common";
import { useSelection, SelectionMode } from "@/services/selections";
import { defaultFormat } from "@/services/defaults";
import { MessagePlugin } from "tdesign-vue-next";
import { localMeta2dDataName } from "@/services/utils";
import localforage from "localforage";
import { checkData, Meta2dBackData } from "@/services/utils";
import { cdn } from "@/services/api";
import dayjs from "dayjs";

const router = useRouter();
const route = useRoute();
const { user, message, getUser, getMessage, signout } = useUser();
const { dot, setDot, getDot } = useDot();
const { select } = useSelection();

const meta2dOptions: Options = {
  cdn,
  rule: true,
  background: '#1e2430',
  x: 32,
  y: 32,
  width: 1920,
  height: 1080,
  color: "#bdc7db",
  disableAnchor:true,
  defaultFormat: { ...defaultFormat },
};
onMounted(() => {
  meta2d = new Meta2d('meta2d', meta2dOptions);
  registerBasicDiagram();
  open();
  // @ts-ignore
  meta2d.on('active', active);
  // @ts-ignore
  meta2d.on('inactive', inactive);
  // @ts-ignore
  meta2d.on('scale', scaleListener);
  // @ts-ignore
  meta2d.on("add", lineAdd);
  meta2d.on("opened", openedListener);

  meta2d.on("undo", autoSave);
  meta2d.on("redo", autoSave);
  meta2d.on("add", autoSave);
  meta2d.on("delete", autoSave);
  meta2d.on("rotatePens", autoSave);
  meta2d.on("translatePens", autoSave);

  //TODO所有编辑栏所做修改
  meta2d.on("components-update-value", autoSave);
});

const watcher = watch(
  () => route.query,
  async () => {
    open();
  }
);

const open = async () => {
  if (route.query.id) {
    const ret: any = getLe5le2d(route.query.id + '');
    ret && meta2d.open(ret);
  } else {
    meta2d.open();
  }
  meta2d.store.data.x = meta2d.store.options.x || 0;
  meta2d.store.data.y = meta2d.store.options.y || 0;
};

const openedListener = () => {
  const {
    locked,
    scale: canvasScale,
    fromArrow: canvasFromArrow,
    toArrow: canvasToArrow,
  } = meta2d.store.data;
  isLock.value = locked||0;
  scale.value = Math.round(canvasScale * 100);
  fromArrow.value = canvasFromArrow||"";
  toArrow.value = canvasToArrow||"";
}

onUnmounted(() => {
  watcher();
  if (meta2d) {
    // @ts-ignore
    meta2d.off('active', active);
    // @ts-ignore
    meta2d.off('inactive', inactive);
    // @ts-ignore
    meta2d.off('scale', scaleListener);
    // @ts-ignore
    meta2d.off("add", lineAdd);
    meta2d.on("opened", openedListener);

    meta2d.off("undo", autoSave);
    meta2d.off("redo", autoSave);
    meta2d.off("add", autoSave);
    meta2d.off("delete", autoSave);
    meta2d.off("rotatePens", autoSave);
    meta2d.off("translatePens", autoSave);
    meta2d.off("components-update-value", autoSave);
    meta2d.destroy();
  }
});

let localSaveTimer: any = 0;
let saveTimer: any = 0;
const autoSave = () => {
  setDot(true);
  localSaveTimer && clearTimeout(localSaveTimer);
  localSaveTimer = setTimeout(() => {
    const data: Meta2dBackData = meta2d.data();
    let _localMeta2dDataName = data._id
      ? localMeta2dDataName + "-" + data._id
      : localMeta2dDataName;
    (data as any).localSaveAt = dayjs().format();
    localforage.setItem(_localMeta2dDataName, JSON.stringify(data));
    localSaveTimer = undefined;
  }, 3000);
  autoSaveServer();
};
//运行 在新标签页查看
function autoSaveServer() {
  //会员享受自动保存
  if (saveTimer) {
    return;
  }
  saveTimer = setTimeout(() => {
    const data: Meta2dBackData = meta2d.data();
    if (
      user &&
      user.id &&
      user.vipExpired &&
      data._id &&
      !data.component &&
      data.owner &&
      data.owner?.id === user.id
    ) {
      save(SaveType.Save);
    }
    saveTimer = null;
  }, 60000);
}

const inactive = () => {
  select();
};

const active = (pens: Pen[]) => {
  select(pens);

  //格式刷处理
  if (one.value || always.value) {
    meta2d.formatPainter();
    one.value = false;
  }
};

const one = ref(false);
const always = ref(false);

const oneFormat = () => {
  if (one.value) {
    one.value = false;
  } else {
    one.value = true;
    meta2d.setFormatPainter();
  }
  if (always.value) {
    always.value = false;
    one.value = false;
  }
};

const alwaysFormat = () => {
  always.value = true;
};

const clearFormat = () => {
  always.value = false;
  one.value = false;
  meta2d.clearFormatPainter();
};

const scale = ref(100);
function scaleListener(newScale: number) {
  scale.value = Math.round(newScale * 100);
}

const connectVisible = ref(false);
const connectShow = () => {
  connectVisible.value = true;
};

const currentLineType = ref('curve');
const lineTypes = reactive([
  { name: "曲线", icon: "#l-curve2", value: "curve" },
  { name: "线段", icon: "#l-polyline", value: "polyline" },
  { name: "直线", icon: "#l-line", value: "line" },
  { name: "脑图曲线", icon: "#l-mind", value: "mind" },
]);

const changeLineType = (value: string) => {
  currentLineType.value = value;
  if (meta2d) {
    meta2d.store.options.drawingLineName = value;
    meta2d.canvas.drawingLineName && (meta2d.canvas.drawingLineName = value);
    meta2d.store.active?.forEach((pen) => {
      meta2d.updateLineType(pen, value);
    });
  }
};

const fromArrow = ref("");
const fromArrows = [
  { icon: "#l-line", value: "" },
  { icon: "#l-from-triangle", value: "triangle" },
  { icon: "#l-from-diamond", value: "diamond" },
  { icon: "#l-from-circle", value: "circle" },
  { icon: "#l-from-lineDown", value: "lineDown" },
  { icon: "#l-from-lineUp", value: "lineUp" },
  { icon: "#l-from-triangleSolid", value: "triangleSolid" },
  { icon: "#l-from-diamondSolid", value: "diamondSolid" },
  { icon: "#l-from-circleSolid", value: "circleSolid" },
  { icon: "#l-from-line", value: "line" },
];
const toArrow = ref("");
const toArrows = [
  { icon: "#l-line", value: "" },
  { icon: "#l-to-triangle", value: "triangle" },
  { icon: "#l-to-diamond", value: "diamond" },
  { icon: "#l-to-circle", value: "circle" },
  { icon: "#l-to-lineDown", value: "lineDown" },
  { icon: "#l-to-lineUp", value: "lineUp" },
  { icon: "#l-to-triangleSolid", value: "triangleSolid" },
  { icon: "#l-to-diamondSolid", value: "diamondSolid" },
  { icon: "#l-to-circleSolid", value: "circleSolid" },
  { icon: "#l-to-line", value: "line" },
];

const changeFromArrow = (value: string) => {
  fromArrow.value = value;
  // 画布默认值
  meta2d.store.data.fromArrow = value;
  // 活动层的箭头都变化
  if (meta2d.store.active) {
    meta2d.store.active.forEach((pen: Pen) => {
      if (pen.type === PenType.Line) {
        pen.fromArrow = value;
        meta2d.setValue(
          {
            id: pen.id,
            fromArrow: pen.fromArrow,
          },
          {
            render: false,
          }
        );
      }
    });
    meta2d.render();
  }
};

const changeToArrow = (value: string) => {
  toArrow.value = value;
  // 画布默认值
  meta2d.store.data.toArrow = value;
  // 活动层的箭头都变化
  if (meta2d.store.active) {
    meta2d.store.active.forEach((pen: Pen) => {
      if (pen.type === PenType.Line) {
        pen.toArrow = value;
        meta2d.setValue(
          {
            id: pen.id,
            toArrow: pen.toArrow,
          },
          {
            render: false,
          }
        );
      }
    });
    meta2d.render();
  }
};

const oneD = ref<boolean>(false);
const alwaysD = ref<boolean>(false);
const oneDraw = () => {
  if (oneD.value) {
    oneD.value = false;
    if (!alwaysD.value) {
      // meta2d.finishDrawLine();
      // meta2d.drawLine();
      meta2d.store.options.disableAnchor =true;
    }
  } else {
    oneD.value = true;
    // meta2d.drawLine(meta2d.store.options.drawingLineName);
    meta2d.store.options.disableAnchor =false;
  }
  if (alwaysD.value) {
    // meta2d.finishDrawLine();
    // meta2d.drawLine();
    oneD.value = false;
    alwaysD.value = false;
    meta2d.store.options.disableAnchor =true;
  }
};
const alwaysDraw = () => {
  alwaysD.value = true;
  // meta2d.drawLine(meta2d.store.options.drawingLineName);
  meta2d.store.options.disableAnchor =false;
};

const lineAdd = (pens: Pen[]) => {
  if (pens.length === 1 && pens[0].name === 'line') {
    //连线类型
    if (oneD.value && !alwaysD.value) {
      if (meta2d.canvas.drawingLineName) {
        oneD.value = false;
        setTimeout(() => {
          // meta2d.finishDrawLine();
          // meta2d.drawLine();
          meta2d.store.options.disableAnchor =true;
        }, 100);
      }
    }
  }
};

const onAddShape = (event: DragEvent | MouseEvent, name: string) => {
  let data: any;
  if (name === 'text') {
    data = {
      text: 'text',
      width: 100,
      height: 20,
      name: 'text',
    };
  } else if (name === 'line') {
    data = {
      anchors: [
        { id: '0', x: 0, y: 0.5 },
        { id: '1', x: 1, y: 0.5 },
      ],
      width: 100,
      height: 1,
      name: 'line',
      lineName: 'line',
      type: 1,
    };
  }
  if (!(event as DragEvent).dataTransfer) {
    meta2d.canvas.addCaches = deepClone([data]);
  } else {
    (event as DragEvent).dataTransfer?.setData('Meta2d', JSON.stringify(data));
  }
  event.stopPropagation();
};

const isLock = ref(0);
function onLock() {
  !isLock.value && (isLock.value = 0);
  if (isLock.value === LockState.DisableMove) {
    isLock.value = LockState.None;
  } else {
    isLock.value++;
  }
  meta2d.lock(isLock.value);
  meta2d.hideInput();
}

const preview = async () => {
  meta2d.stopAnimate();
  // @ts-ignore
  const data: Meta2dBackData = meta2d.data();
  checkData(data);
  if (dot && user && data._id) {
    // 有 id ，是修改后保存
    await save(SaveType.Save);
  }
  if (!data._id) {
    await localforage.setItem(localMeta2dDataName, JSON.stringify(data));
  }
  router.push({
    path: '/preview',
    query: {
      r: Date.now() + '',
      id: data._id,
    },
  });
};
</script>
<style lang="postcss" scoped>
.meta2d {
  display: flex;
  flex-direction: column;
  background-color: var(--color-background-editor);
  border-left: 1px solid var(--color-border);

  .tools {
    display: flex;
    font-size: 12px;
    background-color: var(--color-background);
    height: 40px;
    flex-shrink: 0;
    padding: 0 12px;

    a {
      display: flex;
      align-items: center;
      height: 100%;
      padding: 0 10px;
      color: var(--color);
      text-decoration: none;
      .l-icon {
        width: 16px;
        height: 16px;
      }
      &:hover {
        color: var(--color-primary);
      }
    }

    .t-icon {
      font-size: 16px;
    }
  }

  #meta2d {
    border-top: 1px solid var(--color-background-input);
    height: calc(100vh - 81px);
    :deep(.meta2d-map){
      background: var(--color-background);
    }
  }
}
</style>
