<template>
  <div class="elements">
    <div class="title" style="margin: 8px 0 0 12px">图纸结构</div>
    <t-tree
      class="flex-grow"
      ref="tree"
      :data="data.tree"
      v-model:actived="data.actived"
      activable
      :expand-parent="true"
      @active="onActive"
      style="padding: 0 4px 8px 0"
    >
      <template #label="{ node }: any">
        <div class="flex middle" :class="{ gray: node.data.visible === false }">
          <template v-if="node.getChildren()">
            <t-icon v-if="node.expanded" name="folder-open" />
            <t-icon v-else name="folder" />
          </template>
          <t-icon v-else name="control-platform" />

          <t-input
            v-if="node.data.edited"
            v-model="node.data.label"
            :autofocus="true"
            @blur="onDescription(node)"
            @enter="onDescription(node)"
          />
          <span v-else @dblclick="node.data.edited = true">
            {{ node.label }}
          </span>
        </div>
      </template>
      <template #operations="{ node }: any">
        <div
          class="flex middle operations"
          :class="{
            gray: node.data.visible === false,
            show: node.data.visible === false || node.data.locked,
          }"
          style="width: 36px; height: 16px"
        >
          <t-tooltip
            class="mr-4"
            v-if="!node.data.locked"
            content="可编辑"
            placement="top"
          >
            <t-icon name="lock-off" @click="lock(node, 1)" />
          </t-tooltip>
          <t-tooltip
            class="mr-4"
            v-else-if="node.data.locked == 1"
            content="禁止编辑"
            placement="top"
          >
            <t-icon name="lock-on" @click="lock(node, 2)" />
          </t-tooltip>
          <t-tooltip
            class="mr-4"
            v-else-if="node.data.locked == 2"
            content="禁止编辑和移动"
            placement="top"
          >
            <svg class="l-icon" aria-hidden="true" @click="lock(node, 10)">
              <use xlink:href="#l-wufayidong"></use>
            </svg>
          </t-tooltip>
          <t-tooltip
            class="mr-4"
            v-else-if="node.data.locked == 10"
            content="禁止所有事件"
            placement="top"
          >
            <svg class="l-icon" aria-hidden="true" @click="lock(node, 0)">
              <use xlink:href="#l-jinyong"></use>
            </svg>
          </t-tooltip>

          <t-icon
            v-if="node.data.visible !== false"
            name="browse"
            @click="visible(node, false)"
          />
          <t-icon v-else name="browse-off" @click="visible(node, true)" />
        </div>
      </template>
    </t-tree>
    <div class="groups" style="padding: 8px 0">
      <div class="flex middle between" style="padding: 0 12px">
        <div class="title">图层</div>
        <a @click="addLayer"> +新建图层</a>
      </div>
      <div class="layers">
        <div
          v-for="(item, i) in data.layers"
          class="flex middle between hover"
          :class="{ primary: i == data.activedLayer }"
        >
          <span
            class="flex-grow"
            v-if="i != data.editedLayer"
            @click="activeLayer(i)"
            @dblclick="
              data.activedLayer = data.editedLayer = i;
              data.layer = item;
            "
          >
            {{ item }}
          </span>
          <t-input
            v-else
            v-model="data.layer"
            :autofocus="true"
            @blur="setLayer"
            @enter="setLayer"
          />
          <t-popconfirm
            content="确认删除该图层吗？"
            @confirm="delLayer"
            @cancel="data.deleteLayer = undefined"
          >
            <t-icon
              name="delete"
              class="ml-8"
              :class="{ block: i == data.deleteLayer }"
              @click="data.deleteLayer = i"
            />
          </t-popconfirm>
        </div>
      </div>
    </div>
  </div>
</template>

<script lang="ts" setup>
import { onBeforeMount, onBeforeUnmount, reactive, ref } from 'vue';
import { LockState, Pen } from '@meta2d/core';
import { MessagePlugin } from 'tdesign-vue-next';

const tree = ref<any>(null);
const data = reactive<any>({
  tree: [],
  actived: [],
  layers: [],
});

onBeforeMount(() => {
  meta2d.on('opened', getTree);
  meta2d.on('add', getTree);
  meta2d.on('undo', getTree);
  meta2d.on('redo', getTree);
  meta2d.on('delete', getTree);
  meta2d.on('combine', getTree);

  getTree();

  const d = meta2d.store.data as any;
  if (!d.layers) {
    d.layers = [];
  }
  data.layers = d.layers;
});

const getTree = () => {
  data.tree = [];
  for (const item of meta2d.store.data.pens) {
    if (item.parentId) {
      continue;
    }
    const elem = calcElem(item);
    elem && data.tree.push(elem);
  }
};

const calcElem = (node: Pen) => {
  if (!node) {
    return;
  }

  const elem: any = {
    label: (node as any).description || node.name,
    value: node.id,
    locked: node.locked,
    visible: node.visible,
  };

  if (!node.children) {
    return elem;
  }

  elem.children = [];
  for (const id of node.children) {
    const child = calcElem(meta2d.store.pens[id]);
    child && elem.children.push(child);
  }

  return elem;
};

const onActive = (value: string[]) => {
  if (!value.length) {
    return;
  }

  const pens: Pen[] = [];
  for (const item of meta2d.store.data.pens) {
    for (const v of value) {
      if (item.id === v) {
        pens.push(item);
      }
    }
  }
  meta2d.active(pens, false);
  meta2d.render();
};

const lock = (node: any, v: LockState) => {
  node.data.locked = v;
  meta2d.setValue({
    id: node.value,
    locked: v,
  });
};

const visible = (node: any, v: boolean) => {
  node.data.visible = v;
  setChildrenVisible(node, v);
  const pen = meta2d.findOne(node.value);
  pen && meta2d.setVisible(pen, v);
};

const setChildrenVisible = (node: any, v: boolean) => {
  const children = node.getChildren();
  if (children && children.length > 0) {
    for (const child of children) {
      child.data.visible = v;
      setChildrenVisible(child, v);
    }
  }
};

const onDescription = (node: any) => {
  node.data.edited = false;
  node.setData({ label: node.data.label });
  meta2d.setValue({
    id: node.value,
    description: node.data.label,
  });
};

const addLayer = () => {
  const i = data.layers.length + 1;
  data.layer = '图层' + i;
  data.layers.push(data.layer);
  data.activedLayer = data.editedLayer = i;
};

const activeLayer = (i: number) => {
  data.activedLayer = i;
  const layer = data.layers[i];
  const pens: Pen[] = [];
  for (const item of meta2d.store.data.pens) {
    // @ts-ignore
    if (item.layer === layer) {
      pens.push(item);
    }
  }
  meta2d.active(pens, false);
  meta2d.render();
};

const setLayer = () => {
  if (data.layers[data.editedLayer] === data.layer) {
    data.editedLayer = undefined;
    return;
  }

  if (data.layers.includes(data.layer)) {
    MessagePlugin.error('已经存在相同图层！');
    return;
  }

  for (const item of meta2d.store.data.pens) {
    // @ts-ignore
    if (item.layer === data.layers[data.editedLayer]) {
      // @ts-ignore
      item.layer === data.layer;
    }
  }

  data.layers[data.editedLayer] = data.layer;
  data.editedLayer = undefined;
};

const delLayer = () => {
  for (const item of meta2d.store.data.pens) {
    // @ts-ignore
    if (item.layer === data.layers[data.deleteLayer]) {
      // @ts-ignore
      delete item.layer;
    }
  }
  data.layers.splice(data.deleteLayer, 1);
  data.deleteLayer = undefined;
};

onBeforeUnmount(() => {
  meta2d.off('opened', getTree);
  meta2d.off('add', getTree);
  meta2d.off('undo', getTree);
  meta2d.off('redo', getTree);
  meta2d.off('delete', getTree);
  meta2d.off('combine', getTree);
});
</script>
<style lang="postcss" scoped>
.elements {
  display: flex;
  flex-direction: column;
  height: 100%;

  & > * {
    overflow-y: auto;
    width: 100%;
  }

  .groups {
    flex-shrink: 0;
    height: 240px;
    border-top: 1px solid var(--color-border-input);
    padding: 8px 12px;
  }

  .layers {
    height: calc(100% - 24px);
    overflow-y: auto;
    padding: 0 12px 16px 12px;
    & > div {
      height: 30px;
      line-height: 30px;

      svg {
        display: none;
        &.block {
          display: block;
        }
      }

      &:hover {
        svg {
          display: block;
        }
      }
    }
  }
}
</style>
