<template>
  <div id="compBox">
    <!-- 组件弹窗 -->
    <div
      class="comp-list-drawer"
      :style="getDrawerStyle"
      ondragover="return false"
    >
      <div class="drawer-title">{{ selectedMenu?.name }}</div>
      <Collapse
        :bordered="false"
        style="border-radius: 0"
        v-if="selectedMenu?.isGroup"
      >
        <CollapsePanel
          class="custom-collapse-panel"
          v-for="group in getList"
          :key="group.name"
          :header="group.name"
        >
          <Space :size="4" wrap>
            <div
              class="comp-item"
              v-for="item in group.children"
              :key="item.name"
              @click="handleAddComp(item)"
            >
              <img
                :src="item.icon"
                draggable="true"
                @dragstart="handleDragStart(item)"
                @dragend="handleDragEnd"
              />
              <div class="comp-name">{{ item.name }}</div>
            </div>
          </Space>
        </CollapsePanel>
      </Collapse>
      <div class="comp-box" v-else>
        <Space :size="4" wrap>
          <div
            class="comp-item"
            v-for="item in getList"
            :key="item.name"
            @click="handleAddComp(item)"
          >
            <img
              :src="item.icon"
              draggable="true"
              @dragstart="handleDragStart(item)"
              @dragend="handleDragEnd"
            />
            <div class="comp-name">{{ item.name }}</div>
          </div>
        </Space>
      </div>
    </div>

    <Layout style="height: 100%">
      <LayoutSider
        collapsible
        v-model:collapsed="collapsed"
        :collapsed-width="60"
        style="background: #f7fafc"
        width="100"
      >
        <Menu
          theme="light"
          @click="handleMenuClick"
          v-model:selected-keys="selectedKeys"
          class="comp-menu"
        >
          <MenuItem v-for="item in compSetting.compList" :key="item.type">
            <component :is="item.icon" />
            <span>{{ item.name }}</span>
          </MenuItem>
        </Menu>
        <div class="layer-btn">
          <div class="cus-btn" @click="stageStore.toggleShowLayer">
            <DiffOutlined/><span v-show="!collapsed">组件图层</span>
          </div>
        </div>
      </LayoutSider>
    </Layout>
  </div>
</template>

<script setup lang="ts">
import { ref, computed, watch } from "vue";
import type { Ref } from "vue";
import {
  LayoutSider,
  Layout,
  Menu,
  MenuItem,
  Collapse,
  CollapsePanel,
  Space,
} from "ant-design-vue";
import { compSetting } from "@/config/compSetting";
import type { CompCategory, CompItem } from "@/config/compSetting";
import { useEventListener } from "@vueuse/core";
import { useProjectStore } from "@/store/modules/project";
import { useStageStore } from "@/store/modules/stage";
import { DiffOutlined } from "@ant-design/icons-vue";
import { uuid } from "@/utils";

const projectStore = useProjectStore();
const stageStore = useStageStore();
const openDrawer: Ref<boolean> = ref(false); // 抽屉显示
const collapsed: Ref<boolean> = ref(false); // 菜单折叠
const selectedMenu: Ref<CompCategory | undefined> = ref(); // 选中菜单
const selectedKeys: Ref<string[]> = ref([]); // 选中菜单key
// 抽屉样式
const getDrawerStyle = computed(() => {
  const openLeft = collapsed.value ? "64px" : "104px";
  return {
    left: openDrawer.value ? openLeft : "-500%",
    Transition: "0.5s ease",
  };
});
// 获取选中组件列表
const getList = computed(() => {
  return selectedMenu.value?.children || [];
});

let timer: number;
watch(
  () => openDrawer.value,
  (val) => {
    if (!val) {
      timer = setTimeout(() => {
        selectedMenu.value = undefined;
      }, 500);
    } else {
      clearTimeout(timer);
    }
  }
);

useEventListener(document, "click", (e) => {
  if (
    openDrawer.value &&
    !e?.target?.closest(".comp-list-drawer") &&
    !e?.target?.closest(".comp-menu")
  ) {
    openDrawer.value = false;
    selectedKeys.value = [];
  }
});

// 点击菜单
const handleMenuClick = (e: any) => {
  const menu = compSetting.compList.find((item) => item.type === e.key);
  if (selectedMenu.value?.type === e.key) {
    openDrawer.value = false;
    selectedKeys.value = [];
  } else {
    openDrawer.value = true;
  }
  selectedMenu.value = menu;
};
// 点击组件时 直接添加组件到中心位置
const handleAddComp = (item: CompItem) => {
  selectedKeys.value = [];
  openDrawer.value = false;
  const compData = {
    key: uuid(),
    name: item.name,
    componentType: item.componetName,
    container: {
      props: {
        x: stageStore.width / 2,
        y: stageStore.height / 2,
      },
    },
  };

  projectStore.addElement(compData, 'center');
};
// 拖拽添加组件方式
// 1、拖拽开始时记录要添加的对象
// 2、拖拽到画布区域时通过drop事件完成添加组件
// 3、清空临时数据
const handleDragStart = (item: CompItem) => {
  openDrawer.value = false;
  selectedKeys.value = [];

  projectStore.setAddCompData({
    key: uuid(),
    name: item.name,
    componentType: item.componetName,
    container: {
      props: {
        x: 0,
        y: 0,
      },
    },
  });
};
// 拖拽结束 清空临时数据
const handleDragEnd = () => {
  projectStore.clearAddCompData();
};
</script>

<style lang="less" scoped>
#compBox {
  height: 100%;
}
.comp-list-drawer {
  transition: 0.5s ease;
  position: absolute;
  width: 200px;
  height: calc(100% - 16px);
  top: 8px;
  left: -500%;
  border-radius: 4px;
  background-color: #fff;
  box-shadow: -6px 0 16px 0 rgba(0, 0, 0, 0.08),
    -3px 0 6px -4px rgba(0, 0, 0, 0.12), -9px 0 28px 8px rgba(0, 0, 0, 0.05);
  .drawer-title {
    background: @bg-color;
    line-height: 32px;
    font-size: 14px;
    padding: 0 12px;
  }

  .custom-collapse-panel {
    border-radius: 0;
    background: #fff;
    :deep(.ant-collapse-header) {
      padding: 4px 16px;
      border-bottom: solid 1px #f0f0f0;
      background: @bg-color;
      font-size: 13px;
    }
    :deep(.ant-collapse-content-box) {
      padding: 16px;
      padding-bottom: 24px;
    }
  }
}
.comp-box {
  padding: 16px;
}
.comp-item {
  text-align: center;
  font-size: 12px;
  cursor: pointer;
  &:hover {
    img {
      border: solid 1px #1677ff;
    }
  }
  img {
    width: 80px;
    height: 54px;
    object-fit: contain;
    border: solid 1px #fff;
  }
}

:deep(.ant-menu-light) {
  background: none;

  .ant-menu-item:not(.ant-menu-item-selected):hover {
    background: #eff8ff;
  }
  .ant-menu-item {
    width: 100%;
    border-radius: 0;
    margin-inline: 0;
    &:not(.ant-menu-item-selected) {
      color: #666;
    }
  }
  .ant-menu-item-selected {
    position: relative;
  }
  .ant-menu-item-selected::before {
    content: "";
    position: absolute;
    left: 0;
    top: 0;
    height: 100%;
    border-left: 3px solid #1890ff;
  }
}
:deep(.ant-layout-sider-trigger) {
  background: none;
  color: #666;
}
.layer-btn {
  position: absolute;
  bottom: 50px;
  width: 100%;
  text-align: center;
  font-size: 12px;
  color: #666;
  border-top: solid 1px #f0f0f0;
  border-bottom: solid 1px #f0f0f0;
  padding: 12px 0;
  .cus-btn {
    cursor: pointer;
  }
}
</style>
