<template>
  <Modal
    width="800px"
    :title="$t('scene.add')"
    :visible="visible"
    @ok="okHandler"
    @cancel="visible = false"
    :okText="$t('sys.enter')"
    :cancelText="$t('sys.cancel')"
    class="model-table"
  >
    <div>
      <div className="model-header">
        <p class="header-desc">
          {{ $t("material.selectCount")
          }}<span>（ {{ rowSelection.selectedRowKeys.length }} ）</span>
        </p>
        <Search
          className="content-header-search"
          :placeholder="$t('material.search')"
          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.num"
              :columns="cloumns"
              :rowSelection="rowSelection"
              :data-source="typeFilterScenes[current]"
              :pagination="{ ...params, current: params.pageNum }"
              @change="handleTableChange"
            />
            <div style="padding: 1px" v-else>
              <Empty
                :description="$t('sys.unSearchData')"
                :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 ? $t('sys.unSearchData') : $t('sys.undata')"
          :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">{{ $t("scene.manage") }}</MenuItem>
          <MenuItem @click="selectModel">{{ $t("material.name") }}</MenuItem>
        </Menu>
      </template>
    </Dropdown>
  </div>
</template>

<script lang="ts" setup>
import {
  Modal,
  Input,
  Table,
  Empty,
  Tabs,
  TabPane,
  Dropdown,
  Menu,
  MenuItem,
  TableProps,
} 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 { fetchScenesAll, SceneType, uploadMaterialToModel, type Scene } from "@/api";
import { activeModel, getSceneModel } from "@/sdk";
import { selectMaterials } from "@/components/materials/quisk";
import { lang, ui18n } from "@/lang";
import { custom } from "@/env";
import { actionItems, currentItem } from "@/views/merge";

type Key = string;

const Search = Input.Search;

const spStr = '----ll----'
const selectIds = computed(() => fuseModels.value.filter(item => item.type !== SceneType.SWMX).map((item) => item.raw.isObj + spStr + item.raw.num));
const visible = ref(false);
const keyword = ref("");
const SceneGroupTypeDesc: any = lang.scene.typeRaws

const types = computed(() => [
  ...new Set(Object.values(SceneGroupTypeDesc) as any[]).values(),
]);
const type = ref(types.value[0]);

const handleTableChange: TableProps["onChange"] = (pag) => {
  params.value.pageSize = pag.pageSize!;
  params.value.pageNum = pag.current!;
};
const meshParams = ref({ isObj: 1, pageNum: 1, pageSize: 12, total: 0 })
const cloudParams = ref({ isObj: 0, pageNum: 1, pageSize: 12, total: 0 })
const meshList = ref<Scene[]>([])
const cloudList = ref<Scene[]>([])
const params = computed(() => type.value === ui18n.t('scene.typeRaws.0') ? meshParams.value : cloudParams.value)

let loadCount = 0
watchEffect(() => {
  const list = type.value === ui18n.t('scene.typeRaws.2') ? meshList : cloudList
  const currentCount = ++loadCount
  fetchScenesAll(params.value).then((data) => {
    console.log('====>', currentCount, loadCount, params.value)
    if (currentCount === loadCount) {

      params.value.total = data.total
      list.value = data.list.map(item => ({ ...item, type: type.value, num: item.isObj + spStr + item.num })) as any
      console.log(data.total, list.value)
    }
  })
})

const origin = computed(() => [...meshList.value, ...cloudList.value]);

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

let cache = {} as any
watchEffect(() => {
  if (!visible.value) {
    cache = {}
  }
})

const selects = ref<Key[]>(selectIds.value);
watchEffect(() => console.error(selects.value), {flush: 'sync'})
const rowSelection: any = ref({
  selectedRowKeys: selects,

  hideSelectAll: true,
  onChange: (ids: string[]) => {
    console.error(ids)
    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.num),
  }),
});
const cloumns = [
  {
    width: "400px",
    title: ui18n.t('scene.tabs.name'),
    dataIndex: "name",
    key: "name",
  },
  {
    title: ui18n.t('scene.tabs.type'),
    dataIndex: "type",
    key: "type",
  },
  {
    title: ui18n.t('scene.tabs.createTime'),
    dataIndex: "createTime",
    key: "createTime",
  },
];

const addModelHandler = createLoadPack(async (attachs: any[]) => {
  await save();
  const items = attachs.map((attach) => {
    return {
      data: createFuseModels(),
      attach
    }
  });
  const addPromises = items.map(item => addFuseModel(item.data, item.attach));

  const addModels = await Promise.all(addPromises);
  await new Promise<void>((resolve) => {
    nextTick(() => {
      const stop = watchEffect(() => {
        if (fuseModelsLoaded.value) {
          nextTick(() => {
            stop();
            resolve();
          });
        }
      });
    });
  });

  items.forEach(item => {
    if (getSceneModel(item.data)) {
      item.data.rotation = getSceneModel(item.data)!.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 () => {
  const attachs = selects.value.map(item => {
    const isObj = Number(item.split(spStr)[0])
    const num = item.split(spStr)[1]
    return {isObj, num}
  }).filter(({isObj, num}) =>
    num && !fuseModels.value.some((model) => model.raw.isObj === isObj && model.raw.num === num)
  )
  await addModelHandler(attachs);
  visible.value = false;
});

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

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

  // const modelList = await Promise.all(list.map(item => uploadMaterialToModel(item.uploadId!)))
  const attachs: any[] = []
  for (let i = 0; i < list.length; i++) {
    const uploadId = list[i].uploadId
    if (uploadId ) {
      attachs.push({ uploadId })
    }
  }
  await addModelHandler(attachs);
};
</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>
