<template>
  <div class="XFpdding" style="height: 510px;">
    <ul>
      <li
        class="item"
        v-for="(tab, index) in tabslist2"
        :key="index"
        :class="{ active: currentTab2 === index }"
        @click="selectTab2(index)"
      >
         <img :src="tab.imgSrc" style="width: 22px;"/>
        {{ tab.name }}
      </li>
    </ul>
    <!-- 网格文件 -->
    <!-- 执行 -->
    <div
      class="classtable"
      style="margin-top: 10px; "
      v-show="currentTab2 == '0'"
    >
      <el-form label-position="left">
        <el-form-item label="网格文件：" :label-width="formLabelWidth120">
          <el-input v-model="fname">
            <template #append>
              <fileUploads
                :projectId="125"
                solverType="exampleSolver"
                accept=".bdf"
                upId="uniqueId1"
                :imgSrc="tacsfileSrc"
                name="点击选择文件"
                @update-percentage="updatePercentage"
                @upload-success="handleFileUploadSuccess"
                @upload-status="getUploadStatus"
              />
            </template>
          </el-input>
          <!-- 进度条 -->
          <el-row v-if="showProgress" style="width: 100%; margin-top: 10px;">
            <el-col :span="20">
              <el-progress :percentage="percentage"></el-progress>
            </el-col>
            <el-col :span="4">
              <div style="line-height: 15px">{{uploadStatus}}</div>
            </el-col>
          </el-row>
        </el-form-item>
      </el-form>
      <div style="flex-grow: 1;"
        v-loading="isLoading"
        element-loading-text="拼命加载中...">
        <cloudChart :data="bdfData" :height=canvasHeight />
      </div>
    </div>
    <!-- 设置参数 -->
    <div
      class="classtable"
      style="margin-top: 10px;"
      v-show="currentTab2 == '2'"
    >
      <el-form-item label="分析对象名称：" :label-width="formLabelWidth1">
        <el-input
          v-model="tacsvalue.proname"
          :step="100"
          :min="0"
          :max="1000"
          controls-position="right"
        />
      </el-form-item>
      <el-collapse v-model="TACSactiveNames">
        <el-collapse-item title="材料属性" name="1">
          <template #title>
            <span class="collapse-title">材料属性</span>
          </template>
          <el-form-item label="材料密度：" :label-width="formLabelWidth1">
            <el-input
              v-model="tacsvalue.rho"
              :step="100"
              :min="0"
              :max="1000"
              controls-position="right"
            />
          </el-form-item>
          <el-form-item label="杨氏模量：" :label-width="formLabelWidth1">
            <el-input
              v-model="tacsvalue.e"
              :step="100"
              :min="0"
              :max="1000"
              controls-position="right"
            />
          </el-form-item>
          <el-form-item label="泊松比：" :label-width="formLabelWidth1">
            <el-input
              v-model="tacsvalue.nu"
              :step="100"
              :min="0"
              :max="1000"
              controls-position="right"
            />
          </el-form-item>
          <el-form-item label="屈服应力：" :label-width="formLabelWidth1">
            <el-input
              v-model="tacsvalue.ys"
              :step="100"
              :min="0"
              :max="1000"
              controls-position="right"
            />
          </el-form-item>
          <el-form-item label="启用FFD参数化：" :label-width="formLabelWidth1">
            <el-radio-group v-model="tacsvalue.useffd">
              <el-radio :label='1'>是</el-radio>
              <el-radio :label='0'>否</el-radio>
            </el-radio-group>
          </el-form-item>
        </el-collapse-item>
        <el-collapse-item title="收敛选项" name="2">
          <template #title>
            <span class="collapse-title">收敛选项</span>
          </template>
          <el-form-item label="绝对收敛参数：" :label-width="formLabelWidth1">
            <el-input
              v-model="tacsvalue.l2convergence "
              :step="100"
              :min="0"
              :max="1000"
              controls-position="right"
            />
          </el-form-item>
          <el-form-item label="相对收敛参数：" :label-width="formLabelWidth1">
            <el-input
              v-model="tacsvalue.l2convergencerel "
              :step="100"
              :min="0"
              :max="1000"
              controls-position="right"
            />
          </el-form-item>
        </el-collapse-item>
      </el-collapse>
    </div>
    <!-- 结构参数 v-show="currentTab=='0'"-->
    <div v-show="currentTab2 == '1'">
      <div class="eldesign classtable" style="margin-top: 10px">
        <el-row :gutter="5">
          <el-col :span="21">
            <el-form-item label="个数：" :label-width="70">
              <el-input v-model="jiegouNum" />
            </el-form-item>
          </el-col>
          <el-col :span="3">
            <el-button  @click="addJiegou" style="width: 100%;">应用</el-button>
          </el-col>
        </el-row>
        
        <el-table
          :data="inParams"
          border
          style="width: 100%;height: 450px;"
        >
          <el-table-column label="启用">
            <el-table-column type="index" width="170" label="编号">
            </el-table-column>
          </el-table-column>
          <el-table-column>
            <template v-slot:header>
              <!-- 表头显示复选框 -->
              <el-checkbox
                :false-label="0"
                :true-label="1"
                
                v-model="writesolution"
              />
            </template>
            <el-table-column prop="value" label="厚度分布" >
              <template #default="{ row }">
                <el-input v-model="row.value" />
              </template>
            </el-table-column>
          </el-table-column>
          <!-- <el-table-column>
            <el-table-column prop="con" label=""> </el-table-column>
          </el-table-column> -->
        </el-table>
      </div>
    </div>
    <!-- 分析参数 v-show="currentTab=='0'"-->
    <div v-show="currentTab2 == '3'">
      <div class="eldesign classtable" style="margin-top: 10px">
        <el-table
          :data="outParams"
          border
          style="width: 100%; "
          :header-cell-class-name="headerCellClassName"
        >
          <el-table-column type="index" width="70" label="编号" />
          <el-table-column prop="name" label="参数名称">
            <!-- <template #default="{ row }">
                      <el-input v-model="row.name" @change="handleEdit(row)" />
                    </template> -->
          </el-table-column>
          <el-table-column prop="value" label="参数值">
            <template #default="{ row }">
              <el-input v-model="row.value" />
            </template>
          </el-table-column>
          <el-table-column prop="flag" label="启用" width="100">
            <template v-slot="scope">
              <el-checkbox
                :false-label="0"
                :true-label="1"
                
                v-model="scope.row.flag"
              />
            </template>
          </el-table-column>
        </el-table>
      </div>
    </div>
  </div>
</template>

<script setup>
import { ref, onMounted, reactive, provide, nextTick } from "vue"
import { ElMessage, ElButton, ElDialog, ElSelect } from "element-plus"
import { Edit, CaretBottom } from "@element-plus/icons-vue"
import fileUploads from '../components/fileuploads.vue'
import cloudChart from "../threejsView/index.vue" // 云图
import { request, uploadFile } from "@/utils/request"
import emitter from "@/utils/emitter"

import meshFile from "@/assets/img/meshFile.png";
import jiegoucanshu from "@/assets/img/jiegoucanshu.png";
import configParams from "@/assets/img/configParams.png";
import analysisParams from "@/assets/img/analysisParams.png";

let fid = ref()
let formLabelWidth1 = ref(170)
let formLabelWidth120 = ref(120)
let bdfData = ref()
let currentTab2=ref(0);

let pid = ref();
let wid = ref();
let tacsid = ref();

let tabslist2= ref([
  { id: '0', name: '网格文件' ,imgSrc:meshFile},
  { id: '1', name: '结构参数' ,imgSrc:jiegoucanshu},
  { id: '2', name: '设置参数' ,imgSrc:configParams},
  { id: '3', name: '分析参数' ,imgSrc:analysisParams},

])

const tacsfileSrc = new URL('@/assets/flowimg/ffdFileSave.png', import.meta.url).href;


let TACSactiveNames = ref(['1','2']);

let jiegouNum = ref(0);

let tacsvalue = ref({
  proname:'CRM',
  rho:'2780.0',
  e:'73.1e9',
  nu:'0.33',
  ys:'262.0e6',
  useffd: 1,
  l2convergence:'1e3',
  l2convergencerel:'1e3'
})

let writesolution = ref(1);

let fname = ref('')

let inParams=ref([
  {
    code:'thickness',
    name: '厚度分布',
    value: '0.005',
    flag: 1,
    con: ''
  },
  {
    code:'thickness',
    name: '厚度分布',
    value: '0.003',
    flag: 1,
    con: ''
  },
  {
    code:'thickness',
    name: '厚度分布',
    value: '0.003',
    flag: 1,
    con: ''
  },
  {
    code:'thickness',
    name: '厚度分布',
    value: '0.003',
    flag: 1,
    con: ''
  },
  {
    code:'thickness',
    name: '厚度分布',
    value: '0.003',
    flag: 1,
    con: ''
  },
  {
    code:'thickness',
    name: '厚度分布',
    value: '0.003',
    flag: 1,
    con: ''
  },
  {
    code:'thickness',
    name: '厚度分布',
    value: '0.003',
    flag: 1,
    con: ''
  },
  {
    code:'thickness',
    name: '厚度分布',
    value: '0.003',
    flag: 1,
    con: ''
  },
  {
    code:'thickness',
    name: '厚度分布',
    value: '0.003',
    flag: 1,
    con: ''
  },
  {
    code:'thickness',
    name: '厚度分布',
    value: '0.003',
    flag: 1,
    con: ''
  },
  {
    code:'thickness',
    name: '厚度分布',
    value: '0.003',
    flag: 1,
    con: ''
  },
  {
    code:'thickness',
    name: '厚度分布',
    value: '0.003',
    flag: 1,
    con: ''
  },
  {
    code:'thickness',
    name: '厚度分布',
    value: '0.003',
    flag: 1,
    con: ''
  },
  {
    code:'thickness',
    name: '厚度分布',
    value: '0.003',
    flag: 1,
    con: ''
  },
  {
    code:'thickness',
    name: '厚度分布',
    value: '0.003',
    flag: 1,
    con: ''
  },
  {
    code:'thickness',
    name: '厚度分布',
    value: '0.003',
    flag: 1,
    con: ''
  },
])

let outParams=ref([
  {
    code:'mass',
    name: '结构质量',
    value: 13972.2123,
    flag:'1'
  },
  {
    code:'ks_vmfailure',
    name: 'KS聚合应力',
    value: 0.3337,
    flag:'1'
  },
  {
    code:'maxdeform',
    name: '最大变形',
    value: 0.0,
    flag: '1'
  },
])

let percentage = ref(0)
let uploadStatus = ref('')

// 控制进度条显隐
const showProgress = computed(() => percentage.value > 0 && percentage.value <= 100);

let canvasHeight = ref("400px");
let isLoading = ref(false); // 控制 loading 状态
let websock = shallowRef(null);
let times = ref({
  lockReconnect: false, //是否真正建立连接
  timeout: 60 * 1000, //30秒一次心跳
  heartBeatInterval: 30 * 1000, // 添加心跳发送间隔(30秒发一次)
  timeoutObj: null, //心跳倒计时
  serverTimeoutObj: null, //
  timeoutnum: null, //断开重连倒计时
})

// 更新进度条
const updatePercentage = (newValue) => {
  percentage.value = newValue
}
// 更新上传状态
const getUploadStatus = (newValue) => {
  uploadStatus.value = newValue
}

const selectTab2=(index)=>{
  currentTab2.value = index;
}

const headerCellClassName = ({ column }) => {
  // console.log('列：',column.property)
  if (column.property === 'name') {
    console.log('yanse',column.property)
    return 'header-blue';
  } else if (column.property === 'value') {
    return 'header-green';
  } else if (column.property === 'flag') {
    return 'header-yellow';
  }
  return '';
};

const addJiegou = () => {
  const targetLength = jiegouNum.value
  const currentLength = inParams.value.length

  if (targetLength > currentLength) {
    const diff = targetLength - currentLength
    for (let i = 0; i < diff; i++) {
      inParams.value.push({
        code: 'thickness',
        name: '厚度分布',
        value: '0.003',
        flag: 1,
        con: ''
      })
    }
  } else if (targetLength < currentLength) {
    const diff = currentLength - targetLength
    inParams.value.splice(-diff, diff)
  }
}

const gettacs = (id,nowid) => {
  pid.value = id;
  if(nowid){
    wid.value = nowid;
  }
  // console.log('pid-1:',pid.value)
  const params = {
    transCode: "MDO0066",
    pid: pid.value,
    wid: wid.value
  };
  request(params).then((res) => {
    if (res.hasOwnProperty("tacsid")) {
      gettacsAssign(res);
      emitter.emit('tacsidFromTACS', tacsid);
      // 默认加载cgns文件
      if (res.fid) {
        openWebSocket(res.fid);
      }
    }
  })
  .catch((err) => {
      console.log('TACS初始化失败err:',err)
      ElMessage.error('TACS初始化失败')
    })
}

const gettacsAssign = (data) => {
  // console.log('getfsiAssign-data:', data);
  pid.value = data.pid;
  tacsid.value = data.tacsid;
  fid.value = data.fid;
  fname.value = data.fname;
  tacsvalue.value.proname = data.proname;
  tacsvalue.value.rho = data.rho;
  tacsvalue.value.e = data.e;
  tacsvalue.value.nu = data.nu;
  tacsvalue.value.ys = data.ys;
  tacsvalue.value.useffd = data.useffd;
  tacsvalue.value.l2convergence = data.l2convergence;
  tacsvalue.value.l2convergencerel = data.l2convergencerel;
  writesolution.value = data.writesolution;
  // inParams.value = parseStringToArray(data.inParams);
  outParams.value = data.outParams;
  applyValueStringToParams(inParams,data.thickness);
}

const applyValueStringToParams = (params, valueStr) => {
  const values = valueStr.split(',').map(Number); // 把字符串拆成数字数组
  params.value.forEach((item, index) => {
    if (index < values.length) {
      item.value = values[index];
    }
  });
}



const convertToStringArray = (result, Data) => {
  console.log('Data:', Data);

  // 安全检查 Data，确保它是一个数组
  if (!Array.isArray(Data)) {
    console.error('Data should be an array');
    return result; // 返回原 result 或者根据需要返回其他默认值
  }

  result = Data.map(row => {
    // 获取每一行的 `code`, `name`, `value` 和 `flag`
    const code = row.code || ' ';
    const name = row.name || ' ';
    const value = (row.value === null || row.value === undefined || row.value === '') ? ' ' : row.value;
    const flag = (row.value === null || row.flag === undefined || row.flag === '') ? ' ' : row.flag;

    // 将字段连接为一个以逗号分隔的字符串
    return `${code},${name},${value},${flag}`;
  }).join(';');  // 每行之间用分号分隔

  return result;
}

// "code,name,value#value#value,flag" 格式的字符串
const convertToStringArray1 = (result, Data) => {
  console.log('Data:', Data);

  // 安全检查 Data，确保它是一个数组
  if (!Array.isArray(Data)) {
    console.error('Data should be an array');
    return result; // 返回原 result 或者根据需要返回其他默认值
  }

  if (Data.length === 0) {
    return result; // 如果数组为空，直接返回原 result
  }

  // 获取第一行的 code, name 和 writesolution
  const code = Data[0].code || ' ';
  const name = Data[0].name || ' ';
  const flag = writesolution.value !== undefined && writesolution.value !== null
  ? writesolution.value
  : ' ';

  // 收集所有行的 value，用 # 拼接
  const values = Data.map(row => {
    return (row.value === null || row.value === undefined || row.value === '') ? ' ' : row.value;
  }).join('#');

  // 构建最终字符串
  result = `${code},${name},${values},${flag}`;

  return result;
}

// 将 "code,name,value#value#value,flag" 格式的字符串转回数组格式
const parseStringToArray = (inParamsArray) => {
  if (!Array.isArray(inParamsArray)) return [];
  
  return inParamsArray.map(item => {
    const values = item.value.split('#').map(v => v === ' ' ? '' : v);
    
    return values.map(value => ({
      ...item,        // 保留原对象所有属性
      value: value,   // 覆盖为单个值
    }));
  }).flat(); // 将二维数组展平
}

const gettacssave = (id,nowid) => {
  if(nowid){
    wid.value = nowid
  }
  pid.value = id;
  // console.log("pid:",pid.value);
  const params = {
    transCode: "MDO0067",
    pid: pid.value,
    wid: wid.value,
    proname: tacsvalue.value.proname,
    rho: tacsvalue.value.rho,
    e: tacsvalue.value.e,
    nu: tacsvalue.value.nu,
    ys: tacsvalue.value.ys,
    useffd: tacsvalue.value.useffd,
    l2convergence: tacsvalue.value.l2convergence,
    l2convergencerel: tacsvalue.value.l2convergencerel,
    writesolution: writesolution.value,
    fid: fid.value,
    fname: fname.value,
    // inParams: convertToStringArray1([],inParams.value),
    inParams:'',
    thickness: inParams.value.map(item => item.value).join(','),
    outParams: convertToStringArray([],outParams.value)
  };
  request(params).then((res) => {
    ElMessage({
        message: '保存成功',
        type: 'success',
    })
    gettacs(pid.value,wid.value);
  })
  .catch((err) => {
      ElMessage.error('保存失败')
    })
}

defineExpose({ gettacs, gettacsAssign, gettacssave })

const fetchBdfData = async (fpid) =>{
  isLoading.value = true;
  try {
    const response = await fetch('https://www.adicn.com/airopt/TransServlet', {
      method: 'POST',
      headers: {
        'Content-Type': 'application/json',
      },
      body: JSON.stringify({
        channelNo: 'service',
        clientToken: 'e47b87eec69545559d1e81e56626da68',
        transCode: 'MDO0072',
        userId: '5f06c8bc77234f969d13e160b54c27e3',
        fid: fpid
      }),
    });
  }catch (error) {
    isLoading.value = false;
    console.error("请求失败:", error.response || error);
  }
}
function getUrl(channelNo = 'service') {
  let url = ''
  if (channelNo == 'service') {
    url = '/TransServlet'
  } else if (channelNo == 'manager') {
    url = '/managersvr/TransServlet'
  }
  return url
}

const getBdfData = async (fpid) =>{
  let url = import.meta.env.VITE_BASE_URL + getUrl();
  try {
    const response = await fetch(url, {
      method: 'POST',
      headers: {
        'Content-Type': 'application/json',
      },
      body: JSON.stringify({
        channelNo: 'service',
        clientToken: 'e47b87eec69545559d1e81e56626da68',
        transCode: 'MDO0062',
        userId: '5f06c8bc77234f969d13e160b54c27e3',
        fid: fpid
      }),
    });
    // 解析 JSON 数据
  const data = await response.json(); //
  console.log('接口返回的数据:', data); // 正确打印数据
  bdfData.value = data;
  isLoading.value = false;
  }catch (error) {
    isLoading.value = false;
    console.error("请求失败:", error.response || error);
  }
}

const handleFileUploadSuccess = (data) => {
  //隐藏进度条
  setTimeout(() => {
    percentage.value = 0;
  }, 1000);

  fname.value = data.fname
  fid.value = data.bfid
  console.log("文件上传成功，bfid:", data.bfid, "fname:", data.fname)
  // 开启websocket
  openWebSocket(data.bfid);
  
}

//websockct的连接
const openWebSocket = (fid) => {
  if (websock.value?.readyState === 1) return; // 避免重复创建
  const wsurl = import.meta.env.VITE_WEBSOCKET_URL + fid;
  const ws = new WebSocket(wsurl);
  websock.value = ws;
  ws.onopen = websocketonopen;
  ws.onmessage = websocketonmessage;
  ws.onerror = websocketonerror;
  ws.onclose = websocketclose;
}

// Websoket连接成功事件
const websocketonopen = (res) => {
  console.log("bdfWebSocket连接成功", res);
  // 开启心跳
  start();
  // 调用文件解析
  fetchBdfData(fid.value);
};

// Websoket接收消息事件
const websocketonmessage = (res) => {
  try {
    const receivedData = JSON.parse(res.data);
    console.log('receivedData', receivedData);
    
    if (receivedData.status === 0) {
      console.log("转换成功，准备关闭");
      
      // 1. 清除所有计时器
      clearAllTimers();
      
      // 2. 解除事件监听
      websock.value.onclose = null;
      websock.value.onerror = null;
      
      // 3. 主动关闭（code 1000）
      websock.value.close(1000, "Normal closure");
      
      // 4. 置空引用
      websock.value = null;
      
      // 5. 获取数据
      getBdfData(fid.value);
      return; // 直接返回
    }
  } catch (e) {
    // 非JSON消息（如连接成功的文本提示或心跳回复）
    if (res.data === "建立服务端连接成功！") {
      console.log("WebSocket连接已建立");
    } 
    else if (res.data === "服务端已经接收到消息，msg=heartCheck") {
      console.log("心跳确认");
    }
    else {
      console.warn("未知的非JSON消息:", res.data);
    }
  }
  reset();
};
// Websoket连接错误事件
const websocketonerror = (res) => {
  console.log("连接错误", res);
  websock.close();
  reconnect();
};
// Websoket断开事件
const websocketclose = (res) => {
  console.log("断开连接", res);
  // 只有当非正常关闭时才重连（code 1000=正常关闭）
  if (res.code !== 1000) {
    reconnect();
  }
};

// 心跳包
const reconnect = () => {
  // 增加多个防护条件
  if (
    times.value.lockReconnect ||
    websock.value?.readyState === 1 ||
    !adflowvalue.value?.fid
  ) return;

  console.log("尝试重连...");
  times.value.lockReconnect = true;
  
  clearTimeout(times.value.timeoutnum);
  times.value.timeoutnum = setTimeout(() => {
    if (!websock.value || websock.value?.readyState > 1) {
      openWebSocket(fid.value);
    }
    times.value.lockReconnect = false;
  }, 10000);
};

const reset = () => {
  //重置心跳
  clearTimeout(times.value.timeoutObj);
  clearTimeout(times.value.serverTimeoutObj);
  start();
}

const start = () => {
  clearTimeout(times.value.timeoutObj);
  clearTimeout(times.value.serverTimeoutObj);
  
  // 增加连接状态检查
  if (!websock.value || websock.value.readyState !== 1) return;
  
  times.value.timeoutObj = setTimeout(() => {
    if (websock.value?.readyState === 1) {
      websock.value.send("heartCheck");
      
      times.value.serverTimeoutObj = setTimeout(() => {
        if (websock.value?.readyState === 1) {
          websock.value.close(1006, "Heartbeat timeout");
        }
      }, times.value.timeout);
    }
  }, times.value.heartBeatInterval);
}

const clearAllTimers = () => {
  clearTimeout(times.value.timeoutObj);
  clearTimeout(times.value.serverTimeoutObj);
  clearTimeout(times.value.timeoutnum);
  times.value.lockReconnect = true; // 永久锁定重连
};

</script>

<style scoped lang="scss">

:deep(.collapse-title) {
  flex: 1 0 90%;
  order: 1;
  text-align: left;
}

:deep(.collapse-title) .el-collapse-item__header {
  flex: 1 0 auto;
  order: -1;
}
</style>