<script setup lang="tsx">
import { onMounted, ref, watch, onBeforeUnmount } from 'vue'
import axios from 'axios'

import Progress from '@/renderer/pages/ListNum/ColorfulProgress.vue'

const httpServerPort = ref<number | null>(null)

onMounted(() => {
  window.mainApi.send('msgRequestGetServerPort')

  window.mainApi.receive('msgReceivedServerPort', (event, port) => {
    httpServerPort.value = port
  })
})

class ProgressBarHandler {
  fixedNumber = 3
  percent = ref(0)
  maxNumber = ref(100)
  progressWidth = ref(10)
  targetValue = ref(0.0)
  targetValueString = ref(this.percent.value.toFixed(this.fixedNumber))

  constructor(setMaxNumber: number, setDefaultPercent: number) {
    this.maxNumber.value = setMaxNumber
    this.percent.value = setDefaultPercent
    this.updatePercentToTargetValue()

    watch(this.targetValue, (newPercent) => {
      this.updateTargetValueString(newPercent)
    })

    watch(this.percent, (newPercent) => {
      this.updateTargetValue(newPercent)
    })
  }

  updatePercentToTargetValue() {
    this.updateTargetValueString(this.percent.value)
    this.updateTargetValue(this.targetValue.value)
  }

  updateTargetValue(newValue: number) {
    this.targetValue.value = this.processValue(0.01 * this.maxNumber.value * newValue)
  }

  updateTargetValueString(newValue: number) {
    this.targetValueString.value = this.processValueStringFormat(newValue)
  }

  processValue(rawValue: number): number {
    const processedValue = Math.round(rawValue)
    return +processedValue.toFixed(this.fixedNumber)
  }

  processValueStringFormat(num: number): string {
    const integerPart = Math.floor(num)
    const decimalPart = num - integerPart
    const integerString = integerPart < 10 ? '0' + integerPart : '' + integerPart
    const decimalString = decimalPart.toFixed(this.fixedNumber).slice(2)
    return integerString + '.' + decimalString
  }

  progressMouseUp() {
    this.progressWidth.value = 10
  }

  progressMouseOver() {
    this.progressWidth.value = 20
  }

  progressMouseLeave() {
    this.progressWidth.value = 10
  }

  progressOnIncrease(scale: number) {
    const res = this.percent.value + scale
    this.percent.value = res > 100 ? 100 : res
  }

  progressOnDecline(scale: number) {
    const res = this.percent.value - scale
    this.percent.value = res < 0 ? 0 : res
  }

  progressMouseDown(event: MouseEvent) {
    const adjustLine = event.currentTarget as HTMLElement
    const rect = adjustLine.getBoundingClientRect()
    const initialX = event.clientX

    const updatePercent = (e: MouseEvent) => {
      let x = e.clientX - rect.left
      const dragRange = 0.8 * rect.width
      const dragStart = 0.1 * rect.width
      x = Math.max(Math.min(x, dragStart + dragRange), dragStart)
      this.percent.value = ((x - dragStart) / dragRange) * 100
    }

    const moveHandler = (e: MouseEvent) => {
      if (e.clientX > initialX) {
        this.progressOnIncrease(((e.clientX - initialX) / rect.width) * 100)
      } else {
        this.progressOnDecline(((initialX - e.clientX) / rect.width) * 100)
      }
      updatePercent(e)
    }

    const upHandler = () => {
      document.removeEventListener('mousemove', moveHandler)
      document.removeEventListener('mouseup', upHandler)
    }

    document.addEventListener('mousemove', moveHandler)
    document.addEventListener('mouseup', upHandler)
    updatePercent(event)
  }
}

const defaultBarHandler100 = 5
const defaultBarHandler15000 = 0
const defaultBarHandlerFloat = 0

const BarHandler100 = new ProgressBarHandler(100, defaultBarHandler100)
const BarHandler15000 = new ProgressBarHandler(150, defaultBarHandler15000)
const BarHandlerFloat = new ProgressBarHandler(100, defaultBarHandlerFloat)

const getDeviceValue = () => {
  return computeDeviceValue(
    BarHandler15000.targetValue.value,
    BarHandler100.targetValue.value,
    BarHandlerFloat.targetValue.value
  )
}

const computeDeviceValue = (value15000: number, value100: number, valueFloat: number) => {
  return value15000 * 100 + value100 + valueFloat / 100
}

const getDeviceValueString = () => {
  return deviceValue.value.toFixed(3)
}

const initDeviceValue = () => {
  return computeDeviceValue(defaultBarHandler15000, defaultBarHandler100, defaultBarHandlerFloat)
}

const initDeviceValueString = () => {
  return initDeviceValue().toFixed(3)
}

const deviceValue = ref(initDeviceValue())
const deviceValueString = ref(initDeviceValueString())

watch(BarHandler100.targetValueString, (_) => {
  updateDeviceValueData()
})

watch(BarHandler15000.targetValueString, (_) => {
  updateDeviceValueData()
})

watch(BarHandlerFloat.targetValueString, (_) => {
  updateDeviceValueData()
})

const updateDeviceValueData = () => {
  deviceValue.value = getDeviceValue()
  deviceValueString.value = getDeviceValueString()
}

const height = ref(200)
let initialY = 0 // 初始的鼠标Y坐标
let initialHeight = 0 // 开始调整时的元素高度

const isDragging = ref(false)

const startResize = (event: MouseEvent) => {
  initialY = event.clientY
  initialHeight = height.value
  isDragging.value = true // 设置为正在拖动

  document.addEventListener('mousemove', onResize)
  document.addEventListener('mouseup', stopResize)
}

const onResize = (event: MouseEvent) => {
  const deltaY = initialY - event.clientY // 计算鼠标的垂直移动距离
  height.value = initialHeight + deltaY // 调整元素的高度
}

const stopResize = () => {
  document.removeEventListener('mousemove', onResize)
  document.removeEventListener('mouseup', stopResize)
  isDragging.value = false // 设置为停止拖动
}

const terminalOutput = ref<string[]>([])

// 定义一个方法，允许在组件内部推送内容到terminalOutput数组
const terminalPush = (content: string) => {
  terminalOutput.value.push(content)
}

const setDeviceValue = async (targetDeviceValue: string) => {
  try {
    terminalPush(`[模拟负载] 尝试将负载设置为 ${targetDeviceValue} Ω`)
    const params = {
      set_resistance: targetDeviceValue
    }
    const url = `http://127.0.0.1:${httpServerPort.value}/instrument/analog_electronic_load/set_resistance`
    const response = await axios.get(url, { params })
    const ifSetSuccess = response.data
    if (ifSetSuccess === 'True' || ifSetSuccess === 'true') {
      terminalPush(`[模拟负载] 负载成功调整为 ${targetDeviceValue} Ω`)
    } else {
      terminalPush(`[模拟负载] 负载调整失败`)
    }
  } catch (error) {
    terminalPush(`[模拟负载] 负载调整失败：${error}`)
  }
}

const updateDeviceValue = () => {
  setDeviceValue(deviceValueString.value)
}
</script>

<template>
  <div class="list-page-3">
    <div class="page">
      <div class="page-up">
        <div class="control-zone">
          <div class="title">
            <div class="text">机上模拟负载: {{ deviceValueString }} Ω</div>
          </div>
          <div class="config-zone">
            <div class="text-line">调整：个位 / 十位</div>
            <div
              class="adjust-line"
              @mouseup="BarHandler100.progressMouseUp"
              @mousedown="BarHandler100.progressMouseDown"
              @mouseover="BarHandler100.progressMouseOver"
              @mouseleave="BarHandler100.progressMouseLeave"
            >
              <Progress
                :width="'80%'"
                :percent="BarHandler100.percent.value"
                :stroke-width="BarHandler100.progressWidth.value"
                :stroke-color="{
                  '0%': '#108ee9',
                  '100%': '#87d068',
                  direction: 'right'
                }"
                :show-info="false"
              />
            </div>
            <div class="text-line">调整：小数位</div>
            <div
              class="adjust-line"
              @mouseup="BarHandlerFloat.progressMouseUp"
              @mousedown="BarHandlerFloat.progressMouseDown"
              @mouseover="BarHandlerFloat.progressMouseOver"
              @mouseleave="BarHandlerFloat.progressMouseLeave"
            >
              <Progress
                :width="'80%'"
                :percent="BarHandlerFloat.percent.value"
                :stroke-width="BarHandlerFloat.progressWidth.value"
                :stroke-color="{
                  '0%': '#108ee9',
                  '100%': '#87d068',
                  direction: 'right'
                }"
                :show-info="false"
              />
            </div>
            <div class="text-line">调整：百位 / 千位</div>
            <div
              class="adjust-line"
              @mouseup="BarHandler15000.progressMouseUp"
              @mousedown="BarHandler15000.progressMouseDown"
              @mouseover="BarHandler15000.progressMouseOver"
              @mouseleave="BarHandler15000.progressMouseLeave"
            >
              <Progress
                :width="'80%'"
                :percent="BarHandler15000.percent.value"
                :stroke-width="BarHandler15000.progressWidth.value"
                :stroke-color="{
                  '0%': '#108ee9',
                  '100%': '#87d068',
                  direction: 'right'
                }"
                :show-info="false"
              />
            </div>
            <div class="btn-zone">
              <div @click="updateDeviceValue" class="btn">
                <div class="text">应用配置</div>
              </div>
            </div>
          </div>
        </div>
      </div>
      <div class="page-down">
        <div class="top-bar">
          <div @mousedown="startResize" class="resizer" :class="{ dragging: isDragging }">
            <div class="flag-bar">
              <div class="text">测试输出终端</div>
            </div>
            <div class="middle"></div>
            <div class="last-time">
              <div class="text"></div>
            </div>
          </div>
        </div>
        <div :style="{ height: height + 'px' }" class="content">
          <div class="terminal-zone">
            <!-- <div class="terminal-left">
                            <div class="select-area">
                            </div>
                        </div> -->
            <div class="terminal-dividing"></div>
            <div class="terminal-right">
              <div class="terminal-output">
                <div class="text" v-for="(text, index) in terminalOutput" :key="index">
                  {{ text }}
                </div>
              </div>
            </div>
          </div>
        </div>
      </div>
    </div>
  </div>
</template>

<style lang="scss">
.list-page-3 {
  width: 100%;
  height: 100%;
  overflow-x: hidden;
  overflow-y: hidden;

  .page {
    width: 100%;
    height: 100%;
    overflow-x: hidden;
    overflow-y: hidden;
    display: flex;
    flex-direction: column;
    justify-content: flex-start;
    align-items: flex-start;
    background-color: white;
    padding: 0;
  }

  .page-up {
    width: 100%;
    height: 100%;
    flex: 1;
    overflow-x: hidden;
    overflow-y: auto;
    display: flex;
    flex-direction: row;
    justify-content: flex-start;
    align-items: flex-start;

    .control-zone {
      width: 100%;
      height: 100%;
      display: flex;
      flex-direction: column;
      justify-content: flex-start;
      align-items: center;
      margin-top: 10vh;
    }

    .title {
      font-size: 35px;
      font-weight: 500;
      margin-bottom: 0;
      margin-bottom: 3vh;
    }

    .config-zone {
      width: 100%;
      display: flex;
      flex-direction: column;
      justify-content: flex-start;
      align-items: center;
    }

    .text-line {
      font-size: 25px;
      font-weight: 500;
      margin-top: 2vh;
      margin-bottom: -2vh;
    }

    .adjust-line {
      width: 100%;
      height: auto;
      padding-top: 3vh;
      padding-bottom: 3vh;
      padding-left: 0;
      padding-right: 0;
      display: flex;
      flex-direction: column;
      justify-content: flex-start;
      align-items: center;
    }

    .btn-zone {
      margin-top: 3vh;
      display: flex;
      flex-direction: row;
      justify-content: flex-start;
      align-items: center;

      .btn {
        width: 105px;
        height: 35px;
        overflow: hidden;
        border: 1px solid #dfdfdf;
        border-radius: 5px;
        display: flex;
        flex-direction: row;
        justify-content: center;
        align-items: center;
        color: black;
        position: relative;
        cursor: pointer;
        transition: all 0.1s cubic-bezier(0.78, 0.14, 0.15, 0.86);
      }

      .btn::after {
        content: '';
        position: absolute;
        width: 100%;
        height: 100%;
        background-color: rgba(255, 255, 255, 1);
        z-index: 3;
        transition: all 0.1s cubic-bezier(0.78, 0.14, 0.15, 0.86);
      }

      .btn:hover {
        background: linear-gradient(to right, #108ee9 0%, #87d068 100%);
        background-color: white;
        color: white;
      }

      .btn:hover::after {
        content: '';
        position: absolute;
        width: 100%;
        height: 100%;
        background-color: rgba(255, 255, 255, 0);
        z-index: 3;
      }

      .text {
        font-size: 20px;
        font-weight: 400;
        z-index: 5;
      }
    }
  }

  .page-down {
    width: 100%;
    // height: 200px;
    background-color: white;
    border-top: 1px solid #dfdfdf;
    position: relative;

    .content {
      width: 100%;
      height: 100%;
      overflow: hidden;
      display: flex;
      align-items: center;
      justify-content: center;
    }

    .top-bar {
      height: auto;
      overflow-y: hidden;

      .resizer {
        cursor: ns-resize; // 调整为垂直调整的鼠标样式
        background-color: white;
        height: 22px; // 调整为较小的高度
        width: 100%; // 确保宽度与父 div 一致
        position: absolute;
        top: 0;
        border-top: 1px solid #dfdfdf;
        border-bottom: 1px solid #dfdfdf;
        display: flex;
        flex-direction: row;
        align-items: center;
        justify-content: flex-start;
        overflow-y: hidden;
      }

      .text {
        color: black;
        font-size: 15px;
      }

      .flag-bar {
        background-color: #2673e3;
        width: 125px;
        height: 32px;
        padding-left: 10px;
        display: flex;
        flex-direction: row;
        align-items: center;
        justify-content: flex-start;
        clip-path: polygon(0% 0%, 100% 0%, 90% 100%, 0% 100%);

        .text {
          color: white;
        }
      }

      .middle {
        flex: 1;
        background-color: red;
      }

      .last-time {
        width: auto;
        height: 100%;
        display: flex;
        flex-direction: row;
        align-items: center;
        justify-content: flex-start;
        padding-right: 15px;
        font-weight: 500;
      }

      .dragging {
        border-top: 6px solid #2673e3;
        height: 34px;
      }
    }
  }

  .terminal-zone {
    width: 100%;
    height: 100%;
    overflow-x: hidden;
    overflow-y: hidden;
    display: flex;
    flex-direction: row;
    justify-content: flex-start;
    align-items: flex-start;

    .terminal-right {
      flex: 5;
      height: 100%;
      overflow-x: hidden;
      overflow-y: hidden;
    }

    .terminal-output {
      height: 100%;
      overflow-x: auto;
      overflow-y: scroll;
      background-color: white;
      padding: 25px;
      padding-top: 35px;
    }

    .terminal-dividing {
      width: 0px;
      height: 100%;
      border: 0;
      border-right: 1px solid #dfdfdf;
    }

    .terminal-left {
      flex: 3;
      height: 100%;
      background-color: white;
      overflow-y: auto;
      overflow-x: auto;
      display: flex;
      flex-direction: column;
      justify-content: flex-start;
      align-items: flex-start;
      padding: 25px;
      padding-top: 40px;

      .text {
        color: black;
      }

      .title {
        font-size: 20px;
        font-weight: 500;
        margin-top: 15px;
        margin-bottom: 10px;
      }

      .line {
        width: 100%;
        height: auto;
        display: flex;
        flex-direction: column;
        justify-content: flex-start;
        align-items: flex-start;
        margin-bottom: 6px;

        .item {
          font-size: 18px;
          font-weight: 500;
          flex: 1;
          margin-bottom: 10px;
        }
      }

      .select-area {
        display: flex;
        flex-direction: row;
        justify-content: flex-start;
        align-items: center;

        .text {
          font-size: 20px;
          font-weight: 500;
        }

        .select-box {
          margin-top: 6px;
          margin-bottom: 6px;

          .select-button {
            padding: 3px;
            padding-left: 9px;
            width: 100px;
            border: 1px solid rgba(0, 0, 0, 0.35);
            border-radius: 5px;
            margin-left: 10px;
            margin-right: 20px;
          }
        }

        .button {
          margin-top: 12px;
          font-size: 18px;
          border: 1px solid rgba(0, 0, 0, 0.35);
          border-radius: 5px;
          padding: 3px;
          padding-left: 8px;
          padding-right: 8px;
        }

        .button:hover {
          background-color: #2673e3;
          color: white;
          border: 1px solid rgba($color: #2673e3, $alpha: 1);
        }

        .button:active {
          background-color: rgba($color: #2673e3, $alpha: 0.5);
          border: 1px solid rgba($color: #2673e3, $alpha: 0.5);
          color: white;
        }

        .tip {
          margin-top: 12px;
          font-size: 18px;
          margin-left: 16px;
          font-weight: 500;
        }
      }
    }
  }
}
</style>
