<template>
  <div id="algoCardWrapper" class="algoCardWrapper">
    <div class="algoCardTitle">
      <div>算法参数</div>
    </div>
    <div class="algoCardMain">
      <div style="display: flex">
        <div style="margin-right: 30px; display: flex; margin-top: 16px">
          <div class="algoLabel">检测元数据:</div>
          <div class="algoTimeContent">
            <div
              class="timeAdd"
              :class="{ addDisable: unEmptyLabels.length >= metaObjList.length }"
              @click="handleAddMetaObj"
            >
              <el-icon color="#d0d0d0"><Plus /></el-icon>
            </div>
            <div class="metaValuesList">
              <AlgoParamsCard
                v-for="(v, index) in selectedAlgoDetail.metaValues"
                :key="v.id"
                :ref="(el) => (paramCardRefs[index] = el)"
                :id="v.id"
                @change="handleChange"
              />
            </div>
          </div>
        </div>
        <div>
          <div class="algoRow" style="align-items: center">
            <div class="algoLabel">检测数量范围:</div>
            <el-radio-group v-model="selectedAlgoDetail.judge" class="ml-4" @change="handleChange">
              <el-radio :label="0">小于</el-radio>
              <el-radio :label="1">大于</el-radio>
              <el-radio :label="2">等于</el-radio>
            </el-radio-group>
          </div>
          <div class="algoRow" style="align-items: center">
            <div class="algoLabel">检测频率:</div>
            <ElInputNumber
              v-model="selectedAlgoDetail.detectionFrequency"
              controls-position="right"
              :min="1"
              :step="1"
              size="small"
              style="width: 186px"
              @blur="checkFrequencyValid"
              @change="handleChange"
            />
            <span style="font-size: 12px; margin-left: 5px">S/次</span>
          </div>
          <div class="algoRow" style="align-items: center">
            <div class="algoLabel">持续时间:</div>
            <ElInputNumber
              v-model="selectedAlgoDetail.eventDurationMinMs"
              controls-position="right"
              :min="1"
              :step="1"
              size="small"
              style="width: 186px"
              @blur="checkDurationMinMsValid"
              @change="handleChange"
            />
            <span style="font-size: 12px; margin-left: 5px">毫秒</span>
          </div>
          <div class="algoRow" style="align-items: center">
            <div class="algoLabel">持续帧数:</div>
            <ElInputNumber
              v-model="selectedAlgoDetail.eventDurationMinFrames"
              controls-position="right"
              :min="1"
              :step="1"
              size="small"
              style="width: 186px"
              @blur="checkDurationMinFramesValid"
              @change="handleChange"
            />
            <span style="font-size: 12px; margin-left: 5px">帧</span>
          </div>
          <div class="algoRow" style="align-items: center">
            <div class="algoLabel">报警时间间隔:</div>
            <ElInputNumber
              v-model="selectedAlgoDetail.eventAlarmIntervalMs"
              controls-position="right"
              :min="1"
              :step="1"
              size="small"
              style="width: 186px"
              @blur="checkAlarmIntervalMsValid"
              @change="handleChange"
            />
            <span style="font-size: 12px; margin-left: 5px">秒</span>
          </div>
          <div class="algoRow" style="align-items: center">
            <div class="algoLabel">报警帧间隔:</div>
            <ElInputNumber
              v-model="selectedAlgoDetail.eventAlarmIntervalFrames"
              controls-position="right"
              :min="1"
              :step="1"
              size="small"
              style="width: 186px"
              @blur="checkAlarmIntervalFramesValid"
              @change="handleChange"
            />
            <span style="font-size: 12px; margin-left: 5px">帧</span>
          </div>
        </div>
      </div>

      <div v-if="selectedAlgoDetail.timeWindow !== undefined" class="algoRow" style="align-items: center">
        <div class="algoLabel">检测窗口时长:</div>
        <ElInputNumber
          v-model="selectedAlgoDetail.timeWindow"
          controls-position="right"
          :min="1"
          size="small"
          style="width: 186px"
          placeholder="请输入允许的最长时间"
          @blur="checkTimeWindowValid"
          @change="handleChange"
        />
        <span style="font-size: 12px; margin-left: 5px">S</span>
      </div>

      <div class="algoRow" style="margin-top: 20px">
        <div class="algoLabel">检测时间段:</div>
        <div class="algoTimeContent">
          <div class="timeAdd" @click="handleAddTimePeriod">
            <el-icon color="#d0d0d0"><Plus /></el-icon>
          </div>
          <div class="timeList" v-if="selectedAlgoDetail.timeRangeArr?.length > 0">
            <PeriodCard
              v-for="(x, index) in selectedAlgoDetail.timeRangeArr"
              :key="x.id"
              :ref="(el) => (periodCardRefs[index] = el)"
              :id="x.id"
              @change="handleChange"
            />
          </div>
        </div>
      </div>
      <div style="display: flex; justify-content: flex-end">
        <ElButton size="small" @click="handleRemoveAlgo">取消</ElButton>
        <ElButton size="small" type="primary" @click="handleSave">保存</ElButton>
      </div>
    </div>
  </div>
</template>
<script lang="ts" setup>
  import { ElInputNumber, ElMessage, ElMessageBox } from 'element-plus';
  import { Plus } from '@element-plus/icons-vue';
  import { storeToRefs } from 'pinia';
  // import useCameraAlgoStore, { AlgoParamMetaItem } from './store/useCameraAlgoStore';
  import useAlgoParamsSettingStore from './use-algo-params-edit-store';
  import { AlgoParamMetaItem, CameraAlgoItemInCard } from './types';

  import { createDefaultTime, getTimeCompletion } from './utils';

  import { ALGO_ENABLED_STATUS, FENCE_ENBALED_STATUS } from '@/api/camera/camera-preview';
  import PeriodCard from './AlgoPeriodCard.vue';
  import AlgoParamsCard from './AlgoParamsCard.vue';
  import { uid } from 'uid';
  import { computed, onMounted, onUnmounted, ref } from 'vue';

  // const { data: algoList, loading } = useAllAlgos();
  const algoParamsSettingStore = useAlgoParamsSettingStore();
  const { selectedAlgoDetail, metaObjList, markedTimeRangeIds, markedParamCardIds } =
    storeToRefs(algoParamsSettingStore);

  interface Param {
    /** 算法id */
    algoId: number;
    /** 检测频率，单位是秒 */
    detectionFrequency: number;
    /** 检测时间段，可以有多个，转化为字符串，格式为 09:00-10:00;11:00-12:00 */
    detectionTime: string;
    /** 电子围栏是否开启 */
    electronicFence: FENCE_ENBALED_STATUS;
    /** 算法是否启用 */
    status: ALGO_ENABLED_STATUS;
  }

  const props = defineProps<{
    isChanged?: boolean;
    algoDetail: CameraAlgoItemInCard;
  }>();

  const emits = defineEmits<{
    (e: 'onSubmit', param: Param): Promise<unknown>;
    (e: 'onCancel'): Promise<unknown>;
    (e: 'change'): unknown;
  }>();

  const periodCardRefs = ref<any>([]);
  const paramCardRefs = ref<any>([]);

  onMounted(() => {
    selectedAlgoDetail.value = { ...props.algoDetail };
  });
  const handleChange = () => {
    emits('change');
  };
  const handleAddTimePeriod = () => {
    const emptyList = selectedAlgoDetail.value.timeRangeArr?.filter((item) => !getTimeCompletion(item));
    if (emptyList && emptyList.length > 0) {
      emptyList.forEach((item) => markedTimeRangeIds.value.push(item.id));
      ElMessage.error('请先完善检测时间段数据');
      return;
    }
    handleChange();
    selectedAlgoDetail.value.timeRangeArr?.push(createDefaultTime());
  };

  const unEmptyLabels = computed(() => {
    return selectedAlgoDetail.value.metaValues?.filter((item) => item.label) || [];
  });

  const handleAddMetaObj = () => {
    if (unEmptyLabels.value.length < selectedAlgoDetail.value.metaValues?.length) {
      selectedAlgoDetail.value.metaValues
        .filter((item) => !item.label)
        .forEach((val) => markedParamCardIds.value.push(val.id));
      ElMessage.error('存在未完善的检测元数据');
      return;
    }
    handleChange();
    // if (unemptyList.length == metaObjList.value.length) {
    //   ElMessage.warning('暂无更多检测对象');
    //   return;
    // }
    selectedAlgoDetail.value.metaValues.push({ id: uid() } as AlgoParamMetaItem);
  };

  const checkFrequencyValid = () => {
    selectedAlgoDetail.value.detectionFrequency = Math.ceil(selectedAlgoDetail.value.detectionFrequency);
  };
  const checkDurationMinMsValid = () => {
    selectedAlgoDetail.value.eventDurationMinMs = Math.ceil(selectedAlgoDetail.value.eventDurationMinMs);
  };
  const checkDurationMinFramesValid = () => {
    selectedAlgoDetail.value.eventDurationMinFrames = Math.ceil(selectedAlgoDetail.value.eventDurationMinFrames);
  };
  const checkAlarmIntervalMsValid = () => {
    selectedAlgoDetail.value.eventAlarmIntervalMs = Math.ceil(selectedAlgoDetail.value.eventAlarmIntervalMs);
  };
  const checkAlarmIntervalFramesValid = () => {
    selectedAlgoDetail.value.eventAlarmIntervalFrames = Math.ceil(selectedAlgoDetail.value.eventAlarmIntervalFrames);
  };

  const checkTimeWindowValid = () => {
    selectedAlgoDetail.value.timeWindow = Math.ceil(selectedAlgoDetail.value.timeWindow || 1);
  };

  const handleSave = async () => {
    //判断时间段是否合格
    if (markedTimeRangeIds.value.length > 0) {
      ElMessage.error('请正确填写检测时间段');
      return;
    }
    const emptyTimes = selectedAlgoDetail.value.timeRangeArr.filter((item) => !item.startDay || !item.endDay);
    if (emptyTimes && emptyTimes.length > 0) {
      emptyTimes.forEach((item) => {
        markedTimeRangeIds.value.push(item.id);
      });
      ElMessage.error('请完善检测时间段');
      return;
    }

    for (let i = 0; i < periodCardRefs.value.length; i++) {
      const item = periodCardRefs.value[i];
      if (!item) continue;
      switch (item.checkValid()) {
        case 0:
          ElMessage.error('请正确填写检测时间段');
          return;
        case 1:
          ElMessage.error('请完善检测时间段');
          return;
        case 2:
          ElMessage.error('至少有一个时间段');
          return;
        case 3:
          break;
      }
    }

    //判断元数据是否合格
    for (let i = 0; i < paramCardRefs.value.length; i++) {
      const item = paramCardRefs.value[i];
      if (!item) continue;
      const res = await item.checkValid();
      if (res) {
      } else {
        ElMessage.error('请正确填写检测元数据');
        return;
      }
    }

    //判断时间段和元数据都有值
    const detail = selectedAlgoDetail.value;
    if (!detail) return;
    // const timeRanges = detail.timeRangeArr;
    // if (timeRanges.length == 0) {
    //   ElMessage.error('至少添加一个检测时间段');
    //   return;
    // }
    const metaValues = detail.metaValues;
    // 鹰眼追踪不需要元数据，先放开所有算法的元数据约束
    // if (metaValues.length == 0) {
    //   ElMessage.error('至少添加一个检测元数据');
    //   return;
    // }

    //数据处理
    const metaObjs = metaValues.map((meta) => {
      const obj = metaObjList.value.find((item) => item.label === meta.label);
      const val = {
        label: meta.label,
        confidence: meta.confidence / 100,
        min_width: meta['min_width'],
        min_height: meta['min_height'],
      } as any;
      const nextValues = [] as any[];
      obj.nextObjs.forEach((next) => {
        if (meta[`${next.label}.confidence`]) {
          nextValues.push({
            label: next.label,
            confidence: meta[`${next.label}.confidence`] / 100,
            min_width: meta[next.label + '.' + 'min_width'],
            min_height: meta[next.label + '.' + 'min_height'],
            nextObjs: [],
          });
        }
      });
      val.nextObjs = nextValues;
      return val;
    });
    const param = {
      id: detail.id,
      inferCode: detail.inferCode,
      algoId: detail.algoId,
      detectionFrequency: detail.detectionFrequency,
      eventDurationMinMs: detail.eventDurationMinMs,
      eventDurationMinFrames: detail.eventDurationMinFrames,
      eventAlarmIntervalMs: detail.eventAlarmIntervalMs,
      eventAlarmIntervalFrames: detail.eventAlarmIntervalFrames,
      regionJudge: detail.regionJudge,
      detectionTime: JSON.stringify(detail.timeRangeArr),
      metaObjs,
      criticalCounts: metaValues.map((item) => item.criticalCount),
      judge: detail.judge,
      electronicFence: detail.electronicFenceBool ? FENCE_ENBALED_STATUS.enabled : FENCE_ENBALED_STATUS.disabled,
      status: detail.enableCardBool ? ALGO_ENABLED_STATUS.enabled : ALGO_ENABLED_STATUS.disabled,
    } as any;
    if (detail.timeWindow) {
      param.timeWindow = detail.timeWindow;
    }
    emits('onSubmit', param);
    console.log('param', param);
  };

  const handleRemoveAlgo = () => {
    const el = document.getElementById('algoCardWrapper') as HTMLElement;
    if (props.isChanged) {
      ElMessageBox.confirm('<strong>确认取消算法配置吗?</strong><br />取消后配置的参数将不会被保存。', '', {
        confirmButtonText: '确定',
        cancelButtonText: '取消',
        type: 'warning',
        dangerouslyUseHTMLString: true,
        appendTo: el,
      })
        .then(() => {
          emits('onCancel');
        })
        .catch(() => {});
    } else {
      emits('onCancel');
    }
  };

  onUnmounted(() => {
    algoParamsSettingStore.clear();
  });
</script>
<style scoped>
  .algoCardWrapper {
    border: 1px solid #ccc;
    border-radius: 4px;
    /* padding: 10px; */
    width: 990px;
  }

  .algoRow {
    display: flex;
    margin: 10px 0;
  }

  .algoLabel {
    margin-right: 10px;
    width: 90px;
    text-align: right;
    flex-shrink: 0;
    flex-grow: 0;
  }
  .algoTimeContent {
    display: flex;
  }
  .presetList {
    font-size: 12px;
    display: none;
  }
  .removeIcon {
    margin-left: 10px;
    color: #8c8c8c;
    cursor: pointer;
  }

  .addTimeIcon {
    cursor: pointer;
  }

  .algoCardTitle {
    background: #f0f2f5;
    display: flex;
    justify-content: space-between;
    padding: 4px 20px;
    align-items: center;
  }

  .algoCardMain {
    padding: 10px 15px;
  }

  .timeAdd {
    width: 28px;
    height: 50px;
    background: #ebebeb;
    border-radius: 4px;
    border: 1px dashed #00000026;
    display: flex;
    justify-content: center;
    align-items: center;
    margin-right: 5px;
    cursor: pointer;
  }
  .addDisable {
    opacity: 0.5;
    cursor: not-allowed;
  }

  .timeList {
    overflow-y: auto;
    display: flex;
    flex-wrap: wrap;
    align-items: flex-start;
  }
  .metaValuesList {
    width: 425px;
    max-height: 350px;
    overflow-y: auto;
    display: flex;
    flex-wrap: wrap;
    align-items: flex-start;
  }
  .tipIcon {
    margin-left: 10px;
  }

  :deep(.ml-4) {
    margin-left: 0 !important;
  }
  :deep(.el-message-box__status.el-icon) {
    top: 0 !important;
    transform: none !important;
  }
</style>
