<template>
  <div class="video-container">
    <div class="video-wrapper">
      <!-- 添加 Jessibuca 播放器容器 -->
      <div v-if="playerType === 'jessibuca'" ref="jessibucaContainer" class="jessibuca-container"></div>

      <video
        v-else
        ref="videoElement"
        class="video-player video-js vjs-default-skin"
        controls
        autoplay
      ></video>

      <!-- 添加播放状态指示器 -->
      <div v-if="playStatus !== 'playing' && playStatus !== 'paused'" class="play-status-overlay">
        <div class="status-indicator">
          <div v-if="playStatus === 'loading'" class="loading-spinner"></div>
          <div v-if="playStatus === 'buffering'" class="buffering-spinner"></div>
          <div v-if="playStatus === 'error'" class="error-icon">!</div>
          <div class="status-text">{{ playStatusText }}</div>
        </div>
      </div>
    </div>
    <div class="control-panel">
      <div class="format-decoder-options">
        <!-- 播放器选择 -->
        <div class="option-group">
          <div class="option-title">播放器选择：</div>
          <div class="player-selector">
            <label class="player-label">
              <input type="radio" v-model="playerType" value="jessibuca" checked>
              <span>Jessibuca</span>
            </label>
            <label class="player-label">
              <input type="radio" v-model="playerType" value="videojs">
              <span>VideoJS</span>
            </label>
            <label class="player-label">
              <input type="radio" v-model="playerType" value="native">
              <span>原生播放器</span>
            </label>
          </div>
        </div>

        <!-- 视频格式选择 -->
        <div class="option-group">
          <div class="option-title">视频格式：</div>
          <div class="format-selector">
            <label class="format-label">
              <input type="radio" v-model="videoFormat" value="flv">
              <span>FLV</span>
            </label>
            <label class="format-label">
              <input type="radio" v-model="videoFormat" value="hls">
              <span>HLS (H.265)</span>
            </label>
            <label class="format-label">
              <input type="radio" v-model="videoFormat" value="m3u8">
              <span>M3U8</span>
            </label>
            <label class="format-label">
              <input type="radio" v-model="videoFormat" value="mp4">
              <span>MP4</span>
            </label>
            <label class="format-label">
              <input type="radio" v-model="videoFormat" value="ws">
              <span>WebSocket</span>
            </label>
          </div>
        </div>

        <!-- 解码方式选择 -->
        <div class="option-group" v-if="playerType !== 'jessibuca'">
          <div class="option-title">解码方式：</div>
          <div class="decoder-options">
            <label class="decoder-label">
              <input type="radio" v-model="decoderType" value="hardware">
              <span>硬件加速</span>
            </label>
            <label class="decoder-label">
              <input type="radio" v-model="decoderType" value="software">
              <span>软件解码</span>
            </label>
            <label class="decoder-label">
              <input type="radio" v-model="decoderType" value="auto">
              <span>自动选择</span>
            </label>
            <label class="decoder-label">
              <input type="radio" v-model="decoderType" value="none">
              <span>关闭解码</span>
            </label>
          </div>
        </div>
      </div>
      <div class="video-controls">
        <input
          type="text"
          v-model="videoUrl"
          placeholder="请输入视频URL"
          class="video-url-input"
        />
        <button @click="loadVideo" class="load-button">
          <span class="button-text">播放</span>
        </button>
      </div>
    </div>
  </div>
</template>

<script>
import flvjs from 'flv.js'
import Hls from 'hls.js'
import 'video.js/dist/video-js.css'
import videojs from 'video.js'
import 'videojs-contrib-hls'
import 'videojs-contrib-quality-levels'
// 导入 Jessibuca
import Jessibuca from '@/assets/jessibuca/jessibuca.js'
// 导入 Jessibuca 配置
import { getJessibucaConfig, getJessibucaUrl } from '@/utils/jessibucaConfig'

export default {
  name: 'VideoPlayer',
  data() {
    return {
      videoUrl: '',
      flvPlayer: null,
      hlsPlayer: null,
      vjsPlayer: null,
      wsConnection: null,
      mediaSource: null,
      sourceBuffer: null,
      // 添加 Jessibuca 相关数据
      jessibucaPlayer: null,
      videoFormat: 'flv',
      playerType: 'jessibuca', // 播放器类型
      decoderType: 'auto', // 解码方式
      showPlayButton: false,
      playStatus: 'idle',
      errorMessage: ''
    }
  },
  computed: {
    // 根据播放状态返回对应的文本
    playStatusText() {
      const statusMap = {
        idle: '准备就绪',
        loading: '加载中...',
        buffering: '缓冲中...',
        playing: '播放中',
        paused: '已暂停',
        error: `播放错误: ${this.errorMessage}`
      };
      return statusMap[this.playStatus] || '未知状态';
    }
  },
  methods: {
    loadVideo() {
      if (!this.videoUrl) {
        alert('请输入视频URL');
        return;
      }

      // 设置加载状态
      this.playStatus = 'loading';
      this.errorMessage = '';

      // 销毁之前的播放器实例
      this.destroyPlayer();

      // 根据选择的播放器类型加载视频
      if (this.playerType === 'jessibuca') {
        // 使用 Jessibuca 播放器
        this.loadWithJessibuca();
      } else if (this.playerType === 'videojs') {
        // 使用 VideoJS 播放器
        const videoElement = this.$refs.videoElement;
        this.addVideoEventListeners(videoElement);
        this.loadWithVideoJS();
      } else if (this.playerType === 'native') {
        // 使用原生播放器
        const videoElement = this.$refs.videoElement;
        this.addVideoEventListeners(videoElement);
        
        // 根据解码方式和视频格式选择加载方法
        if (this.decoderType === 'hardware') {
          this.loadWithVideoJS();
        } else if (this.decoderType === 'software') {
          this.loadWithSoftwareDecoder();
        } else if (this.decoderType === 'none') {
          this.loadWithoutDecoder();
        } else {
          // 自动选择解码方式
          if (this.videoFormat === 'flv') {
            this.loadFlvVideo(videoElement);
          } else if (this.videoFormat === 'hls' || this.videoFormat === 'm3u8') {
            this.loadHlsVideo(videoElement);
          } else if (this.videoFormat === 'mp4') {
            this.loadMp4Video(videoElement);
          } else if (this.videoFormat === 'ws') {
            this.loadWebSocketVideo(videoElement);
          }
        }
      }
    },

    // 添加视频事件监听器
    addVideoEventListeners(videoElement) {
      // 移除之前的事件监听器
      videoElement.removeEventListener('playing', this.handlePlaying);
      videoElement.removeEventListener('pause', this.handlePause);
      videoElement.removeEventListener('waiting', this.handleWaiting);
      videoElement.removeEventListener('error', this.handleError);
      
      // 添加新的事件监听器
      videoElement.addEventListener('playing', this.handlePlaying);
      videoElement.addEventListener('pause', this.handlePause);
      videoElement.addEventListener('waiting', this.handleWaiting);
      videoElement.addEventListener('error', this.handleError);
    },
    
    // 视频事件处理函数
    handlePlaying() {
      this.playStatus = 'playing';
    },
    
    handlePause() {
      this.playStatus = 'paused';
    },
    
    handleWaiting() {
      this.playStatus = 'buffering';
    },
    
    handleError(e) {
      console.error('视频播放错误:', e);
      this.playStatus = 'error';
      this.errorMessage = `视频播放错误: ${e.target.error ? e.target.error.message : '未知错误'}`;
    },

    // 使用 VideoJS 播放视频
    loadWithVideoJS() {
      const videoElement = this.$refs.videoElement;
      
      if (this.vjsPlayer) {
        this.vjsPlayer.dispose();
      }
      
      this.vjsPlayer = videojs(videoElement, {
        controls: true,
        autoplay: true,
        preload: 'auto',
        fluid: true,
        sources: [{
          src: this.videoUrl,
          type: this.getVideoJSType()
        }]
      });
      
      this.vjsPlayer.on('ready', () => {
        console.log('VideoJS 准备就绪');
      });
      
      this.vjsPlayer.on('error', (e) => {
        console.error('VideoJS 错误:', e);
        this.playStatus = 'error';
        this.errorMessage = `VideoJS 错误: ${this.vjsPlayer.error().message}`;
      });
    },
    
    // 获取 VideoJS 的视频类型
    getVideoJSType() {
      switch(this.videoFormat) {
        case 'flv':
          return 'video/x-flv';
        case 'hls':
        case 'm3u8':
          return 'application/x-mpegURL';
        case 'mp4':
          return 'video/mp4';
        case 'ws':
          return 'video/mp4'; // 假设 WebSocket 流是 MP4 格式
        default:
          return '';
      }
    },
    
    // 使用软件解码播放视频
    loadWithSoftwareDecoder() {
      if (this.videoFormat === 'flv') {
        this.loadFlvVideo(this.$refs.videoElement);
      } else if (this.videoFormat === 'hls' || this.videoFormat === 'm3u8') {
        this.loadHlsVideo(this.$refs.videoElement);
      } else if (this.videoFormat === 'mp4') {
        this.loadMp4Video(this.$refs.videoElement);
      } else if (this.videoFormat === 'ws') {
        this.loadWebSocketVideo(this.$refs.videoElement);
      }
    },
    
    // 不使用解码器直接播放视频
    loadWithoutDecoder() {
      const videoElement = this.$refs.videoElement;
      
      if (this.videoFormat === 'flv' && !flvjs.isSupported()) {
        this.playStatus = 'error';
        this.errorMessage = '浏览器不支持直接播放FLV格式';
        return;
      }
      
      if ((this.videoFormat === 'hls' || this.videoFormat === 'm3u8') && 
          !videoElement.canPlayType('application/vnd.apple.mpegurl')) {
        this.playStatus = 'error';
        this.errorMessage = '浏览器不支持直接播放HLS/M3U8格式';
        return;
      }
      
      videoElement.src = this.videoUrl;
      videoElement.load();
      videoElement.play();
    },
    
    // 使用 Jessibuca 播放视频
    loadWithJessibuca() {
      // 获取 Jessibuca 容器
      const container = this.$refs.jessibucaContainer;
      
      // 销毁之前的实例
      if (this.jessibucaPlayer) {
        this.jessibucaPlayer.destroy();
        this.jessibucaPlayer = null;
      }
      
      // 获取 Jessibuca 配置
      const config = getJessibucaConfig(container);
      
      // 创建 Jessibuca 实例
      this.jessibucaPlayer = new Jessibuca(config);
      
      // 处理 Jessibuca 事件
      this.jessibucaPlayer.on('load', () => {
        console.log('Jessibuca 加载成功');
      });
      
      this.jessibucaPlayer.on('play', () => {
        console.log('Jessibuca 开始播放');
        this.playStatus = 'playing';
      });
      
      this.jessibucaPlayer.on('pause', () => {
        console.log('Jessibuca 暂停播放');
        this.playStatus = 'paused';
      });
      
      this.jessibucaPlayer.on('error', (e) => {
        console.error('Jessibuca 错误:', e);
        this.playStatus = 'error';
        this.errorMessage = `Jessibuca 错误: ${e}`;
      });
      
      this.jessibucaPlayer.on('timeout', () => {
        console.error('Jessibuca 加载超时');
        this.playStatus = 'error';
        this.errorMessage = 'Jessibuca 加载超时';
      });
      
      this.jessibucaPlayer.on('fullscreen', (isFullscreen) => {
        console.log('Jessibuca 全屏状态:', isFullscreen);
      });
      
      // 获取处理后的 URL
      const url = getJessibucaUrl(this.videoUrl, this.videoFormat);
      
      // 开始播放
      this.jessibucaPlayer.play(url);
    },
    
    // 使用 FLV.js 播放 FLV 视频
    loadFlvVideo(videoElement) {
      if (!flvjs.isSupported()) {
        this.playStatus = 'error';
        this.errorMessage = '浏览器不支持 FLV 播放';
        return;
      }
      
      // 销毁之前的实例
      if (this.flvPlayer) {
        this.flvPlayer.destroy();
        this.flvPlayer = null;
      }
      
      // 创建 FLV 播放器
      this.flvPlayer = flvjs.createPlayer({
        type: 'flv',
        url: this.videoUrl,
        isLive: true,
        hasAudio: true,
        hasVideo: true,
        cors: true,
        withCredentials: false
      });
      
      // 绑定视频元素
      this.flvPlayer.attachMediaElement(videoElement);
      
      // 加载视频
      this.flvPlayer.load();
      
      // 播放视频
      this.flvPlayer.play().catch(e => {
        console.error('FLV 播放错误:', e);
        this.playStatus = 'error';
        this.errorMessage = `FLV 播放错误: ${e.message || '未知错误'}`;
      });
    },
    
    // 使用 HLS.js 播放 HLS/M3U8 视频
    loadHlsVideo(videoElement) {
      if (!Hls.isSupported()) {
        // 如果浏览器原生支持 HLS
        if (videoElement.canPlayType('application/vnd.apple.mpegurl')) {
          videoElement.src = this.videoUrl;
          videoElement.load();
          videoElement.play().catch(e => {
            console.error('HLS 原生播放错误:', e);
            this.playStatus = 'error';
            this.errorMessage = `HLS 原生播放错误: ${e.message || '未知错误'}`;
          });
          return;
        }
        
        this.playStatus = 'error';
        this.errorMessage = '浏览器不支持 HLS 播放';
        return;
      }
      
      // 销毁之前的实例
      if (this.hlsPlayer) {
        this.hlsPlayer.destroy();
        this.hlsPlayer = null;
      }
      
      // 创建 HLS 播放器
      this.hlsPlayer = new Hls({
        debug: false,
        defaultAudioCodec: 'aac',
        progressive: true,
        lowLatencyMode: true,
        backBufferLength: 90
      });
      
      // 绑定事件
      this.hlsPlayer.on(Hls.Events.MEDIA_ATTACHED, () => {
        console.log('HLS 媒体已附加');
        this.hlsPlayer.loadSource(this.videoUrl);
      });
      
      this.hlsPlayer.on(Hls.Events.MANIFEST_PARSED, () => {
        console.log('HLS 清单已解析');
        videoElement.play().catch(e => {
          console.error('HLS 播放错误:', e);
          this.playStatus = 'error';
          this.errorMessage = `HLS 播放错误: ${e.message || '未知错误'}`;
        });
      });
      
      this.hlsPlayer.on(Hls.Events.ERROR, (event, data) => {
        console.error('HLS 错误:', data);
        if (data.fatal) {
          switch(data.type) {
            case Hls.ErrorTypes.NETWORK_ERROR:
              // 尝试恢复网络错误
              console.log('HLS 网络错误，尝试恢复...');
              this.hlsPlayer.startLoad();
              break;
            case Hls.ErrorTypes.MEDIA_ERROR:
              // 尝试恢复媒体错误
              console.log('HLS 媒体错误，尝试恢复...');
              this.hlsPlayer.recoverMediaError();
              break;
            default:
              // 无法恢复的错误
              this.playStatus = 'error';
              this.errorMessage = `HLS 错误: ${data.details}`;
              this.hlsPlayer.destroy();
              break;
          }
        }
      });
      
      // 附加到视频元素
      this.hlsPlayer.attachMedia(videoElement);
    },
    
    // 播放 MP4 视频
    loadMp4Video(videoElement) {
      // MP4 可以直接使用 video 元素播放
      videoElement.src = this.videoUrl;
      videoElement.load();
      videoElement.play().catch(e => {
        console.error('MP4 播放错误:', e);
        this.playStatus = 'error';
        this.errorMessage = `MP4 播放错误: ${e.message || '未知错误'}`;
      });
    },
    
    // 通过 WebSocket 播放视频
    loadWebSocketVideo(videoElement) {
      // 确保 URL 是 WebSocket 格式
      let wsUrl = this.videoUrl;
      if (!wsUrl.startsWith('ws://') && !wsUrl.startsWith('wss://')) {
        wsUrl = `ws://${wsUrl.replace(/^https?:\/\//, '')}`;
      }
      
      // 销毁之前的连接
      if (this.wsConnection) {
        this.wsConnection.close();
        this.wsConnection = null;
      }
      
      // 创建 MediaSource
      this.mediaSource = new MediaSource();
      videoElement.src = URL.createObjectURL(this.mediaSource);
      
      this.mediaSource.addEventListener('sourceopen', () => {
        console.log('MediaSource 已打开');
        
        // 创建 SourceBuffer
        try {
          this.sourceBuffer = this.mediaSource.addSourceBuffer('video/mp4; codecs="avc1.42E01E, mp4a.40.2"');
        } catch (e) {
          console.error('创建 SourceBuffer 失败:', e);
          this.playStatus = 'error';
          this.errorMessage = `创建 SourceBuffer 失败: ${e.message}`;
          return;
        }
        
        // 创建 WebSocket 连接
        this.wsConnection = new WebSocket(wsUrl);
        
        // 设置二进制类型
        this.wsConnection.binaryType = 'arraybuffer';
        
        // 连接打开
        this.wsConnection.onopen = () => {
          console.log('WebSocket 已连接');
        };
        
        // 接收数据
        this.wsConnection.onmessage = (event) => {
          if (this.sourceBuffer && !this.sourceBuffer.updating) {
            try {
              this.sourceBuffer.appendBuffer(event.data);
            } catch (e) {
              console.error('添加数据到 SourceBuffer 失败:', e);
            }
          }
        };
        
        // 连接错误
        this.wsConnection.onerror = (e) => {
          console.error('WebSocket 错误:', e);
          this.playStatus = 'error';
          this.errorMessage = 'WebSocket 连接错误';
        };
        
        // 连接关闭
        this.wsConnection.onclose = () => {
          console.log('WebSocket 已关闭');
        };
      });
      
      // 播放视频
      videoElement.play().catch(e => {
        console.error('WebSocket 视频播放错误:', e);
        this.playStatus = 'error';
        this.errorMessage = `WebSocket 视频播放错误: ${e.message || '未知错误'}`;
      });
    },
    
    // 销毁播放器实例
    destroyPlayer() {
      // 销毁 Jessibuca 播放器
      if (this.jessibucaPlayer) {
        this.jessibucaPlayer.destroy();
        this.jessibucaPlayer = null;
      }
      
      // 销毁 FLV 播放器
      if (this.flvPlayer) {
        this.flvPlayer.destroy();
        this.flvPlayer = null;
      }
      
      // 销毁 HLS 播放器
      if (this.hlsPlayer) {
        this.hlsPlayer.destroy();
        this.hlsPlayer = null;
      }
      
      // 销毁 VideoJS 播放器
      if (this.vjsPlayer) {
        this.vjsPlayer.dispose();
        this.vjsPlayer = null;
      }
      
      // 关闭 WebSocket 连接
      if (this.wsConnection) {
        this.wsConnection.close();
        this.wsConnection = null;
      }
      
      // 释放 MediaSource
      if (this.mediaSource && this.mediaSource.readyState === 'open') {
        try {
          this.mediaSource.endOfStream();
        } catch (e) {
          console.error('关闭 MediaSource 失败:', e);
        }
      }
      this.mediaSource = null;
      this.sourceBuffer = null;
      
      // 重置视频元素
      const videoElement = this.$refs.videoElement;
      if (videoElement) {
        videoElement.src = '';
        videoElement.load();
      }
    }
  },
  beforeDestroy() {
    // 组件销毁前清理资源
    this.destroyPlayer();
  }
}
</script>

<style scoped>
.video-container {
  width: 100%;
  max-width: 1200px;
  margin: 0 auto;
  padding: 20px;
  box-sizing: border-box;
}

.video-wrapper {
  position: relative;
  width: 100%;
  background-color: #000;
  aspect-ratio: 16/9;
  overflow: hidden;
  border-radius: 8px;
  box-shadow: 0 4px 12px rgba(0, 0, 0, 0.1);
}

.video-player,
.jessibuca-container {
  width: 100%;
  height: 100%;
  background-color: #000;
}

.control-panel {
  margin-top: 20px;
  padding: 15px;
  background-color: #f5f5f5;
  border-radius: 8px;
  box-shadow: 0 2px 8px rgba(0, 0, 0, 0.05);
}

.format-decoder-options {
  display: flex;
  flex-wrap: wrap;
  gap: 20px;
  margin-bottom: 20px;
}

.option-group {
  flex: 1;
  min-width: 200px;
}

.option-title {
  font-weight: bold;
  margin-bottom: 10px;
  color: #333;
}

.player-selector,
.format-selector,
.decoder-options {
  display: flex;
  flex-wrap: wrap;
  gap: 10px;
}

.player-label,
.format-label,
.decoder-label {
  display: flex;
  align-items: center;
  padding: 6px 12px;
  background-color: #fff;
  border-radius: 4px;
  cursor: pointer;
  transition: all 0.2s;
  box-shadow: 0 1px 3px rgba(0, 0, 0, 0.1);
}

.player-label:hover,
.format-label:hover,
.decoder-label:hover {
  background-color: #f0f0f0;
}

.player-label input,
.format-label input,
.decoder-label input {
  margin-right: 6px;
}

.video-controls {
  display: flex;
  gap: 10px;
}

.video-url-input {
  flex: 1;
  padding: 10px 15px;
  border: 1px solid #ddd;
  border-radius: 4px;
  font-size: 14px;
}

.load-button {
  padding: 10px 20px;
  background-color: #4CAF50;
  color: white;
  border: none;
  border-radius: 4px;
  cursor: pointer;
  font-weight: bold;
  transition: background-color 0.2s;
}

.load-button:hover {
  background-color: #45a049;
}

.button-text {
  display: inline-block;
}

/* 播放状态指示器样式 */
.play-status-overlay {
  position: absolute;
  top: 0;
  left: 0;
  width: 100%;
  height: 100%;
  display: flex;
  justify-content: center;
  align-items: center;
  background-color: rgba(0, 0, 0, 0.5);
  z-index: 10;
}

.status-indicator {
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  padding: 20px;
  background-color: rgba(0, 0, 0, 0.7);
  border-radius: 8px;
  color: white;
}

.loading-spinner,
.buffering-spinner {
  width: 40px;
  height: 40px;
  border: 4px solid rgba(255, 255, 255, 0.3);
  border-top: 4px solid white;
  border-radius: 50%;
  margin-bottom: 10px;
  animation: spin 1s linear infinite;
}

.error-icon {
  width: 40px;
  height: 40px;
  border-radius: 50%;
  background-color: #f44336;
  color: white;
  display: flex;
  justify-content: center;
  align-items: center;
  font-size: 24px;
  font-weight: bold;
  margin-bottom: 10px;
}

.status-text {
  font-size: 16px;
  text-align: center;
}

@keyframes spin {
  0% { transform: rotate(0deg); }
  100% { transform: rotate(360deg); }
}
</style>
