<template>
  <div class="app-container">
    <el-card shadow="never">
      <template #header>
        <div class="card-header">
          <el-space>
            <el-button text @click="$router.back()">← 返回</el-button>
            <span>视频监控</span>
          </el-space>
          <el-space>
            <el-select v-model="layout" size="small" style="width:100px" @change="setLayout">
              <el-option label="1x1" value="1x1" />
              <el-option label="2x2" value="2x2" />
              <el-option label="3x3" value="3x3" />
              <el-option label="4x4" value="4x4" />
            </el-select>
            <el-button size="small" @click="handleSnap">预览抓图</el-button>
            <el-button size="small" @click="osdVisible=true">字符叠加</el-button>
            <el-button size="small" @click="playbackVisible=true">历史回放</el-button>
            <el-button size="small" type="danger" @click="stopAllPreview">停止全部预览</el-button>
          </el-space>
        </div>
      </template>
      <el-row :gutter="16">
        <el-col :span="4">
          <div class="station-list">
            <div v-for="group in cameraGroups" :key="group.name" class="station-group">
              <div class="station-title">{{ group.name }}</div>
              <div v-for="cam in group.cameras" :key="cam.code" class="station-item"
                :class="{ active: currentCamera === cam.code }" @click="selectCamera(cam)">
                {{ cam.name }}
              </div>
            </div>
          </div>
          <div class="station-actions">
            <a href="./exe/VideoWebPlugin.exe" download class="download-link">下载视频插件</a>
          </div>
        </el-col>
        <el-col :span="20">
          <div ref="playWndRef" class="play-wnd" :style="{ height: playHeight + 'px' }">
            <div v-if="!pluginReady" class="plugin-tip">
              <el-empty description="视频插件加载中..." v-if="initCount < 3" />
              <el-empty description="插件启动失败，请检查是否安装视频插件">
                <el-button type="primary" size="small" @click="initPlugin">重新加载</el-button>
              </el-empty>
            </div>
          </div>
        </el-col>
      </el-row>
    </el-card>
    <!-- 字符叠加对话框 -->
    <el-dialog v-model="osdVisible" title="字符叠加" width="500px">
      <el-form :model="osdForm" label-width="100px" size="small">
        <el-form-item label="叠加文本"><el-input v-model="osdForm.text" type="textarea" :rows="3" placeholder="请输入叠加文本" /></el-form-item>
        <el-row :gutter="16">
          <el-col :span="12"><el-form-item label="X坐标"><el-input-number v-model="osdForm.x" :min="0" :max="1000" style="width:100%" /></el-form-item></el-col>
          <el-col :span="12"><el-form-item label="Y坐标"><el-input-number v-model="osdForm.y" :min="0" :max="1000" style="width:100%" /></el-form-item></el-col>
        </el-row>
        <el-row :gutter="16">
          <el-col :span="8"><el-form-item label="R"><el-input-number v-model="osdForm.r" :min="0" :max="255" style="width:100%" /></el-form-item></el-col>
          <el-col :span="8"><el-form-item label="G"><el-input-number v-model="osdForm.g" :min="0" :max="255" style="width:100%" /></el-form-item></el-col>
          <el-col :span="8"><el-form-item label="B"><el-input-number v-model="osdForm.b" :min="0" :max="255" style="width:100%" /></el-form-item></el-col>
        </el-row>
        <el-form-item label="预览窗口">
          <el-select v-model="osdForm.wndId" style="width:100%">
            <el-option label="当前选中窗口" :value="0" />
            <el-option v-for="i in 16" :key="i" :label="'窗口 ' + i" :value="i" />
          </el-select>
        </el-form-item>
      </el-form>
      <template #footer>
        <el-button type="primary" @click="submitOSD">叠加字符</el-button>
        <el-button @click="osdVisible=false">取 消</el-button>
      </template>
    </el-dialog>
    <!-- 历史回放对话框 -->
    <el-dialog v-model="playbackVisible" title="历史回放" width="600px">
      <el-form :model="playbackForm" label-width="100px" size="small">
        <el-form-item label="监控点">
          <el-input :value="currentCameraName" disabled />
        </el-form-item>
        <el-row :gutter="16">
          <el-col :span="12"><el-form-item label="开始时间"><el-date-picker v-model="playbackForm.startTime" type="datetime" placeholder="选择开始时间" style="width:100%" /></el-form-item></el-col>
          <el-col :span="12"><el-form-item label="结束时间"><el-date-picker v-model="playbackForm.endTime" type="datetime" placeholder="选择结束时间" style="width:100%" /></el-form-item></el-col>
        </el-row>
        <el-form-item label="码流类型">
          <el-radio-group v-model="playbackForm.streamMode">
            <el-radio :value="0">主码流</el-radio>
            <el-radio :value="1">子码流</el-radio>
          </el-radio-group>
        </el-form-item>
      </el-form>
      <template #footer>
        <el-button type="primary" @click="startPlayback">开始回放</el-button>
        <el-button @click="stopPlayback">停止回放</el-button>
        <el-button @click="playbackVisible=false">关 闭</el-button>
      </template>
    </el-dialog>
  </div>
</template>
<script setup name="VideoMonitor">
const playWndRef = ref(null)
const layout = ref('1x1')
const currentCamera = ref('5fe21f4e48ba4e14931e9c7794081060')
const pluginReady = ref(false)
const initCount = ref(0)
const playHeight = ref(500)
let pubKey = ''

const osdVisible = ref(false)
const osdForm = ref({ text: '', x: 0, y: 0, r: 255, g: 0, b: 0, wndId: 0 })
const playbackVisible = ref(false)
const playbackForm = ref({ startTime: '', endTime: '', streamMode: 0 })

const cameraGroups = ref([
  { name: '太浦闸', cameras: [
    { code: 'b83a1f06ae4943409f8fc4cdcc0d899f', name: '套闸下游' },
    { code: '2d2f2ddb114b4a1a82e0c1c7ee67da5c', name: '套闸上游' },
    { code: '5fe21f4e48ba4e14931e9c7794081060', name: '北堡上游' },
    { code: '946cd7478e744c3fbc60f17ff1b3d8e3', name: '北堡下游' },
  ]},
  { name: '望亭枢纽', cameras: [
    { code: '', name: '人行桥上游' },
    { code: 'f10b71ae57b345388b5b1999d65e97b1', name: '人行桥下游' },
    { code: '20b42333b36c46618e4a0f1ac0cd114b', name: '下游水质站' },
    { code: '5a723fc0d9ba4ca4a76a449df5a0a106', name: '下游南岸堤防' },
  ]},
])
const currentCameraName = computed(() => {
  for (const g of cameraGroups.value) {
    const cam = g.cameras.find(c => c.code === currentCamera.value)
    if (cam) return cam.name
  }
  return ''
})

function selectCamera(cam) {
  currentCamera.value = cam.code
  if (cam.code) startPreview(cam.code)
}
function startPreview(code) {
  if (!window.oWebControl) return
  window.oWebControl.JS_RequestInterface({
    funcName: 'startPreview',
    argument: JSON.stringify({ cameraIndexCode: code, streamMode: 0, transMode: 1, gpuMode: 0, wndId: -1 })
  })
}
function stopAllPreview() {
  if (!window.oWebControl) return
  window.oWebControl.JS_RequestInterface({ funcName: 'stopAllPreview' })
}
function setLayout(val) {
  if (!window.oWebControl) return
  window.oWebControl.JS_RequestInterface({ funcName: 'setLayout', argument: JSON.stringify({ layout: val }) })
}
function handleSnap() {
  if (!window.oWebControl) return
  window.oWebControl.JS_RequestInterface({ funcName: 'snapShot', argument: JSON.stringify({ name: '', wndId: 0 }) })
    .then(() => ElMessage.success('抓图成功'))
}
function submitOSD() {
  if (!window.oWebControl) return
  const color = 65536 * osdForm.value.b + 256 * osdForm.value.g + osdForm.value.r
  window.oWebControl.JS_RequestInterface({
    funcName: 'drawOSD',
    argument: JSON.stringify({
      text: osdForm.value.text, x: osdForm.value.x, y: osdForm.value.y,
      color: color, wndId: osdForm.value.wndId
    })
  }).then(() => { ElMessage.success('叠加成功'); osdVisible.value = false })
}
function startPlayback() {
  if (!window.oWebControl) return
  if (!playbackForm.value.startTime || !playbackForm.value.endTime) { ElMessage.warning('请选择回放时间段'); return }
  const formatTime = d => { const pad = n => String(n).padStart(2, '0'); return `${d.getFullYear()}-${pad(d.getMonth()+1)}-${pad(d.getDate())} ${pad(d.getHours())}:${pad(d.getMinutes())}:${pad(d.getSeconds())}` }
  window.oWebControl.JS_RequestInterface({
    funcName: 'startPlayback',
    argument: JSON.stringify({
      cameraIndexCode: currentCamera.value,
      startTime: formatTime(playbackForm.value.startTime),
      endTime: formatTime(playbackForm.value.endTime),
      streamMode: playbackForm.value.streamMode,
      transMode: 1, gpuMode: 0, wndId: -1
    })
  }).then(() => { ElMessage.success('开始回放') })
}
function stopPlayback() {
  if (!window.oWebControl) return
  window.oWebControl.JS_RequestInterface({ funcName: 'stopAllPlayback' })
    .then(() => ElMessage.success('已停止回放'))
}
function setEncrypt(value) {
  if (!window.JSEncrypt || !pubKey) return value
  const encrypt = new window.JSEncrypt()
  encrypt.setPublicKey(pubKey)
  return encrypt.encrypt(value)
}
function getPubKey(callback) {
  window.oWebControl.JS_RequestInterface({ funcName: 'getRSAPubKey', argument: JSON.stringify({ keyLength: 1024 }) })
    .then(oData => { if (oData.responseMsg.data) { pubKey = oData.responseMsg.data; callback() } })
}
function initVideo() {
  getPubKey(() => {
    window.oWebControl.JS_RequestInterface({
      funcName: 'init',
      argument: JSON.stringify({
        appkey: '20671975', secret: setEncrypt('vBsmHRbAgkiWdrenmwC8'),
        ip: setEncrypt('10.8.8.201'), playMode: 0, port: 443,
        snapDir: 'D:\\SnapDir', videoDir: 'D:\\VideoDir',
        layout: layout.value, enableHTTPS: 1, encryptedFields: 'secret,ip'
      })
    }).then(() => { pluginReady.value = true; startPreview(currentCamera.value) })
  })
}
function initPlugin() {
  if (typeof window.WebControl === 'undefined') { ElMessage.warning('视频插件未加载，请先下载并安装插件'); return }
  initCount.value++
  window.oWebControl = new window.WebControl({
    szPluginContainer: playWndRef.value,
    iServicePortStart: 15900, iServicePortEnd: 15909,
    cbConnectSuccess: () => {
      window.oWebControl.JS_StartService('window', { dllPath: './VideoPluginConnect.dll' }).then(() => {
        const rect = playWndRef.value.getBoundingClientRect()
        window.oWebControl.JS_CreateWnd(playWndRef.value, rect.width, rect.height).then(() => { initVideo() })
      })
    },
    cbConnectError: () => {
      pluginReady.value = false; window.oWebControl = null
      if (initCount.value < 3) setTimeout(initPlugin, 3000)
    },
    cbConnectClose: () => { window.oWebControl = null }
  })
}
function handleResize() {
  if (!window.oWebControl || !playWndRef.value) return
  const rect = playWndRef.value.getBoundingClientRect()
  window.oWebControl.JS_Resize(rect.width, rect.height)
}
onMounted(() => {
  playHeight.value = window.innerHeight - 200
  initPlugin()
  window.addEventListener('resize', handleResize)
})
onBeforeUnmount(() => {
  window.removeEventListener('resize', handleResize)
  if (window.oWebControl) { window.oWebControl.JS_Disconnect().then(() => {}, () => {}) }
})
</script>
<style scoped>
.card-header { font-weight:600;font-size:16px;display:flex;justify-content:space-between;align-items:center; }
.station-list { border: 1px solid #e5e5e5; border-radius: 4px; padding: 8px; max-height: 500px; overflow-y: auto; }
.station-group { margin-bottom: 12px; }
.station-title { background: #086560; color: #fff; padding: 6px 12px; font-size: 14px; font-weight: 600; border-radius: 2px; }
.station-item { padding: 6px 12px; cursor: pointer; font-size: 13px; border-bottom: 1px solid #f0f0f0; }
.station-item:hover { background: #f5f5f5; color: #086560; }
.station-item.active { background: #e6f7ff; color: #086560; font-weight: 600; }
.station-actions { margin-top: 12px; text-align: center; }
.download-link { color: #086560; font-size: 13px; }
.play-wnd { width: 100%; border: 1px solid #e5e5e5; position: relative; background: #000; }
.plugin-tip { position: absolute; top: 50%; left: 50%; transform: translate(-50%, -50%); }
</style>
