<template>
  <div class="graphics">
    <div class="input-search">
      <div class="btn">
        <t-icon name="search" />
      </div>
      <t-input placeholder="搜索" />
    </div>
    <div class="groups-panel">
      <div class="groups">
        <div
          v-for="group in groups"
          :class="group.name === activedGroup ? 'active' : ''"
          @click="groupChange(group.name)"
        >
          <t-icon :name="group.icon" />
          {{ group.name }}
        </div>
      </div>
      <div class="list" :class="groupType ? 'two-list' : ''">
        <t-collapse v-model:value="activedPanel" @change="onChangeGroupPanel">
          <t-collapse-panel
            :value="item.name"
            :header="item.name"
            v-for="item in subGroups"
            :key="item.name"
          >
            <div v-if="item.loading">
              <t-loading
                text="加载中..."
                size="small"
                style="margin-left: 32px; margin-bottom: 4px"
              />
            </div>
            <template v-else>
              <div
                class="graphic"
                v-for="elem in item.list"
                :draggable="!groupType || groupType >= 10"
                @dragstart="dragStart($event, elem)"
                @drag="drag($event, elem)"
                @dragend="dragEnd()"
                @click.stop="dragStart($event, elem)"
                @dblclick.stop="open(elem)"
              >
                <t-image v-if="elem.image" :src="elem.image" />
                <div class="svg-box" v-else-if="elem.svg" v-html="elem.svg" />
                <svg v-else class="l-icon" aria-hidden="true">
                  <use :xlink:href="'#' + elem.icon"></use>
                </svg>
                <p :title="elem.name">{{ elem.name }}</p>
                <div class="price" v-if="elem.price > 0">
                  ￥{{ elem.price }}
                </div>
              </div>
              <div
                v-if="!item.list || !item.list.length"
                class="gray center"
                style="white-space: nowrap; margin-left: 32px"
              >
                暂无数据，待更新
              </div>
            </template>
          </t-collapse-panel>
        </t-collapse>
      </div>
    </div>
  </div>
</template>

<script lang="ts" setup>
import { onMounted, onUnmounted, reactive, ref, watch } from 'vue';
import { useRouter } from 'vue-router';
import axios from 'axios';

import { cases, shapes, charts, formComponents } from '@/services/defaults';
import { getPngFolders, getPngs } from '@/services/png';
import { getIconFolders, getIcons } from '@/services/icons';
import { getComponents, getComponentsList, getLe5leV } from '@/services/api';
import { convertPen } from '@/services/upgrade';
import { deepClone } from '@meta2d/core';
import { isGif } from '@/services/utils';
import { autoSave, delAttrs } from '@/services/common';

const router = useRouter();

const activedGroup = ref('图形');

const groups = reactive([
  {
    icon: 'desktop',
    name: '场景',
    key: '',
  },
  {
    icon: 'root-list',
    name: '模板',
    key: '',
  },
  {
    icon: 'chart',
    name: '图表',
    key: 'chart',
  },
  {
    icon: 'control-platform',
    name: '控件',
    key: '',
  },
  {
    icon: 'image',
    name: '素材',
    key: '',
  },
  {
    icon: 'file-icon',
    name: '图标',
    key: '',
  },
  {
    icon: 'chart-bubble',
    name: '图形',
    key: 'shape',
  },
  {
    icon: 'app',
    name: '我的',
    key: '',
  },
]);
const subGroups = ref<any[]>([]);
const groupType = ref(0);
const activedPanel = ref([]);

const templates = reactive<any>({});
const materials = reactive([]);
const icons = reactive([]);

const groupChange = async (name: string) => {
  activedPanel.value = [];
  activedGroup.value = name;
  groupType.value = 0;
  switch (name) {
    case '场景':
      groupType.value = 1;
      subGroups.value = cases;
      subGroups.value[0].loading = true;
      if (!templates[name + cases[0].name]) {
        templates[name + cases[0].name] = await getCaseProjects(
          name,
          cases[0].name
        );
      }
      subGroups.value[0].list = templates[name + cases[0].name];
      subGroups.value[0].loading = false;
      break;
    case '模板':
      groupType.value = 2;
      subGroups.value = cases;
      subGroups.value[0].loading = true;
      if (!templates[name + cases[0].name]) {
        templates[name + cases[0].name] = await getCaseProjects(
          name,
          cases[0].name
        );
      }
      subGroups.value[0].list = templates[name + cases[0].name];
      subGroups.value[0].loading = false;
      break;
    case '图表':
      subGroups.value = charts;
      break;
    case '控件':
      subGroups.value = formComponents;
      break;
    case '素材':
      if (!materials.length) {
        materials.push(...(await getPngFolders()));
      }
      subGroups.value = materials;
      break;
    case '图标':
      if (!icons.length) {
        icons.push(...(await getIconFolders()));
      }
      subGroups.value = icons;
      break;
    case '图形':
      subGroups.value = shapes;
      break;
    case '我的':
      subGroups.value = await getPrivateCommponents();
      groupType.value = 10;
      break;
  }
  activedPanel.value = [subGroups.value[0].name];
};

const getCaseProjects = async (name: string, group: string) => {
  const ret: any = await axios.post(
    '/api/data/le5leV/list?current=1&pageSize=1000',
    {
      query: { tags: name, case: group },
      shared: 'true',
      projection: { _id: 1, name: 1, image: 1, price: 1 },
    }
  );

  if (!ret) {
    return [];
  }
  return ret.list;
};

const getPrivateCommponents = async () => {
  const data = {
    projection: {
      image: 1,
      _id: 1,
      name: 1,
      folder: 1,
      component: 1,
    },
  };
  const config = {
    params: {
      current: 1,
      pageSize: 100,
    },
  };
  const res: any = await getComponentsList(data, config);
  const folderMap: any = {};
  res.list?.map((item: any) => {
    if (!folderMap[item.folder]) {
      folderMap[item.folder] = [];
    }

    folderMap[item.folder].push(item);
  });
  let list = [];
  for (let key in folderMap) {
    list.push({
      name: key === 'undefined' ? '未分类' : key,
      show: true,
      list: folderMap[key],
    });
  }

  return list;
};

watch(
  () => activedPanel.value,
  async (newV: any[], oldV: any[]) => {
    const newOpen: any = [];
    for (let v of newV) {
      !oldV.includes(v) && newOpen.push(v);
    }
    if (newOpen.length === 0) {
      return;
    }
    if (activedGroup.value === '素材') {
      const data: any = materials.find((item) => item.name === newOpen[0]);
      if (!data.list || data.list.length === 0) {
        data.list = await getPngs(
          globalThis.folderJson ? data.pinyin : data.name
        );
        subGroups.value = deepClone(materials);
      }
    } else if (activedGroup.value === '图标') {
      const data: any = icons.find((item) => item.name === newOpen[0]);
      if (!data.list || data.list.length === 0) {
        data.list = await getIcons(
          globalThis.folderJson ? data.pinyin : data.name
        );
        subGroups.value = deepClone(icons);
      }
    }
  }
);

const dragStart = async (event: DragEvent | MouseEvent, item: any) => {
  if (
    (groupType.value > 0 && groupType.value < 10) ||
    !item ||
    (event instanceof DragEvent && !event.dataTransfer)
  ) {
    return;
  }
  let data = null;
  if (item._id && !item.componentDatas) {
    let res: any = await getComponents(item._id);
    item.component = true;
    item.componentDatas = res.componentDatas;
    item.componentData = res.componentData;
  }
  if (!item.data && !item.component && item.image) {
    let target: any = event.target;
    target.children[0] && (target = target.children[0].children[0]);
    // firefox naturalWidth svg 图片 可能是 0
    const normalWidth = target.naturalWidth || target.width;
    const normalHeight = target.naturalHeight || target.height;
    const [name, lockedOnCombine] = isGif(item.image)
      ? ['gif', 0]
      : ['image', undefined];

    data = {
      name,
      width: 100,
      height: 100 * (normalHeight / normalWidth),
      image: item.image,
      imageRatio: true,
      lockedOnCombine,
    };
  } else if (item.component) {
    if (item.componentData) {
      const pens = convertPen([item.componentData]);
      data = deepClone(pens);
    } else if (item.componentDatas) {
      data = deepClone(item.componentDatas);
    }
  } else {
    data = item.componentDatas || item.data;
  }
  if (event instanceof DragEvent) {
    meta2d.canvas.addCaches = [];
    event.dataTransfer?.setData('Meta2d', JSON.stringify(data));
  } else {
    if (!Array.isArray(data)) {
      data = deepClone([data]);
    }
    meta2d.canvas.addCaches = data;
  }
  event.stopPropagation();
};

const drag = (event: DragEvent, item: any) => {};

const dragEnd = () => {};

const dragstart = (event: any) => {
  event.target.style.opacity = 0.5;
};

const dragend = (event: any) => {
  event.target.style.opacity = 1;
};

const open = async (item: any) => {
  autoSave();
  router.push({
    path: '/',
    query: {
      r: Date.now() + '',
    },
  });

  const ret: any = await getLe5leV(item._id || item.id);
  for (const k of delAttrs) {
    delete (ret as any)[k];
  }
  meta2d.open(ret);
};

const onChangeGroupPanel = async (val: string[]) => {
  if (groupType.value > 0 && groupType.value < 10 && val?.length) {
    for (const name of val) {
      if (
        !templates[activedGroup.value + name] ||
        !templates[activedGroup.value + name].length
      ) {
        for (const item of subGroups.value) {
          if (item.name === name) {
            item.loading = true;
          }
        }
        templates[activedGroup.value + name] = await getCaseProjects(
          activedGroup.value,
          name
        );
        for (const item of subGroups.value) {
          if (item.name === name) {
            item.list = templates[activedGroup.value + name];
            item.loading = false;
          }
        }
      }
    }
  }
};

onMounted(() => {
  groupChange('场景');
  document.addEventListener('dragstart', dragstart, false);
  document.addEventListener('dragend', dragend, false);
});

onUnmounted(() => {
  document.removeEventListener('dragstart', dragstart);
  document.removeEventListener('dragend', dragend);
});
</script>
<style lang="postcss" scoped>
.graphics {
  display: flex;
  flex-direction: column;

  .input-search {
    flex-shrink: 0;
    height: 40px;
  }

  .groups-panel {
    display: grid;
    grid-template-columns: 50px 1fr;
    border-top: 1px solid var(--color-background-input);
    flex-grow: 1;
    overflow-y: auto;
    font-size: 12px;

    .groups {
      & > div {
        display: flex;
        flex-direction: column;
        align-items: center;
        padding: 16px 4px;
        line-height: 1;
        cursor: pointer;

        .t-icon {
          font-size: 20px;
          margin-bottom: 8px;
        }

        &:hover {
          color: var(--color-primary);
        }
      }

      .active {
        background-color: var(--color-background-active);
        color: var(--color-primary);
        border-left: 2px solid var(--color-primary);
      }
    }

    .list {
      overflow-y: auto;
      max-height: calc(100vh - 100px);
      background-color: var(--color-background-active);
      padding-top: 8px;

      * {
        background-color: var(--color-background-active);
      }

      :deep(.t-collapse) {
        border: none;
      }
      :deep(.t-collapse-panel__header) {
        border: none;
        font-size: 12px;
        font-weight: 400;
        padding: 8px 16px;
        &:hover {
          color: var(--color-primary);
        }
      }

      :deep(.t-collapse-panel__body) {
        border: none;
      }
      :deep(.t-collapse-panel__content) {
        background-color: var(--color-background-active);
        padding: 4px 4px 20px 4px;
        display: grid;
        grid-template-columns: 1fr 1fr 1fr;
        grid-row-gap: 20px;
      }
      .graphic {
        position: relative;

        &:hover {
          cursor: pointer;
          color: var(--color-primary-hover);
          svg {
            color: var(--color-primary-hover);
          }
        }
        p {
          text-align: center;
          font-size: 12px;
          height: 12px;
          line-height: 1;
          overflow: hidden;
          text-overflow: ellipsis;
          display: -webkit-box;
          -webkit-line-clamp: 1;
          word-break: break-all;
          -webkit-box-orient: vertical;
        }
        .t-image__wrapper {
          height: 32px;
          width: 32px;
          background: #fff0;
          margin-left: calc(50% - 16px);
          margin-top: 10px;
          margin-bottom: 10px;
          :deep(.t-image) {
            border-radius: 2px;
          }
        }

        svg {
          color: var(--color);
          height: 32px;
          width: 100%;
          margin: 4px 0px;
        }

        .svg-box {
          height: 32px;
          width: 32px;
          margin-left: calc(50% - 16px);
          margin-top: 10px;
          margin-bottom: 10px;
          &:deep(svg) {
            height: 100%;
            width: 100%;
            .cls-1 {
              stroke: var(--color) !important;
            }
          }
        }

        .price {
          position: absolute;
          top: 8px;
          right: 8px;
          display: inline-block;
          z-index: 1;
          border-radius: 2px;
          background-color: #ff400060;
          color: var(--color-bland);
          font-size: 10px;
          line-height: 1;
          padding: 3px;
        }
      }
    }

    .two-list {
      :deep(.t-collapse-panel__content) {
        padding: 0 8px;
        grid-template-columns: 116px 116px;
      }
      .graphic {
        p {
          margin-top: 10px;
          margin-bottom: 12px;
        }
        .t-image__wrapper {
          width: 88px;
          height: 88px;
          margin-left: 14px;
        }
      }
    }
  }
}
</style>
