<template>
  <BasicModal
    @register="register"
    title="风机运行工况辅助决策"
    :maskStyle="{ backgroundColor: '#000000aa' }"
    width="1200px"
    v-bind="$attrs"
    @ok="onSubmit"
    @cancel="onSubmit"
    :canFullscreen="false"
    :destroyOnClose="true"
    :footer="null"
  >
    <div class="modal-box">
      <div class="right-box">
        <!-- <div class="box-title">风机信息</div> -->
        <dv-decoration7 style="height: 20px">
          <div class="box-title">风机信息</div>
        </dv-decoration7>
        <div class="info-container">
          <template v-if="isMock">
            <div v-for="(item, index) in fanInfo" class="info-item" :key="index">
              <div class="title">{{ item.title }}：</div>
              <div class="value">{{ fanInfoData && fanInfoData[item.code] ? fanInfoData[item.code] : '-' }}</div>
            </div>
          </template>
          <template v-else>
            <div v-for="(item, index) in columns" class="info-item" :key="index">
              <div class="title">{{ item['title'] }}：</div>
              <div class="value">{{ selectData && selectData[item['dataIndex']] ? selectData[item['dataIndex']] : '-' }}</div>
            </div>
          </template>
        </div>
      </div>
      <div class="center-box">
        <a-spin :spinning="loadding" tip="正在计算，请稍等。。。">
          <div ref="chartRef" class="info-echarts" style="width: 450px; height: 375px"></div>
          <div v-if="resultObj" class="result-tip">
            工况点为
            <span style="color: #9a60b4; padding: 0 10px; font-weight: 600">{{ parseInt(resultObj.Hz) }}Hz</span>
            <span style="color: #c60000; padding: 0 10px; font-weight: 600">{{ formatNum(resultObj.x) }} m³/s</span>
            <span style="color: #c60000; padding: 0 10px; font-weight: 600">{{ formatNum(resultObj.y) }} Pa</span></div
          >
        </a-spin>
      </div>
      <div class="left-box">
        <!-- <div class="box-title">曲线方程</div> -->
        <dv-decoration7 style="height: 20px">
          <div class="box-title">曲线方程</div>
        </dv-decoration7>
        <div class="info-lines">
          <div v-for="(item, index) in lineEquation" class="info-item" :key="index">
            <div class="title">{{ item }}</div>
          </div>
        </div>
      </div>
    </div>
    <div class="setting-box">
      <div class="left-buttons">
        <!-- <div class="btn btn1" @click="edit('info')">编辑风机信息</div> -->
        <!-- <div class="btn btn1" @click="edit('line')">编辑特性曲线</div> -->
        风机当前角度：<span>{{ selectData.bladeAngle }} &nbsp;°</span>
      </div>
      <!-- <div class="border-clip"></div> -->
      <div class="right-inputs">
        <div class="vent-flex-row">
          <div class="input-title">风量(m³/s)：</div>
          <Input class="input-box" size="large" v-model:value="uQ" />
          <div class="input-title">风压(Pa)：</div>
          <Input class="input-box" size="large" v-model:value="uH" />
        </div>
        <div class="btn btn1" @click="makeLine">决策工况</div>
      </div>
    </div>
    <!-- <div v-if="formShow" class="is-close" :class="{ 'is-open': formShow }">
      <a-divider orientation="left" style="border-color: #00d8ff22">{{ formType }}</a-divider>
      <BasicForm @register="registerForm" @submit="handleSubmit" :schemas="columns" />
    </div> -->
  </BasicModal>
</template>

<script lang="ts" setup>
  //ts语法
  import { ref, onMounted, reactive, nextTick, defineProps, defineEmits, watch } from 'vue';
  import echarts from '/@/utils/lib/echarts';
  import { option, initData, fanInfoData, fanInfo, getSchamas, getSchamas1, lineFormData } from '../main.data.ts';
  import { BasicModal, useModalInner } from '/@/components/Modal';
  import { BasicForm, useForm } from '/@/components/Form/index';
  import { Input } from 'ant-design-vue';
  import { Decoration7 as DvDecoration7 } from '@kjgl77/datav-vue3';
  import { message } from 'ant-design-vue';
  import { formatNum } from '/@/utils/ventutil';
  import { getTableHeaderColumns } from '/@/hooks/web/useWebColumns';
  import { list } from '../main.api';
  const props = defineProps({
    deviceType: {
      type: String,
    },
    selectData: {
      type: Object,
      default: () => {},
    },
  });
  const emit = defineEmits(['close', 'register', 'openModal']);
  type AssistanceItemType = {
    angle: number;
    Hz: number;
    a: number;
    b: number;
    c: number;
    min: number;
    max: number;
  };
  const columns = ref([]);
  const isMock = true;
  // 注册 modal
  const [register, { closeModal }] = useModalInner(() => {
    nextTick(() => {
      computeAssistance();
      if (option['xAxis']) option['xAxis']['data'] = xData;
      option['series'] = yDataList;
      initEcharts();
    });
  });
  const loadding = ref<boolean>(false);
  const formShow = ref(false);
  const formType = ref('');
  const chartRef = ref();
  const myChart = ref();
  const refresh = ref(true);
  const xData: any[] = [];
  const yDataList: [] = [];
  let lineNum = 0;
  const lineEquation = ref<string[]>([]);
  const deviceData = ref({});
  const uQ = ref<string | undefined>(undefined); // 100 - 400
  const uH = ref<number | undefined>(undefined); //  - 1000
  const resultObj = ref<{ x: number; y: number; Hz: number } | null>(null);

  const [registerForm, {}] = useForm({
    labelWidth: 120,
    actionColOptions: {
      span: 24,
    },
    compact: true,
    showSubmitButton: true,
    submitButtonOptions: {
      text: '提交',
      preIcon: '',
    },
    showResetButton: true,
    resetButtonOptions: {
      text: '关闭',
      preIcon: '',
    },
    resetFunc: async () => {
      formShow.value = false;
    },
  });

  function computeAssistance() {
    const assistanceData = initData();
    lineNum = 0;
    const assistanceDataList = [];
    const lineEquationList: string[] = [];
    for (const key in assistanceData) {
      const item = assistanceData[key];
      assistanceDataList.push(item);
      lineEquationList.push(
        `H${parseInt(item['Hz'])} = ${item['a']}Q² ${Number(item['b']) > 0 ? '+' : '-'} ${Math.abs(Number(item['b'])).toFixed(5)}Q ${
          Number(item['c']) > 0 ? '+' : '-'
        } ${Math.abs(Number(item['c'])).toFixed(5)}`
      );
    }
    lineEquation.value = lineEquationList;
    lineNum = assistanceDataList.length;
    const xDataMin =
      Math.min.apply(
        Math,
        assistanceDataList.map((item) => {
          return item.min;
        })
      ) - 10;
    // const xDataMax = Math.max.apply(Math, assistanceDataList.map(item => { return item.max }))
    const xDataMax = 230;
    fanInfoData.flfw = `${xDataMin}~${xDataMax}`;
    const computeItem = (item: AssistanceItemType) => {
      const min = item.min;
      const max = item.max;
      const HList: number[] = [];
      for (let i = xDataMin; i <= xDataMax; i++) {
        if (i < min) {
          HList.push(null);
        } else if (i > max) {
          HList.push(null);
        } else {
          HList.push(item.a * i * i + item.b * i + item.c);
        }
      }
      return HList;
    };

    for (const key in assistanceData) {
      const element: AssistanceItemType = assistanceData[key];
      const yData: number[] = computeItem(element);
      const series = {
        name: `${element['Hz']}Hz`,
        type: 'line',
        smooth: true,
        showSymbol: false,
        emphasis: {
          focus: 'series',
        },
        itemStyle: { normal: { label: { show: true } } },
        lineStyle: {
          width: 1,
          color: '#ffffff88',
        },
        zlevel: 0,
        z: 1,
        endLabel: {
          show: true,
          formatter: '{a}',
          distance: 0,
          color: '#39E9FE99',
          backgroundColor: 'transparent',
          padding: [3, 3, 2, 3],
        },
        data: yData,
      };
      yDataList.push(series);
    }

    for (let i = xDataMin; i <= xDataMax; i++) {
      xData.push(i);
    }
  }

  function computeRLine() {
    if (uH.value && uQ.value) {
      const R = uH.value / Number(uQ.value) / Number(uQ.value);
      const yAxis: number[] = [];
      for (let i = 0; i < xData.length; i++) {
        const x = xData[i];
        const y = R * x * x;
        if (x == uQ.value) {
          uH.value = y;
        }
        yAxis.push(y);
      }
      const series = {
        name: 'R',
        type: 'line',
        smooth: true,
        showSymbol: false,
        zlevel: 0,
        emphasis: {
          focus: 'series',
        },
        itemStyle: { normal: { label: { show: true } } },
        lineStyle: {
          width: 2,
          color: '#D0A343',
        },
        endLabel: {
          show: true,
          formatter: '{a}',
          distance: 0,
          color: '#D0A343',
        },
        data: yAxis,
      };
      yDataList[lineNum] = series;
    }
  }

  function reSetLine() {
    let minIndex = -1;
    for (let i = 0; i < yDataList.length; i++) {
      if (i !== lineNum && i != lineNum + 1) {
        if (yDataList[i]['lineStyle']) yDataList[i]['lineStyle']['color'] = '#ffffff88';
        if (yDataList[i]['lineStyle']) yDataList[i]['lineStyle']['width'] = 1;
        if (yDataList[i]['endLabel'] && yDataList[i]['endLabel']['color']) yDataList[i]['endLabel']['color'] = '#39E9FE99';
        if (yDataList[i]['endLabel'] && yDataList[i]['endLabel']['backgroundColor']) yDataList[i]['endLabel']['backgroundColor'] = 'transparent';
        if (yDataList[i]['z']) yDataList[i]['z'] = 1;
      }
      if (`${resultObj.value.Hz}Hz` == yDataList[i]['name']) {
        minIndex = i;
      }
    }
    if (minIndex != -1) {
      yDataList[minIndex]['lineStyle']['color'] = '#9A60B4';
      yDataList[minIndex]['lineStyle']['width'] = 2;
      yDataList[minIndex]['endLabel']['color'] = '#9A60B4';
      yDataList[minIndex]['endLabel']['backgroundColor'] = '#111';
      yDataList[minIndex]['z'] = 999;
    }
  }

  // 根据风量计算压差
  function computePa() {
    const R = uH.value / Number(uQ.value) / Number(uQ.value);
    const pointX = Number(uQ.value);
    const pointY = Number(uH.value);
    type ItemType = {
      x: number;
      y: number;
      Hz: number;
    };
    const assistanceData = initData();
    const paList = new Map<number, ItemType>(); // key 是最近距离
    const getIntersectionPoint = (a, b, c, R, min, max) => {
      const obj: { x: undefined | number; y: undefined | number } = { x: undefined, y: undefined };
      // 计算二次方程的判别式
      const discriminant = b * b - 4 * (a - R) * c;

      if (discriminant > 0) {
        // 有两个实根
        const x1 = (-b + Math.sqrt(discriminant)) / (2 * (a - R));
        const x2 = (-b - Math.sqrt(discriminant)) / (2 * (a - R));

        const y1 = R * x1 * x1;
        const y2 = R * x2 * x2;
        if (x1 >= min && x1 <= max) {
          obj.x = x1;
          obj.y = y1;
        } else {
          obj.x = x2;
          obj.y = y2;
        }
      } else if (discriminant === 0) {
        // 有一个实根
        const x = -b / (2 * (a - R));
        const y = R * x * x;
        if (x >= min && x <= max) {
          obj.x = x;
          obj.y = y;
        }
        // console.log(`唯一交点: (${x}, ${y})`);
      } else {
        // 没有实根，交点在虚数域
        console.log('没有实数交点');
      }
      return obj;
    };

    for (let key in assistanceData) {
      const item: AssistanceItemType = assistanceData[key];
      paList.set(item.Hz, getIntersectionPoint(item.a, item.b, item.c, R, item.min, item.max));
    }

    const min = (points: Map<number, ItemType>) => {
      const targetX = uQ.value;
      const targetY = uH.value;
      let minDistance = Number.POSITIVE_INFINITY;
      let closestPoint = null;
      let keyVal = '';
      // 遍历已知点数组，计算距离并更新最小距离和对应的点
      for (const [key, point] of points) {
        const distance = Math.sqrt((targetX - point.x) ** 2 + (targetY - point.y) ** 2);
        if (distance < minDistance) {
          minDistance = distance;
          closestPoint = point;
          keyVal = key;
        }
      }

      if (closestPoint !== null) {
        console.log(`距离最小的点是 (${closestPoint.x}, ${closestPoint.y}), 距离为 ${minDistance}`);
        resultObj.value = { x: closestPoint.x, y: closestPoint.y, Hz: keyVal };
      } else {
        console.log('没有找到最小距离的点');
      }
    };
    min(paList);
    reSetLine();
  }

  function computeR() {
    if (uQ.value && uH.value) {
      computeRLine();
      computePa();
      if (resultObj.value && resultObj.value.x && resultObj.value.y) {
        const series = {
          type: 'effectScatter',
          symbolSize: 5,
          // symbolOffset:[1, 1],
          showEffectOn: 'render',
          // 涟漪特效相关配置。
          rippleEffect: {
            // 波纹的绘制方式，可选 'stroke' 和 'fill'。
            brushType: 'stroke',
          },
          zlevel: 1,
          z: 999,
          itemStyle: {
            color: '#C60000',
          },
          data: [[resultObj.value.x.toFixed(0), Number(resultObj.value.y.toFixed(0))]],
        };
        yDataList[lineNum + 1] = series;
      }
    }
  }

  function edit(flag) {
    if (flag == 'info') {
      formType.value = '编辑风机信息';
    }
    if (flag == 'line') {
      formType.value = '编辑特性曲线';
    }
    if (formShow.value == true) {
      formShow.value = false;
      nextTick(() => {
        formShow.value = true;
      });
    } else {
      formShow.value = true;
    }
  }

  async function onSubmit() {
    emit('close');
    closeModal();
    chartRef.value = null;
    uQ.value = undefined;
    uH.value = undefined;
    formType.value = '';
    myChart.value = undefined;
    refresh.value = true;
    xData.length = 0;
    yDataList.length = 0;
    lineNum = 0;
    lineEquation.value = [];
    resultObj.value = null;
  }

  function initEcharts() {
    if (chartRef.value) {
      computeR();
      myChart.value = echarts.init(chartRef.value);
      option && myChart.value.setOption(option);
      refresh.value = false;
      nextTick(() => {
        setTimeout(() => {
          refresh.value = true;
        }, 0);
      });
    }
  }

  function makeLine() {
    if (uQ.value && uH.value) {
      loadding.value = true;
      setTimeout(() => {
        initEcharts();
        loadding.value = false;
      }, 1200);
    }
  }
  function handleSubmit() {
    message.success('提交成功');
    setTimeout(() => {
      formShow.value = false;
    }, 800);
  }
  function getColumn() {
    let lineColumns = [];
    if (props.deviceType) {
      lineColumns = getTableHeaderColumns(props.deviceType + '_input') as [];
      if (lineColumns && lineColumns.length < 1) {
        lineColumns = getTableHeaderColumns(props.deviceType.split('_')[0] + '_input') as [];
      }
      if (lineColumns.length > 0) {
        lineColumns = lineColumns.filter((item) => item['dataIndex'] && item['dataIndex'].includes('_line_'));
        columns.value = lineColumns;
      }
    }
  }
  watch(
    () => props.deviceType,
    async () => {
      getColumn();
      // deviceData.value = await list({ devicetype: 'fanmain', pagetype: 'normal' });
    }
  );
  watch(
    () => props.selectData,
    async (selectData) => {
      debugger;
      deviceData.value = selectData;
    }
  );
  onMounted(() => {});
</script>

<style scoped lang="less">
  .modal-box {
    display: flex;
    flex-direction: row;
    background-color: #ffffff05;
    padding: 20px 8px;
    border: 1px solid #00d8ff22;
    // min-height: 600px;
    .box-title {
      width: calc(100% - 40px);
      text-align: center;
      background-color: #1dc1f522;
    }
    .info-item {
      display: flex;
      justify-content: space-between;
      align-items: center;
      padding: 2px 0px;
      margin: 4px 0;
      background-image: linear-gradient(to right, #39deff15, #3977e500);
      &:first-child {
        margin-top: 0;
      }
      .title {
        width: 200px;
        text-align: left;
        padding-left: 20px;
        color: #f1f1f1cc;
      }
      .value {
        width: 150px;
        color: #00d8ff;
        padding-right: 20px;
        text-align: right;
      }
    }
    .right-box {
      width: 350px;

      .info-container {
        width: calc(100% - 2px);
        margin-top: 5px;
        box-shadow: 0px 0px 50px #86baff08 inset;
      }
    }
    .left-box {
      width: 350px;
      .info-lines {
        width: calc(100% - 2px);
        height: 390px;
        box-shadow: 0px 0px 50px #86baff08 inset;
        overflow-y: auto;
        margin-top: 5px;
        .title {
          width: 100%;
          color: #f1f1f1cc;
        }
      }
    }
    .center-box {
      margin: 0 10px;

      .info-echarts {
        // background-color: #ffffff11;
      }
      .result-tip {
        text-align: center;
        background-color: #00000011;
        line-height: 28px;
        margin: 10px 50px 0 50px;
        border: 1px solid #00d8ff22;
        border-radius: 2px;
      }
    }
  }
  .setting-box {
    width: 1170px;
    height: 70px;
    margin: 10px 0;
    background-color: #ffffff05;
    border: 1px solid #00d8ff22;
    display: flex;
    align-items: center;
    justify-content: space-between;

    .right-inputs {
      display: flex;
      height: 40px;
      margin-right: 10px;
    }
    .left-buttons {
      display: flex;
      height: 40px;
      margin-left: 15px;
      .btn {
        margin: 0 10px;
      }
      span {
        color: #00d8ff;
      }
    }
    .border-clip {
      width: 1px;
      height: 25px;
      border-right: 1px solid #8b8b8b77;
    }
    .input-title {
      width: 80px;
    }
    .input-box {
      width: 200px !important;
      background: transparent !important;
      border-color: #00d8ff44 !important;
      margin-right: 20px;
      color: #fff !important;
    }
    .btn {
      padding: 8px 20px;
      position: relative;
      border-radius: 2px;
      color: #fff;
      width: fit-content;
      cursor: pointer;

      &::before {
        position: absolute;
        display: block;
        content: '';
        width: calc(100% - 4px);
        height: calc(100% - 4px);
        top: 2px;
        left: 2px;
        border-radius: 2px;
        z-index: -1;
      }
    }

    .btn1 {
      border: 1px solid #5cfaff;

      &::before {
        background-image: linear-gradient(#2effee92, #0cb1d592);
      }

      &:hover {
        border: 1px solid #5cfaffaa;

        &::before {
          background-image: linear-gradient(#2effee72, #0cb1d572);
        }
      }
    }
  }
  .is-open {
    animation: open 0.5s;
    animation-iteration-count: 1;
    animation-fill-mode: forwards;
    animation-timing-function: ease-in;
  }
  .is-close {
    height: 0px;
  }

  @keyframes open {
    0% {
      height: 0px;
    }
    100% {
      height: fit-content;
    }
  }

  @keyframes close {
    0% {
      height: fit-content;
    }
    100% {
      height: 0px;
    }
  }
  :deep(.zxm-divider-inner-text) {
    color: #cacaca88 !important;
  }
  :deep(.zxm-form-item) {
    margin-bottom: 10px;
  }
</style>
