<template>
  <Modal
    width="800px"
    title="添加场景"
    :visible="visible"
    @ok="okHandler"
    @cancel="visible = false"
    okText="确定"
    cancelText="取消"
    class="model-table"
  >
    <div>
      <div className="model-header">
        <p class="header-desc">
          已选择数据<span>（ {{ rowSelection.selectedRowKeys.length }} ）</span>
        </p>
        <Search
          className="content-header-search"
          placeholder="输入名称搜索"
          v-model:value="keyword"
          allow-clear
          style="width: 244px"
        />
      </div>
      <div class="table-layout" v-if="origin.length">
        <Tabs v-model:activeKey="type">
          <TabPane v-for="current in types" :key="current" :tab="current">
            <Table
              v-if="typeFilterScenes[current].length"
              :row-key="(record: Scene) => record.modelId"
              :columns="cloumns"
              :rowSelection="rowSelection"
              :data-source="typeFilterScenes[current]"
              :pagination="false"
            />
            <div style="padding: 1px" v-else>
              <Empty
                description="暂无搜索结果"
                :image="Empty.PRESENTED_IMAGE_SIMPLE"
                className="ant-empty ant-empty-normal"
              />
            </div>
          </TabPane>
        </Tabs>
      </div>
      <div style="padding: 1px" v-else>
        <Empty
          :description="keyword.length ? '暂无搜索结果' : '暂无结果'"
          :image="Empty.PRESENTED_IMAGE_SIMPLE"
          className="ant-empty ant-empty-normal"
        />
      </div>
    </div>
  </Modal>

  <div class="slot-layout">
    <Dropdown placement="bottom">
      <slot></slot>
      <template #overlay>
        <Menu>
          <MenuItem @click="visible = true">场景管理</MenuItem>
          <MenuItem @click="selectModel">媒体库</MenuItem>
        </Menu>
      </template>
    </Dropdown>
  </div>
</template>

<script lang="ts" setup>
import {
  Modal,
  Input,
  Table,
  Empty,
  Tabs,
  TabPane,
  Dropdown,
  Menu,
  MenuItem,
} from "ant-design-vue";
import { computed, nextTick, ref, watch, watchEffect } from "vue";
import { scenes, save, SceneTypeDesc } from "@/store";
import { asyncTimeout, createLoadPack, diffArrayChange } from "@/utils";
import {
  fuseModels,
  createFuseModels,
  addFuseModel,
  fuseModelsLoaded,
  initialScenes,
} from "@/store";

import { SceneType, uploadMaterialToModel, type Scene } from "@/api";
import { activeModel, getSceneModel } from "@/sdk";
import { selectMaterials } from "@/components/materials/quisk";
import { custom } from "@/env";
import { actionItems, currentItem } from "@/views/merge";

type Key = Scene["modelId"];

const Search = Input.Search;

const selectIds = computed(() => fuseModels.value.filter(item => item.type !== SceneType.SWMX).map((item) => item.modelId));
const visible = ref(false);
const keyword = ref("");
const SceneGroupTypeDesc: any = {
  [SceneType.SWKK]: 'Mesh场景',
  [SceneType.SWKJ]: 'Mesh场景',
  [SceneType.SWSS]: '点云场景',
  [SceneType.SWSSMX]: 'Mesh场景',
  [SceneType.SWYDSS]: '点云场景',
  [SceneType.SWYDMX]: 'Mesh场景',
  [SceneType.DSFXJ]: 'Mesh场景'
}

const origin = computed(() =>
  scenes.value.filter(scene => scene.type !== SceneType.SWMX).map((scene) => ({
    ...scene,
    createTime: scene.createTime.substr(0, 16),
    type: SceneGroupTypeDesc[scene.type],
  }))
);

const typeFilterScenes = computed(() => {
  const typeScenes: any = {};
  for (const type of types.value) {
    typeScenes[type] = origin.value
      .filter((item) => item.name && item.modelId && item.name.includes(keyword.value))
      .filter((item) => item.type === type);
  }
  return typeScenes;
});

const types = computed(() => [
  ...new Set(origin.value.map((item) => item.type)).values(),
]);
const type = ref(types.value[0]);
const cache = {} as any

const selects = ref<Key[]>(selectIds.value);
const rowSelection: any = ref({
  selectedRowKeys: selects,
  onChange: (ids: number[]) => {
    ids = ids.filter(id => !selectIds.value.includes(id))
    cache[type.value] = ids
    const curIds = [...selectIds.value]
    for (const key in cache) {
      curIds.push(...cache[key])
    }
    selects.value = curIds
  },
  getCheckboxProps: (record: Scene) => ({
    disabled: selectIds.value.includes(record.modelId),
  }),
});
const cloumns = [
  {
    width: "400px",
    title: "名称",
    dataIndex: "name",
    key: "name",
  },
  {
    title: "类型",
    dataIndex: "type",
    key: "type",
  },
  {
    title: "拍摄/创建时间",
    dataIndex: "createTime",
    key: "createTime",
  },
];

const addModelHandler = createLoadPack(async (modelIds: number[]) => {
  const models = modelIds.map((modelId) => createFuseModels({ modelId }));
  const addPromises = models.map(addFuseModel);

  const addModels = await Promise.all(addPromises);
  await new Promise<void>((resolve) => {
    nextTick(() => {
      const stop = watchEffect(() => {
        if (fuseModelsLoaded.value) {
          nextTick(() => {
            stop();
            resolve();
          });
        }
      });
    });
  });
  models.forEach((model) => {
    if (getSceneModel(model)) {
      model.rotation = getSceneModel(model)!.getDefaultRotation();
    }
  });
  await asyncTimeout(100);
  await save();

  activeModel({ showMode: 'fuse', active: addModels[addModels.length - 1] })
  // custom.currentModel = addModels[addModels.length - 1]
  currentItem.value = actionItems[0]
});

const okHandler = createLoadPack(async () => {
  console.log(selects.value);
  const models = selects.value.filter(
    (modelId) => !fuseModels.value.some((model) => model.modelId === modelId)
  );
  await addModelHandler(models);
  visible.value = false;
});

watch(visible, (visible, oldvisible) => {
  if (visible !== oldvisible) {
    keyword.value = "";
    selects.value = selectIds.value;
    visible && initialScenes();
  }
});

const selectModel = async () => {
  const list = await selectMaterials({
    uploadFormat: ["zip"],
    format: ["obj", "ply", "las", "laz", "b3dm", "shp", "osgb", "glb"],
    maxSize: 2 * 1024 * 1024 * 1024,
  });
  if (!list?.length) return;

  const modelList = await Promise.all(list.filter(item => item.uploadId).map(item => uploadMaterialToModel(item.uploadId!)))
  const modelIds = modelList
    .map((item) => item.modelId!)
    .filter(
      (modelId) => modelId && !fuseModels.value.some((model) => model.modelId === modelId)
    );
  await addModelHandler(modelIds);
};
</script>

<style lang="less" scoped>
.model-header {
  display: flex;
  justify-content: space-between;
  padding-bottom: 24px;
  align-items: center;
}

.table-layout {
  max-height: 500px;
  overflow-y: auto;
}
.slot-layout {
  display: flex;
  align-items: center;
  height: 100%;
}
</style>

<style lang="less">
.model-header .header-desc {
  margin-bottom: 0;
}

.ant-modal-root .ant-table-tbody > tr > td {
  word-break: break-all;
}
</style>
