<!-- 
  @Date: 2024-10-29
  @Author: ©WANGKANG
  @Email: 1686617586@qq.com
-->
<template>
  <div class="table-box">
    <ProTable ref="proTable" :columns="columns" row-key="id" :request-api="listTargetDetectionApi">
      <!-- 表格 header 按钮 -->
      <template #tableHeader="scope">
        <el-button type="primary" v-auth="['demo:TargetDetection:add']" icon="CirclePlus" @click="openDialog(1, '目标检测新增')"> 新增 </el-button>
        <!--        <el-button type="primary" v-auth="['demo:TargetDetection:import']" icon="Upload" plain @click="batchAdd">-->
        <!--          导入-->
        <!--        </el-button>-->
        <!--        <el-button type="primary" v-auth="['demo:TargetDetection:export']" icon="Download" plain @click="downloadFile">-->
        <!--          导出-->
        <!--        </el-button>-->
        <el-button
          type="danger"
          v-auth="['demo:TargetDetection:remove']"
          icon="Delete"
          plain
          :disabled="!scope.isSelected"
          @click="batchDelete(scope.selectedListIds)"
        >
          批量删除
        </el-button>
      </template>
      <!-- 表格操作 -->
      <template #operation="scope">
        <!--        <el-button type="primary" link icon="View" @click="openModelDialog(scope.row)">-->
        <!--          &lt;!&ndash;@click="openStartDialog(scope.row)"  &ndash;&gt;-->
        <!--          详情-->
        <!--        </el-button>-->
        <el-button type="primary" link icon="View" v-auth="['demo:TargetDetection:query']" @click="openDialog(3, '详情', scope.row)">
          详情
        </el-button>
        <el-button type="primary" link icon="EditPen" v-auth="['demo:TargetDetection:edit']" @click="openDialog(2, '编辑', scope.row)">
          编辑
        </el-button>
        <el-button
          type="primary"
          link
          icon="View"
          v-auth="['demo:trackSequence:start']"
          v-if="scope.row.status == '0' || scope.row.status == '3' || scope.row.status == '4'"
          @click="startTargetDetection(scope.row)"
        >
          开始
        </el-button>
        <el-popconfirm title="确定终止此任务吗?" v-if="scope.row.status == '1'" @confirm="stopTargetDetect(scope.row)">
          <template #reference>
            <el-button type="primary" link icon="Delete">终止</el-button>
          </template>
        </el-popconfirm>
        <el-button
          type="primary"
          link
          icon="View"
          v-auth="['demo:toInfrared:query']"
          @click="viewLogRef.handleOpen(scope.row.id)"
          v-if="scope.row.status != '0'"
        >
          日志
        </el-button>
        <el-button
          type="primary"
          link
          icon="View"
          v-auth="['demo:trackSequence:download']"
          v-if="scope.row.status == '2'"
          @click="dowloadTargetDetection(scope.row)"
        >
          下载
        </el-button>
        <el-button
          type="primary"
          link
          icon="View"
          v-auth="['demo:ToInfrared:download']"
          v-if="scope.row.status == '2' && scope.row.type == AlgorithmType2['训练']"
          @click="showModelDialog(scope.row.id)"
        >
          模型
        </el-button>
        <el-button type="primary" link icon="Delete" v-auth="['demo:TargetDetection:remove']" @click="deleteTargetDetection(scope.row)">
          删除
        </el-button>
      </template>
    </ProTable>
    <FormDialog ref="formDialogRef" />
    <ImportExcel ref="dialogRef" />
    <ViewLog ref="viewLogRef" :get-log-api="getLogTargetDetectionApi" />
    <el-dialog v-model="showModelDialogVisible" title="模型列表" width="1000">
      <el-scrollbar ref="scrollbarRef" id="scrollbarRef1" height="500px">
        <template v-for="model in model_list" :key="model">
          <el-card style="width: 100%; margin-bottom: 10px">
            <el-form label-width="130px" label-position="left">
              <el-form-item label="Model Name">
                {{ model.name }}
              </el-form-item>
              <el-form-item label="Model Path">
                {{ model.path }}
              </el-form-item>
              <el-form-item label="Model Size">
                {{ model.size }}
              </el-form-item>
              <el-form-item label="操作">
                <el-link :href="model.url" type="primary" icon="Download" :underline="false" target="_blank" style="margin-right: 20px"
                  >下载
                </el-link>
                <el-button type="success" link @click="addModel(model.path, model.name)">
                  <el-icon>
                    <Plus />
                  </el-icon>
                  添加模型
                </el-button>
              </el-form-item>
            </el-form>
          </el-card>
        </template>
      </el-scrollbar>
    </el-dialog>
  </div>
</template>

<script setup lang="tsx" name="TargetDetection">
import { ref, reactive, onMounted, Ref } from 'vue'
import { useHandleData } from '@/hooks/useHandleData'
import { useDownload } from '@/hooks/useDownload'
import { ElMessage, ElMessageBox } from 'element-plus'
import ProTable from '@/components/ProTable/index.vue'
import ImportExcel from '@/components/ImportExcel/index.vue'
import FormDialog from '@/components/FormDialog/index.vue'
import { ProTableInstance, ColumnProps } from '@/components/ProTable/interface'
import {
  listTargetDetectionApi,
  delTargetDetectionApi,
  addTargetDetectionApi,
  updateTargetDetectionApi,
  importTemplateApi,
  importTargetDetectionDataApi,
  exportTargetDetectionApi,
  getTargetDetectionApi,
  startTargetDetectionApi,
  dowloadTargetDetectionApi,
  stopTargetDetectionApi,
  getLogTargetDetectionApi,
  showTargetDetectionModelApi
} from '@/api/modules/demo/TargetDetection'

import { listDataSeqApi } from '@/api/modules/demo/DataSeq'
import { enumAlgorithmModelTrackApi, getAlgorithmModelTrackApi } from '@/api/modules/demo/AlgorithmModelTrack'
import { enumAlgorithmConfigTrackApi, getAlgorithmConfigTrackApi } from '@/api/modules/demo/AlgorithmConfigTrack'
import { updateTrackSequenceApi } from '@/api/modules/demo/trackSequence'
import ViewLog from '@/views/demo/components/ViewLog.vue'
import { AlgorithmType2 } from '@/views/demo/utils'
import { addAlgorithmModelTrackApi } from '@/api/modules/demo/AlgorithmModelTrack'
import useWebSocketStore from '@/stores/modules/websocket'
import { resetHeart } from '@/utils/websocket'

import { getDictsApi } from '@/api/modules/system/dictData'
const zipFileDescDict = ref<any>({})
onMounted(async () => {
  const res = await getDictsApi('zip_file_format_description')
  for (let i = 0; i < res.data.length; i++) {
    const item = res.data[i]
    zipFileDescDict.value[item.dictValue] = item.remark
  }
})

onMounted(() => {
  const websocketStore = useWebSocketStore()
  websocketStore.websocket.onmessage = (e: any) => {
    if (e.data.indexOf('heartbeat') > 0) {
      resetHeart()
    }
    if (e.data.indexOf('ping') > 0) {
      return
    }
    // console.log(e)
    proTable.value?.getTableList(true)
  }
})
const enumsAlgorithmConfigTrack = ref<any>([])
onMounted(async () => {
  const result = await enumAlgorithmConfigTrackApi()
  enumsAlgorithmConfigTrack.value = []
  const tmp_data: any = result['data']
  for (const item of tmp_data) {
    if (item.subsystem === SubSystem__['目标检测']) {
      item['label'] = item['label'] + '-' + SubSystem[item['subsystem']] + '-' + AlgorithmType[item['type']]
      enumsAlgorithmConfigTrack.value.push(item)
    }
  }
})

const setItemsOptions222 = () => {
  itemsOptions = [
    {
      label: '算法',
      prop: 'algorithmId',
      rules: [{ required: true, message: '算法不能为空', trigger: 'blur' }],
      compOptions: {
        elTagName: 'select',
        placeholder: '请输入算法',
        enum: enumsAlgorithmConfigTrack
      }
    },
    {
      label: '子系统',
      prop: 'subSystem',
      rules: [{ required: true, message: '子系统不能为空', trigger: 'blur' }],
      compOptions: {
        disabled: true,
        elTagName: 'select',
        placeholder: '请输入子系统',
        enum: enumsSubSystem
      }
    },
    {
      label: '模型名称',
      prop: 'modelName',
      rules: [{ required: true, message: '模型名称不能为空', trigger: 'blur' }],
      compOptions: {
        disabled: false,
        placeholder: '请输入模型名称'
      }
    },
    {
      label: '模型路径',
      prop: 'modelPath',
      rules: [{ required: false, message: '模型文件不能为空', trigger: 'blur' }],
      compOptions: {
        placeholder: '请输入模型名称',
        disabled: true
      }
    },
    {
      label: '备注',
      prop: 'remarks',
      rules: [{ required: false, message: '备注不能为空', trigger: 'blur' }],
      compOptions: {
        placeholder: '请输入备注'
      }
    }
  ]
}

const addModel = async (modelPath: string, modelName: string) => {
  console.log(modelPath, modelName)
  let res = { data: { modelPath, subSystem: SubSystem__['目标检测'], type: AlgorithmType2['预测/推理'], modelName: modelName } }
  // 重置表单
  setItemsOptions222()
  const params = {
    title: '添加模型',
    width: 580,
    isEdit: true,
    itemsOptions: itemsOptions,
    model: res.data,
    api: addAlgorithmModelTrackApi,
    getTableList: proTable.value?.getTableList,
    closedEvent: async () => {
      await updateWnumsAlgorithmModelTrack()
    }
  }
  formDialogRef.value?.openDialog(params)
}

const showModelDialogVisible = ref(false)
const model_list: Ref<any> = ref([])

const showModelDialog = async (id: any) => {
  const res: any = await showTargetDetectionModelApi(id)
  model_list.value = res.data
  showModelDialogVisible.value = true
}

const viewLogRef = ref()

const stopTargetDetect = async (params: any) => {
  const res: any = await stopTargetDetectionApi(params.id)
  if (res.code === 200) {
    ElMessage.success('终止任务成功！')
  } else {
    ElMessage.error('终止任务失败，请检查！')
  }
  proTable.value?.getTableList()
}

import statusEnums from '@/utils/status'
import { AlgorithmType, SubSystem, SubSystem__, enumsAlgorithmType, enumsSubSystem } from '@/views/demo/utils'
import { getDictsApi } from '@/api/modules/system/dictData'

const dowloadTargetDetection = async (params: any) => {
  await useDownload(dowloadTargetDetectionApi, params.name, params.id, true, '.zip')
}

const startTargetDetection = async (params: any) => {
  const res: any = await startTargetDetectionApi(params.id)
  if (res.code === 200) {
    ElMessage.success('任务已开始，请等待完成！')
  } else {
    ElMessage.error('任务开始失败，请检查！')
  }
  proTable.value?.getTableList()
}

const openModelDialog = async row => {
  const algorithmModelId = row.algorithmModelId
  const result: any = await getAlgorithmModelTrackApi(algorithmModelId)

  // console.log(result.data)

  setItemsOptionsModel()
  const params = {
    title: '模型',
    width: 580,
    isEdit: false,
    itemsOptions: itemsOptions,
    model: result.data,
    api: updateTrackSequenceApi,
    getTableList: proTable.value?.getTableList
  }
  formDialogRef.value?.openDialog(params)
}

// ProTable 实例
const proTable = ref<ProTableInstance>()

// 删除目标检测信息
const deleteTargetDetection = async (params: any) => {
  await useHandleData(delTargetDetectionApi, params.id, '删除【' + params.id + '】目标检测')
  proTable.value?.getTableList()
}

// 批量删除目标检测信息
const batchDelete = async (ids: string[]) => {
  await useHandleData(delTargetDetectionApi, ids, '删除所选目标检测信息')
  proTable.value?.clearSelection()
  proTable.value?.getTableList()
}

// 导出目标检测列表
const downloadFile = async () => {
  ElMessageBox.confirm('确认导出目标检测数据?', '温馨提示', { type: 'warning' }).then(() =>
    useDownload(exportTargetDetectionApi, '目标检测列表', proTable.value?.searchParam)
  )
}

// 批量添加目标检测
const dialogRef = ref<InstanceType<typeof ImportExcel> | null>(null)
const batchAdd = () => {
  const params = {
    title: '目标检测',
    tempApi: importTemplateApi,
    importApi: importTargetDetectionDataApi,
    getTableList: proTable.value?.getTableList
  }
  dialogRef.value?.acceptParams(params)
}

const formDialogRef = ref<InstanceType<typeof FormDialog> | null>(null)
// 打开弹框的功能
const openDialog = async (type: number, title: string, row?: any) => {
  let res = { data: {} }
  if (row?.id) {
    res = await getTargetDetectionApi(row.id || null)
    const params = JSON.parse(res.data['algorithmParameters'])
    if (params.otherParams) {
      res.data = { ...res.data, ...params.otherParams }
    }
  }
  // 重置表单
  setItemsOptions()
  if (row?.id) {
    itemsOptions = await updateItemsOptions(row.algorithmId)
  }
  const params = {
    title,
    width: 580,
    isEdit: type !== 3,
    itemsOptions: itemsOptions,
    model: type == 1 ? {} : res.data,
    api: type == 1 ? addTargetDetectionApi : updateTargetDetectionApi,
    getTableList: proTable.value?.getTableList
  }
  formDialogRef.value?.openDialog(params)
}

// 表格配置项
const columns = reactive<ColumnProps<any>[]>([
  { type: 'selection', fixed: 'left', width: 70 },
  { prop: 'id', label: '主键ID', width: 180 },
  {
    prop: 'name',
    label: '任务名称',
    search: {
      el: 'input'
    },
    width: 150
  },
  {
    prop: 'status',
    label: '任务状态',
    search: {
      el: 'select'
    },
    tag: true,
    enum: statusEnums,
    width: 150
  },
  {
    prop: 'type',
    label: '类型',
    tag: true,
    enum: enumsAlgorithmType,
    width: 120
  },
  {
    prop: 'subsystem',
    label: '分系统',
    tag: true,
    enum: enumsSubSystem,
    width: 200
  },
  {
    prop: 'algorithmName',
    label: '算法名称',
    width: 200
  },
  {
    prop: 'modelName',
    label: '模型名称',
    width: 200
  },
  {
    prop: 'algorithmParameters',
    label: '算法参数',
    search: {
      el: 'input'
    },
    width: 150
  },
  // {
  //   prop: 'algorithmModelId',
  //   label: '模型',
  //   search: {
  //     el: 'input'
  //   },
  //   width: 150
  // },
  {
    prop: 'startTime',
    label: '开始时间',
    width: 180
  },
  {
    prop: 'endTime',
    label: '结束时间',
    width: 180
  },
  {
    prop: 'costSecond',
    label: '耗时',
    width: 120
  },
  {
    prop: 'log',
    label: '日志',
    width: 120
  },
  {
    prop: 'outputPath',
    label: '输出路径',
    width: 120
  },
  {
    prop: 'remarks',
    label: '备注',
    search: {
      el: 'input'
    },
    width: 120
  },
  { prop: 'operation', label: '操作', width: 230, fixed: 'right' }
])

const imageUrlList________ = ref<any>([])
const getImageData = async (subsystem: string) => {
  const qyery = {
    subsystem: SubSystem__[subsystem],
    pageNum: 1,
    pageSize: 1000
  }
  const result: any = await listDataSeqApi(qyery)
  const data = result['data']['list']
  for (const item of data) {
    imageUrlList________.value.push({
      value: item['inputOssId'],
      label: item['name'] + '-' + subsystem
    })
  }
}
onMounted(async () => {
  await getImageData('可见光转红外')
  await getImageData('目标检测')
  await getImageData('注释轨迹序列')
})

const enumsAlgorithmModelTrack = ref<any>([])

const updateWnumsAlgorithmModelTrack = async () => {
  const result: any = await enumAlgorithmModelTrackApi()
  // console.log(result.data);
  enumsAlgorithmModelTrack.value = []

  for (const item of result.data) {
    if (SubSystem[item['subsystem']] === '目标检测') {
      item['label'] =
        item.value + '_' + item['label'] + '-' + SubSystem[item['subsystem']] + '-' + AlgorithmType[item['type']] + '-' + item['algorithmName']
      enumsAlgorithmModelTrack.value.push(item)
    }
  }
}

onMounted(async () => {
  updateWnumsAlgorithmModelTrack()
})

const remove_unnecessary_parameters = (itemsOptions: ProForm.ItemsOptions[]): ProForm.ItemsOptions[] => {
  try {
    const endIndex = itemsOptions.findIndex(option => option['label'] === '备注')
    if (endIndex !== -1) {
      itemsOptions = itemsOptions.slice(0, endIndex + 1)
    }
    return itemsOptions
  } catch (error) {
    console.error('移除不必要的参数时出错:', error)
    // ElMessage.error('移除不必要的参数时出错，请检查！');
    return itemsOptions // 返回原始选项，避免进一步的问题
  }
}

const updateItemsOptions = async (algorithmId: any) => {
  try {
    const result = await getAlgorithmConfigTrackApi(algorithmId)
    if (result.code === 200) {
      // 处理结果
      const parameters = JSON.parse(result.data['parameters'])
      // console.log('parameters: ', parameters)

      const itemsOptions_new = remove_unnecessary_parameters(itemsOptions)
      for (const item of parameters) {
        // 添加新的表单项选项
        itemsOptions_new.push({
          label: item['name'],
          prop: item['agName'],
          rules: [{ required: item['required'], message: item['agName'] + '不能为空', trigger: 'blur' }],
          tooltip: item['prompt'],
          compOptions: {
            elTagName: 'input',
            placeholder: item['defaultValue']
            // value: item['defaultValue']
          }
        })
      }
      formDialogRef.value?.updateItemOptions(itemsOptions_new)
      return itemsOptions_new
    }
  } catch (err) {
    console.log(err)
    ElMessage.error('获取算法配置失败，请检查！')
  }
}

// 表单配置项
let itemsOptions: ProForm.ItemsOptions[] = []
const setItemsOptions = () => {
  itemsOptions = [
    {
      label: '任务名称',
      prop: 'name',
      rules: [{ required: true, message: '任务名称不能为空', trigger: 'blur' }],
      compOptions: {
        placeholder: '请输入任务名称'
      }
    },
    {
      label: '选择数据集',
      prop: 'inputOssId',
      rules: [{ required: false, message: '数据集不能为空', trigger: 'blur' }],
      compOptions: {
        elTagName: 'select',
        placeholder: '请选择或者上传数据集',
        enum: imageUrlList________,
        clearable: true
      }
    },
    {
      label: '上传数据集',
      prop: 'inputOssId',
      rules: [{ required: true, message: '数据集不能为空', trigger: 'blur' }],
      tooltip: zipFileDescDict.value['target_detection'],
      compOptions: {
        elTagName: 'file-upload',
        fileSize: 4096,
        fileType: ['zip'],
        placeholder: '请上传数据集'
      }
    },
    {
      label: '选择算法',
      prop: 'algorithmId',
      rules: [{ required: true, message: '算法不能为空', trigger: 'blur' }],
      compOptions: {
        elTagName: 'select',
        placeholder: '请选择算法',
        enum: enumsAlgorithmConfigTrack,
        clearable: true,
        onChange: async (value: any) => {
          if (value != undefined && value != null && value != '') {
            await updateItemsOptions(value)
          }
        }
      }
    },
    {
      label: '任务类型',
      prop: 'type',
      rules: [{ required: true, message: '任务类型不能为空', trigger: 'blur' }],
      compOptions: {
        disabled: true,
        elTagName: 'select',
        placeholder: '请选择模任务类型',
        enum: enumsAlgorithmType,
        clearable: true,
        value: ''
      },
      show: params => {
        if (params.value.algorithmId != undefined) {
          for (let i = 0; i < enumsAlgorithmConfigTrack.value.length; i++) {
            if (enumsAlgorithmConfigTrack.value[i]['value'] === params.value.algorithmId) {
              params.value.type = enumsAlgorithmConfigTrack.value[i]['type']
              return true
            }
          }
        }
        return false
      }
    },
    {
      label: '选择模型',
      prop: 'algorithmModelId',
      rules: [{ required: true, message: '模型不能为空', trigger: 'blur' }],
      show: params => {
        if (params.value.type == AlgorithmType2['预测/推理']) {
          return true
        }
        params.value.algorithmModelId = ''
        return false
      },
      compOptions: {
        elTagName: 'select',
        placeholder: '请选择模型',
        enum: enumsAlgorithmModelTrack,
        clearable: true
      }
    },
    {
      label: '备注',
      prop: 'remarks',
      rules: [],
      compOptions: {
        elTagName: 'input',
        placeholder: '请输入备注'
      }
    }
  ]
}

const setItemsOptionsModel = () => {
  itemsOptions = [
    {
      label: '算法ID',
      prop: 'algorithmId',
      rules: [{ required: true, message: '算法不能为空', trigger: 'blur' }],
      compOptions: {
        disabled: true,
        placeholder: '请输入算法'
      }
    },
    {
      label: '算法类型',
      prop: 'algorithmType',
      rules: [{ required: true, message: '算法不能为空', trigger: 'blur' }],
      compOptions: {
        disabled: true,
        elTagName: 'select',
        placeholder: '请输入算法',
        enum: enumsAlgorithmConfigTrack
      }
    },
    {
      label: '算法参数',
      prop: 'parameterConfig',
      rules: [{ required: true, message: '模型名称不能为空', trigger: 'blur' }],
      compOptions: {
        placeholder: '请输入模型名称'
      }
    },
    {
      label: '模型ID',
      prop: 'id',
      rules: [{ required: true, message: '模型名称不能为空', trigger: 'blur' }],
      compOptions: {
        placeholder: '请输入模型名称'
      }
    },
    {
      label: '模型名称',
      prop: 'modelName',
      rules: [{ required: true, message: '模型名称不能为空', trigger: 'blur' }],
      compOptions: {
        placeholder: '请输入模型名称'
      }
    },
    {
      label: '模型保存路径',
      prop: 'modelAddress',
      rules: [{ required: true, message: '模型名称不能为空', trigger: 'blur' }],
      compOptions: {
        placeholder: '请输入模型名称'
      }
    },
    {
      label: '备注',
      prop: 'remarks',
      rules: [{ required: false, message: '备注不能为空', trigger: 'blur' }],
      compOptions: {
        placeholder: '请输入备注'
      }
    }
  ]
}
</script>
