<template>
  <el-dialog
    title="设置"
    :visible.sync="visible"
    width="600px"
    :close-on-click-modal="false"
    @close="handleClose"
  >
    <el-tabs v-model="activeTab" :tab-position="'left'" class="settings-tabs">
      <!-- 视频设置 -->
      <el-tab-pane name="video">
        <span slot="label"><i class="el-icon-video-camera"></i> 视频</span>
        <el-form :model="videoConfig" label-width="140px" class="settings-form">
          <!-- 摄像头选择：使用外部传入的摄像头列表 -->
          <el-form-item label="摄像头/工作站">
            <el-select
              v-model="videoConfig.camera"
              placeholder="请选择"
              style="width: 240px"
              @change="getCameraResolutions"
            >
              <el-option
                v-for="cam in effectiveCameraList"
                :key="cam.id"
                :label="cam.name"
                :value="cam.id"
              />
            </el-select>
          </el-form-item>

          <el-form-item label="采集卡">
            <el-select
              v-model="videoConfig.captureCard"
              placeholder="请选择"
              style="width: 240px"
            />
          </el-form-item>
          <el-form-item label="网络调控策略">
            <el-select
              v-model="videoConfig.networkStrategy"
              placeholder="请选择"
              style="width: 240px"
            >
              <el-option label="弱网下流畅度优先" value="smooth" />
              <el-option label="清晰度优先" value="quality" />
              <el-option label="平衡模式" value="balance" />
            </el-select>
          </el-form-item>
          <!-- 摄像头分辨率 -->
          <el-form-item label="摄像头分辨率">
            <el-select
              v-model="videoConfig.cameraResolution"
              placeholder="请选择"
              style="width: 240px"
            >
              <el-option
                v-for="res in supportedResolutions"
                :key="res.label"
                :label="res.label"
                :value="res.label"
              />
            </el-select>
          </el-form-item>
          <el-form-item label="采集卡分辨率">
            <el-select
              v-model="videoConfig.captureResolution"
              placeholder="请选择"
              style="width: 240px"
            />
          </el-form-item>

          <el-form-item label="采集卡帧率">
            <el-select
              v-model="videoConfig.captureFps"
              placeholder="请选择"
              style="width: 240px"
            />
          </el-form-item>

          <el-form-item label="采集卡码率(2-8M)">
            <el-input
              v-model="videoConfig.captureBitrate"
              style="width: 240px"
            />
            <i class="el-icon-edit edit-icon" style="margin-left: 10px"></i>
          </el-form-item>
          <el-form-item label="视频镜像">
            <el-radio-group v-model="videoConfig.mirror">
              <el-radio :label="true">是</el-radio>
              <el-radio :label="false">否</el-radio>
            </el-radio-group>
          </el-form-item>
        </el-form>
      </el-tab-pane>

      <!-- 音频设置 -->
      <el-tab-pane name="audio">
        <span slot="label"><i class="el-icon-microphone"></i> 音频</span>
        <el-form :model="audioConfig" label-width="140px" class="settings-form">
          <el-form-item label="麦克风">
            <el-select
              v-model="audioConfig.mic"
              placeholder="请选择麦克风"
              style="width: 240px"
              @change="startMicTest"
            >
              <el-option
                v-for="mic in effectiveMicList"
                :key="mic.id"
                :label="mic.name"
                :value="mic.id"
              />
            </el-select>
          </el-form-item>
          <!-- 麦克风音量实时测试条 -->
          <el-form-item label="麦克风测试">
            <el-slider
              v-model="micTestPercent"
              class="progress-slider"
              disabled
            />
          </el-form-item>
          <!-- 扬声器选择 -->
          <el-form-item label="扬声器">
            <el-select
              v-model="audioConfig.speaker"
              placeholder="请选择扬声器"
              style="width: 240px"
              @change="playSpeakerTest"
            >
              <el-option
                v-for="spk in effectiveSpeakerList"
                :key="spk.id"
                :label="spk.name"
                :value="spk.id"
              />
            </el-select>
          </el-form-item>
          <!-- 扬声器音量实时测试条 -->
          <el-form-item label="扬声器测试">
            <el-slider
              v-model="speakerTestPercent"
              class="progress-slider"
              disabled
            />
          </el-form-item>
        </el-form>
      </el-tab-pane>
    </el-tabs>
  </el-dialog>
</template>

<script>
export default {
  name: "SettingsDialog",
  props: {
    visible: {
      type: Boolean,
      default: false,
    },
    videoConfig: {
      type: Object,
      required: true,
    },
    audioConfig: {
      type: Object,
      required: true,
    },
    cameraList: {
      type: Array,
      default: () => [],
    },
    micList: {
      type: Array,
      default: () => [],
    },
    speakerList: {
      type: Array,
      default: () => [],
    },
  },
  data() {
    return {
      activeTab: "video",
      micTestPercent: 0,
      speakerTestPercent: 0,
      videoDevices: [],
      audioInputDevices: [],
      audioOutputDevices: [],
      supportedResolutions: [],
      micAudioContext: null,
      micAnalyser: null,
      micAnimation: null,
      speakerAudio: null,
    };
  },
  computed: {
    effectiveCameraList() {
      if (this.cameraList && this.cameraList.length) {
        return this.cameraList;
      }
      return this.videoDevices.map(d => ({ id: d.deviceId, name: d.label || '未知摄像头' }));
    },
    effectiveMicList() {
      if (this.micList && this.micList.length) {
        return this.micList;
      }
      return this.audioInputDevices.map(d => ({ id: d.deviceId, name: d.label || '未知麦克风' }));
    },
    effectiveSpeakerList() {
      if (this.speakerList && this.speakerList.length) {
        return this.speakerList;
      }
      return this.audioOutputDevices.map(d => ({ id: d.deviceId, name: d.label || '未知扬声器' }));
    },
  },
  watch: {
    visible(val) {
      if (val) {
        this.getDevices();
        this.micTestPercent = 10;
        this.speakerTestPercent = 10;
      } else {
        this.stopAllTest();
      }
    },
  },
  methods: {
    async getDevices() {
      if (this.cameraList && this.cameraList.length) {
        this.getCameraResolutions();
        return;
      }
      try {
        await navigator.mediaDevices.getUserMedia({ audio: true, video: true });
        const devices = await navigator.mediaDevices.enumerateDevices();
        this.videoDevices = devices.filter((d) => d.kind === "videoinput");
        this.audioInputDevices = devices.filter((d) => d.kind === "audioinput");
        this.audioOutputDevices = devices.filter((d) => d.kind === "audiooutput");
        
        if (this.videoDevices.length && !this.videoConfig.camera) {
          this.videoConfig.camera = this.videoDevices[0].deviceId;
          this.getCameraResolutions();
        }
        if (this.audioInputDevices.length && !this.audioConfig.mic) {
          this.audioConfig.mic = this.audioInputDevices[0].deviceId;
          this.startMicTest();
        }
        if (this.audioOutputDevices.length && !this.audioConfig.speaker) {
          this.audioConfig.speaker = this.audioOutputDevices[0].deviceId;
        }
      } catch (err) {
        console.error("获取设备失败", err);
      }
    },
    async getCameraResolutions() {
      if (!this.videoConfig.camera) return;
      try {
        const stream = await navigator.mediaDevices.getUserMedia({
          video: { deviceId: this.videoConfig.camera },
        });
        const track = stream.getVideoTracks()[0];
        const caps = track.getCapabilities ? track.getCapabilities() : { width: { max: 1920 } };
        const list = [
          { w: 3840, h: 2160, label: "4K" },
          { w: 1920, h: 1080, label: "1080P" },
          { w: 1280, h: 720, label: "720P" },
          { w: 640, h: 480, label: "480P" },
        ].filter((item) => (caps.width && caps.width.max >= item.w) || true);
        this.supportedResolutions = list;
        if (list.length && !this.videoConfig.cameraResolution) {
          this.videoConfig.cameraResolution = list[0].label;
        }
        stream.getTracks().forEach((t) => t.stop());
      } catch (e) {
        this.supportedResolutions = [
          { w: 1920, h: 1080, label: "1080P" },
          { w: 1280, h: 720, label: "720P" },
          { w: 640, h: 480, label: "480P" },
        ];
      }
    },
    async startMicTest() {
      this.stopMicTest();
      try {
        const stream = await navigator.mediaDevices.getUserMedia({
          audio: { deviceId: this.audioConfig.mic },
        });

        this.micAudioContext = new AudioContext();
        this.micAnalyser = this.micAudioContext.createAnalyser();
        this.micAnalyser.fftSize = 256;
        const source = this.micAudioContext.createMediaStreamSource(stream);
        source.connect(this.micAnalyser);

        const dataArray = new Uint8Array(this.micAnalyser.frequencyBinCount);
        const update = () => {
          if (!this.micAnalyser) return;
          this.micAnalyser.getByteFrequencyData(dataArray);
          const sum = dataArray.reduce((a, b) => a + b, 0);
          const vol = Math.min(100, sum / 50);
          this.micTestPercent = vol;
          this.micAnimation = requestAnimationFrame(update);
        };
        update();
      } catch (err) {
        console.log("麦克风测试失败");
      }
    },
    stopMicTest() {
      if (this.micAnimation) {
        cancelAnimationFrame(this.micAnimation);
        this.micAnimation = null;
      }
      if (this.micAudioContext) {
        this.micAudioContext.close();
        this.micAudioContext = null;
        this.micAnalyser = null;
      }
      this.micTestPercent = 10;
    },
    async playSpeakerTest() {
      try {
        if (this.speakerAudio) {
          this.speakerAudio.pause();
          this.speakerAudio = null;
        }
        this.speakerTestPercent = 10;

        const audio = new Audio(
          "data:audio/wav;base64,UklGRnoGAABXQVZFZm10IBAAAAABAAEAQB8AAEAfAAABAAgAZGF0YQoGAACBhYqFbF1fdJmWl5hQVjMpOkhUXMDc1d3d1dPQ1NDR0dLR0dDQ0M/Pz8vLy8rKysnJyeHh4d3d3dHR0dDQ0M/Pz8vLy8rKysnJyeHh4d3d3dHR0dHR0dHR0dHR0dHR0dHQ="
        );
        audio.muted = false;

        if (this.audioConfig.speaker && audio.setSinkId) {
          await audio.setSinkId(this.audioConfig.speaker);
        }

        audio.onplaying = () => {
          this.speakerTestPercent = 80;
          setTimeout(() => (this.speakerTestPercent = 40), 300);
          setTimeout(() => (this.speakerTestPercent = 70), 600);
          setTimeout(() => (this.speakerTestPercent = 30), 900);
          setTimeout(() => (this.speakerTestPercent = 10), 1200);
        };
        audio.play();
        this.speakerAudio = audio;
      } catch (e) {
        console.log("扬声器测试失败");
      }
    },
    stopAllTest() {
      this.stopMicTest();
      if (this.speakerAudio) {
        this.speakerAudio.pause();
        this.speakerAudio = null;
      }
      this.speakerTestPercent = 10;
    },
    handleClose() {
      this.$emit("update:visible", false);
    },
  },
};
</script>

<style lang="scss" scoped>
.settings-form {
  padding: 10px;
}
.edit-icon {
  margin-left: 5px;
  cursor: pointer;
}
.progress-slider {
  width: 240px;
}
</style>