<template>
  <el-container>
    <splitpanes class="default-theme diysplitpanes">
      <pane min-size="10" size="20" max-size="50" class="custom-aside">
        <el-tabs
          v-model="activeName"
          type="border-card"
          class="full-height-tabs"
          @tab-click="handleTabclick"
        >
          <!-- 组件区域 -->
          <el-tab-pane label="Library" name="Liberal">
            <el-collapse v-model="colactiveNames">
              <el-collapse-item
                v-for="item in collapseData"
                :key="item.ftypecode"
                :title="item.ftypedesc"
                :name="String(item.ftypecode)"
              >
                <div class="coms-container">
                  <div
                    v-for="com in item.coms"
                    :key="com.comId"
                    class="com-item"
                    @dragstart="onDragStart($event, 'default', com)"
                    :draggable="true"
                  >
                    <img
                      :src="getImage(com.image) || getImgPath('temp.png')"
                      alt="component image"
                      class="com-image"
                    />
                    <div class="com-name">{{ com.name }}</div>
                  </div>
                </div>
              </el-collapse-item>
            </el-collapse>
          </el-tab-pane>

          <el-tab-pane label="Project" name="Project">
            <!-- 使用自定义图标和垂直虚线 -->
            <ProjectTree
              :data="treeData"
              :useCustomExpandIcon="true"
              :nodeIcon="systemIcon"
              :expandIcon="expandIcon"
              :collapseIcon="collapseIcon"
              :treeProps="{
                label: 'label',
                children: 'children',
                isLeaf: 'isLeaf'
              }"
              @node-click="handleNodeClick"
            />
            <!-- 使用 Element Plus 默认箭头（无前置图标和虚线） -->
            <!-- <ProjectTree :data="treeData" :useCustomExpandIcon="false" @node-click="handleNodeClick" /> -->
          </el-tab-pane>
          <el-tab-pane label="Result" name="Result">
            <el-empty v-if="activities.length === 0" description="暂无数据" />
            <el-timeline v-else>
              <el-timeline-item
                v-for="(activity, index) in activities"
                center
                :key="index"
                :color="selectedIndex === index ? '#67C23A' : ''"
                size="normal"
                :timestamp="activity.timestamp"
                @click="handleTimelineItemClick(index)"
              >
                {{ activity.content }}
              </el-timeline-item>
            </el-timeline>
          </el-tab-pane>
        </el-tabs>
      </pane>
      <!-- canvas区域 -->
      <pane class="custom-main">
        <splitpanes class="default-theme" horizontal>
          <pane min-size="50" size="75" max-size="100" class="flow-pane">
            <div class="main-header">
              <div class="header-content">
                <div class="image-container">
                  <img :src="topoIcon" alt="Topology Image" />
                </div>
                <div class="text-container">
                  <span>Topology</span>
                </div>
              </div>
              <TopoButtonBar 
              @run-button-click="btnfunc"
              @open-simulationData-dialog="handleOpenSimulationDataDialog"
              @button-click="handleTopoButtonClick"
              @mode-switch="handleTopoModeSwitch"
              />
            </div>
            <!-- <div class="main-header">
              <div class="topologyStyle">Topology</div> -->
              <!-- <el-tabs type="border-card">
                <el-tab-pane label="Topology">
                  <el-space :size="spacesize" class="spaceclass">
                    <el-button
                      title="放大"
                      @click="zoomIn"
                      class="custom-icon-button"
                    >
                      <el-icon><ZoomIn /></el-icon>
                    </el-button>
                    <el-button
                      title="缩小"
                      @click="zoomOut"
                      class="custom-icon-button"
                    >
                      <el-icon><ZoomOut /></el-icon>
                    </el-button>
                    <el-button
                      title="自适应"
                      @click="fitView"
                      class="custom-icon-button"
                    >
                      <el-icon><FullScreen /></el-icon>
                    </el-button>

                    <el-tooltip content="重置" placement="top">
                      <el-button
                        title="重置"
                        @click="resetTransform"
                        class="custom-icon-button"
                      >
                        <changebak name="reset" />
                      </el-button>
                    </el-tooltip>

                    <el-tooltip content="背景切换" placement="top">
                      <el-button
                        title="背景切换"
                        @click="toggleDarkMode"
                        class="custom-icon-button"
                      >
                        <changebak v-if="dark" name="sun" />
                        <changebak v-else name="moon" />
                      </el-button>
                    </el-tooltip>

                    <el-tooltip content="保存" placement="top">
                      <el-button
                        @click="saveproject"
                        class="custom-icon-button"
                      >
                        <el-icon class="btn-icon" :color="iconcolor"
                          ><UploadFilled
                        /></el-icon>
                      </el-button>
                    </el-tooltip>
                  </el-space>
                </el-tab-pane>
              </el-tabs> -->
            <!-- </div> -->
            <div class="flow-content" ref="flowContentRef">
              <vueflow 
                ref="vueflowRef" 
                :jobId="jobId"
                :showGrid="buttonStates.showGrid"
                :fixedGrid="buttonStates.fixedGrid"
                :isSelectMode="modeSwitch"
                @save="handleSave"
                @copy="handleCopy"
                @cut="handleCut"
                @paste="handlePaste"
              />
              <Ruler :visible="buttonStates.showRuler" :container-ref="flowContentRef" />
            </div>
          </pane>
          <pane min-size="0" size="25" max-size="50">
            <el-tabs type="border-card" style="height: 100%">
              <el-tab-pane label="日志" style="height: 100%">
                <el-input
                  v-model="logContent"
                  type="textarea"
                  id="textarea_id"
                  spellcheck="false"
                  style="height: 100%; font-size: 12px"
                  :autosize="false"
                  resize="none"
                />
              </el-tab-pane>
            </el-tabs>
          </pane>
        </splitpanes>
      </pane>
    </splitpanes>
  </el-container>
    <!-- 模拟数据弹窗 -->
    <SLDataDialog ref="SLdatadialogref" @selectRunType="handleSelectRunType" />
    <!-- 运行弹窗 -->
    <RunDialog ref="RunDialogRef" :runData="arrobj" />

    <!-- 单位系统弹窗 -->
    <SystemUnitDialog
      :visible="showSystemUnitDialog"
      @update:visible="showSystemUnitDialog = $event"
      @confirm="handleSystemUnitConfirm"
    />
    <!-- 个人单位系统弹窗 -->
    <PersonUnitDialog
      :visible="showPersonUnitDialog"
      @update:visible="showPersonUnitDialog = $event"
      @confirm="handlePersonUnitConfirm"
    />
</template>

<script setup>
import { Splitpanes, Pane } from "splitpanes"
import "splitpanes/dist/splitpanes.css"
import { request, getImage } from "@/utils/request"
import emitter from '@/utils/emitter';
import { ElMessage } from "element-plus"
import { useProjectStore } from "@/store/project"
import { useI18n } from "vue-i18n"
import vueflow from "./vueflow/index.vue"
import useDragAndDrop from "./vueflow/useDnD"
import { ProjectTree } from "@/components/ProjectTree"
import TopoButtonBar from "@/components/layout/TopoButtonBar.vue"
import Ruler from '@/components/Ruler.vue'
import {
  ZoomIn,
  ZoomOut,
  FullScreen,
  Lock,
  Unlock,
  DocumentDelete,
  Delete,
  UploadFilled,
  Histogram,
  DeleteFilled,
  Crop,
  Close
} from "@element-plus/icons-vue"
import changebak from "./vueflow/changebak.vue"
import SLDataDialog from "./dialog/SLDataDialog.vue"
import RunDialog from "./dialog/RunDialog.vue"
import { useVueFlow } from "@vue-flow/core"
import SystemUnitDialog from "@/components/SystemUnitDialog.vue"
import PersonUnitDialog from "@/components/PersonUnitDialog.vue"
import systemIcon from "@/assets/img/treeSystemIcon.png"
import topoIcon from "@/assets/icons/topo.png"
import expandIcon from "@/assets/img/treeExpand.png"
import collapseIcon from "@/assets/img/treeCollapse.png"

const { zoomIn, zoomOut, fitView, setInteractive } = useVueFlow()

const { t, locale } = useI18n()

const projectStore = useProjectStore()

const { onDragStart, onDragLeave, treeobj, onDrop } = useDragAndDrop()

// 树中单元系统的弹窗显示控制
const showSystemUnitDialog = ref(false)
const showPersonUnitDialog = ref(false)
// 存储 SystemUnitDialog 的 tableData
const systemUnitData = ref([])
const flowContentRef = ref(null)

// 项目树数据
const treeData = ref([
  {
    id: "root",
    label: t("treeData.system"),
    children: [
      {
        id: "systemSetup",
        label: t("treeData.systemSetup"),
        children: [
          {
            id: "systemUnit",
            label: t("treeData.systemUnitView"),
            children: []
          },
          {
            id: "personUnit",
            label: t("treeData.personUnitSetting"),
            children: []
          }
        ]
      }
    ]
  }
])

// 项目树节点点击事件
const handleNodeClick = ({ node, data, event }) => {
  console.log("Node clicked:", node, data, event)
  if (node.id === "systemUnit") {
    console.log("System Unit clicked")
    showSystemUnitDialog.value = true
  } else if (node.id === "personUnit") {
    showPersonUnitDialog.value = true
  }
}

// 单元系统弹窗确认事件
const handleSystemUnitConfirm = () => {
  showSystemUnitDialog.value = false
}

// 个人单元弹窗确认事件
const handlePersonUnitConfirm = () => {
  showPersonUnitDialog.value = false
}

const getImgPath = (url) => {
  return new URL(`../../assets/img/${url}`, import.meta.url).href
}

let pid = computed(() => projectStore.pid || "")

let spacesize = ref(10)
let colactiveNames = ref(["1"])
let collapseData = ref()
const vueflowRef = ref()
const dark = ref(false)
let iconcolor = ref("#000")

const activeName = ref("Liberal")

const selectedIndex = ref(null)
const activities = ref([])

const jobId = ref()

const SLdatadialogref = ref(null)
const RunDialogRef = ref(null)
const modeSwitch = ref(true) // 连接模式开关
const buttonStates = ref({ // 拓扑按钮状态
  showGrid: false,
  fixedGrid: false
})

const headerbuttons = ref([
  { type: "button", img: "newproject.png", name: "temp" },
  { type: "button", img: "save.png", name: "temp" },
  { type: "button", img: "importpro.png", name: "temp" },
  { type: "button", img: "exportpro.png", name: "temp" },
  { type: "divider" },
  { type: "button", img: "back.png", name: "temp" },
  { type: "button", img: "goon.png", name: "temp" },
  { type: "divider" },
  { type: "button", img: "temp.png", name: "temp" },
  { type: "divider" },
  { type: "button", img: "monidata.png", name: "SLdata" },
  { type: "divider" },
  { type: "button", img: "run.png", name: "run" },
  { type: "button", img: "stop.png", name: "stop" },
  { type: "button", img: "monitor.png", name: "monitor" },
  { type: "button", img: "temp.png", name: "temp" },
  { type: "button", img: "temp.png", name: "temp" },
  { type: "button", img: "temp.png", name: "temp" },
  { type: "button", img: "temp.png", name: "temp" },
  { type: "divider" },
  { type: "button", img: "text.png", name: "temp" },
  { type: "button", img: "text2.png", name: "temp" },
  { type: "button", img: "text3.png", name: "temp" },
  { type: "divider" },
  { type: "button", img: "temp.png", name: "temp" }
])

let mainbuttons = ref([
  { img: "temp.png" },
  { img: "temp.png" },
  { img: "temp.png" },
  { img: "temp.png" },
  { img: "temp.png" },
  { img: "temp.png" },
  { img: "temp.png" },
  { img: "temp.png" },
  { img: "temp.png" }
])

const logContent = ref("")
const arrobj = ref([])
let websock = ref(null)
let times = ref({
  lockReconnect: false, //是否真正建立连接
  timeout: 28 * 1000, //30秒一次心跳
  timeoutObj: null, //心跳倒计时
  serverTimeoutObj: null, //
  timeoutnum: null //断开重连倒计时
})

// 用于分开不同求解运行
const runtype = ref("")

// 获取组件数据
const getComponent = () => {
  const params = {
    transCode: "ES1001",
    pid: pid.value
  }
  request(params)
    .then((res) => {
      console.log(res)
      collapseData.value = res.rows
      console.log("zujian:", collapseData.value)
    })
    .catch((err) => {
      ElMessage.error(err.returnMsg)
    })
}

const resetTransform = () => {
  if (vueflowRef.value) {
    vueflowRef.value.resetTransform()
  }
}

const toggleDarkMode = () => {
  if (vueflowRef.value) {
    vueflowRef.value.toggleDarkMode()
  }
}

const saveproject = () => {
  if (vueflowRef.value) {
    vueflowRef.value.saveproject()
  }
}
const removeNode = () => {
  if (vueflowRef.value) {
    vueflowRef.value.removeNode()
  }
}
const removeEdge = () => {
  if (vueflowRef.value) {
    vueflowRef.value.removeEdge()
  }
}

const confirmDelete = () => {
  if (vueflowRef.value) {
    vueflowRef.value.confirmDelete()
  }
}

// 处理 topoButtonBar 触发的 open-data-dialog 事件
const handleOpenSimulationDataDialog = (pid) => {
  if (pid) {
    SLdatadialogref.value?.openDialog?.(pid);
  }
};

const btnfunc = (name) => {
  if (name === "run") {
    if (runtype.value === "") {
      ElMessage.error("请先设置模拟类型")
      return
    } else if (runtype.value === "Incompressible Transient") {
      // 处理不可压缩瞬态的逻辑
      RunDialogRef.value?.openDialog?.()
    } else if (runtype.value === "Incompressible Steady State") {
      // 处理不可压缩稳态的逻辑
      runProject()
    } else if (runtype.value === "Compressible Transient") {
      // 处理可压缩瞬态的逻辑
    } else if (runtype.value === "Compressible Steady State") {
      // 处理可压缩稳态的逻辑
      runProject()
    } else {
      ElMessage.error("未知的模拟类型")
      return
    }
  } else if (name === "SLdata") {
    nextTick(() => {
      SLdatadialogref.value?.openDialog?.(pid.value)
    })
  }
}

const runProject = () => {
  const params = {
    transCode: "ES0013",
    pid: pid.value
  }
  request(params)
    .then((res) => {
      ElMessage.success("开始运行")
    })
    .catch((err) => {
      ElMessage.error(err.returnMsg)
    })
}

const handleSelectRunType = (type) => {
  runtype.value = type
  projectStore.setruntype(type)
}

// 获取结果列表
const getresultlist = () => {
  const params = {
    transCode: "ES0014",
    pid: pid.value
  }
  request(params)
    .then((res) => {
      console.log("获取结果列表成功", res)
      // 处理结果列表数据
      activities.value = res.rows.map((item) => ({
        jobId: item.jobId,
        content: "结果" + item.ser,
        timestamp: item.startTime.split(" +")[0]
      }))
    })
    .catch((err) => {
      console.error("获取结果列表失败", err)
      ElMessage.error("获取结果列表失败")
    })
}

const handleTabclick = (tab, event) => {
  console.log("tab clicked:", tab.props.name)
  if (tab.props.name === "Result") {
    getresultlist()
  }
}

const handleTimelineItemClick = (index) => {
  selectedIndex.value = index
  console.log("Timeline item clicked:", activities.value[index])
  jobId.value = activities.value[index].jobId
  vueflowRef.value?.asideDataref?.getresultData(jobId.value)
}

// 处理 topoButtonBar 触发的 button-click 事件
const handleTopoButtonClick = ({ action, isActive }) => {
  buttonStates.value[action] = isActive !== undefined ? isActive : buttonStates.value[action]
  // 根据 action 调用 VueFlow 对应方法
  switch (action) {
    case 'zoomIn':
      zoomIn()
      break
    case 'zoomOut':
      zoomOut()
      break
    case 'fitView':
      fitView()
      break
    case 'actualSize':
      // 重置为实际大小（缩放 1x，位置 0,0）
      if (vueflowRef.value) {
        vueflowRef.value.resetTransform()  // 假设你的 vueflow 组件暴露了 resetTransform 方法
      } else {
        // 备选：直接使用 useVueFlow 的 setViewport
        const { setViewport } = useVueFlow()
        setViewport({ x: 0, y: 0, zoom: 1 })
      }
      break
    case 'drag':
      setInteractive(true)
      break
    default:
      console.log(`Unhandled action: ${action}`)
      break
  }
}

// 处理 topoButtonBar 触发的 mode-switch 事件
const handleTopoModeSwitch = (value) => {
  modeSwitch.value = value
  // setInteractive(!value)
  console.log(value ? "切换到选择模式" : "切换到连接模式")
}

// 新增事件处理函数
const handleSave = () => {
  if (vueflowRef.value) {
    vueflowRef.value.saveproject();
  }
};

const handleCopy = () => {
  if (vueflowRef.value) {
    vueflowRef.value.copyNodes();
  }
};

const handleCut = () => {
  if (vueflowRef.value) {
    vueflowRef.value.cutNodes();
  }
};

const handlePaste = () => {
  if (vueflowRef.value) {
    vueflowRef.value.pasteNodes();
  }
};


//websockct的连接
function initWebSocket() {
  //初始化weosocket
  const wsurl = import.meta.env.VITE_WEBSOCKET_URL + pid.value
  websock = new WebSocket(wsurl)
  websock.onopen = websocketonopen
  websock.onmessage = websocketonmessage
  websock.onerror = websocketonerror
  websock.onclose = websocketclose
}

// Websoket连接成功事件
const websocketonopen = (res) => {
  console.log("WebSocket连接成功", res)
  start()
}

// Websoket接收消息事件
const websocketonmessage = (res) => {
  console.log("websocket接受消息:", res.data)
  if (res.data.indexOf("{") !== -1) {
  } else {
    if (res.data.indexOf("——开始") !== -1) {
      arrobj.value = [] // 清空数据点数组
    }
    if (res.data.indexOf("——成功") !== -1) {
      getresultlist() //刷新结果列表
      const timer = setTimeout(function () {
        console.log("关闭定时器")
      }, 10000)
    }
    if (res.data.indexOf("msg=heartChec") == -1) {
      // 去除空行
      const cleanedLog = res.data
        .split("\n")
        .filter((line) => line.trim() !== "")
        .join("\n")
      logContent.value = logContent.value + "\n" + cleanedLog
      let textarea = document.getElementById("textarea_id")
      textarea.scrollTop = textarea.scrollHeight
    }
    // 提取数据点
    const lines = res.data.split("\n")
    for (const line of lines) {
      const match = line.match(/value:\s*([\d.]+);\s*([\d.]+);/)
      if (match) {
        const step = parseFloat(match[1])
        const value = parseFloat(match[2])
        arrobj.value.push({ step, value })
      }
    }
    // console.log('arrobjvalue',arrobj.value)
  }

  reset()
}

// Websoket连接错误事件
const websocketonerror = (res) => {
  console.log("连接错误", res)
  websock.close()
  reconnect()
}
// Websoket断开事件
const websocketclose = (res) => {
  console.log("断开连接", res)
}

// 心跳包
const reconnect = () => {
  if (times.value.lockReconnect) return
  times.value.lockReconnect = true
  //没连接上会一直重连，设置延迟避免请求过多
  times.value.timeoutnum && clearTimeout(times.value.timeoutnum)
  times.value.timeoutnum = setTimeout(function () {
    //新连接
    initWebSocket()
    times.value.lockReconnect = false
  }, 10000)
}
const reset = () => {
  //重置心跳
  clearTimeout(times.value.timeoutObj)
  clearTimeout(times.value.serverTimeoutObj)
  start()
}
const start = () => {
  //开启心跳
  times.value.timeoutObj && clearTimeout(times.value.timeoutObj)
  times.value.serverTimeoutObj && clearTimeout(times.value.serverTimeoutObj)
  times.value.timeoutObj = setTimeout(function () {
    //这里发送一个心跳，后端收到后，返回一个心跳消息
    if (websock.readyState == 1) {
      //如果连接正常
      websock.send("heartCheck")
    } else {
      //否则重连
      reconnect()
    }
    times.value.serverTimeoutObj = setTimeout(function () {
      // 超时关闭
      websock.close() //如果onclose会执行reconnect，我们执行ws.close()就行了.如果直接执行reconnect 会触发onclose导致重连两次
    }, times.value.timeout)
  }, times.value.timeout)
}

const getlogs = () => {
  const params = {
    transCode: "ES0017",
    pid: pid.value
  }
  request(params)
    .then((res) => {
      // console.log("获取日志成功", res)
      logContent.value = res.logs
        .split("\n")
        .filter((line) => line.trim() !== "")
        .join("\n")
      // 自动滚动日志到底部
      let textarea = document.getElementById("textarea_id")
      textarea.scrollTop = textarea.scrollHeight
    })
    .catch((err) => {
      console.error("获取日志失败", err)
      ElMessage.error("获取日志失败")
    })
}

onMounted(() => {
  runtype.value = projectStore.runtype || ""

  getComponent()

  setTimeout(function () {
    initWebSocket()
    getlogs()
  }, 1500)

  emitter.on('save', handleSave);
  emitter.on('copy', handleCopy);
  emitter.on('cut', handleCut);
  emitter.on('paste', handlePaste);
});

onUnmounted(() => {
  emitter.off('save', handleSave);
  emitter.off('copy', handleCopy);
  emitter.off('cut', handleCut);
  emitter.off('paste', handlePaste);
});

// onBeforeUnmount(() => {
//   websock?.close()
//   clearTimeout(times.value.timeoutObj)
//   clearTimeout(times.value.serverTimeoutObj)
// })
</script>

<style scoped>
.flow-pane {
  display: flex;
  flex-direction: column;
  height: 100%;
}

.main-header {
  background: #edf2fa;
  border-radius: 0px 0px 0px 0px;
  border: 2px solid #eeeeee;
}

.header-content {
  display: flex;
  align-items: center;
  justify-content: space-between;
  max-width: 110px;
  background-color: #ffffff;
  padding: 3px;
  margin: 0;
  border-top: #075679 3px solid;
}

.image-container {
  flex: 1;
  max-width: 45%;
  padding-right: 5px;
}

.text-container{
  padding: 0 5px 0 0;
  font-size: 16px;
}

.diysplitpanes {
  overflow: auto;
}

.main-header :deep(.el-tabs--border-card > .el-tabs__content) {
  padding: 5px 15px;
}

.main-header :deep(.el-tabs__content) {
  background: #ffffff;
  border-radius: 0px 0px 0px 0px;
  border: 1px solid #d8d8d8;
}

.coms-container {
  display: flex;
  flex-wrap: wrap;
  gap: 10px;
}
.com-item {
  display: flex;
  justify-content: start;
  align-items: center;
  width: 130px;
}
.com-image {
  width: 24px;
  height: 24px;
  object-fit: contain;
}
.com-name {
  font-size: 11px;
}

.flow-content {
  width: 100%;
  flex: 1;
  background: #ffffff;
  position: relative;
  overflow: hidden;
}

.btn-icon {
  font-size: 16px;
}

.topologyStyle {
  width: 80px;
  height: 30px;
  font-size: 18px;
  border-top: 3px solid #77c5e6;
  background-color: #ffffff;
}
</style>