import { debounce } from 'lodash-es';
import React, { useCallback, useEffect, useRef } from 'react';

// SDK
import { Controller } from '@tingwu/core';

// 数据
import {
  docPlayerHooks,
  documentHooks,
  eDocScene,
} from '../../../../../documentModel';

// 事件管理器
import * as ParagraphsEvts from '../../../../../pages/docASR/utils/constants';
import evtBus from '../../../../../utils/bus';
import { DocPlayerEvts } from './DocPlayer.event';

import { useDataHooks } from '../../../../../pages/docASR/components/businessCommon/separateHooks/dataShare';
import {
  iTWDocPlayerHandler,
  TWDocAudioPlayer,
} from '../../atomicComponent/TWAudioPlayer';
import { useMediaMarkTokens } from './useMarkTokens';
import { useMediaAgendas } from './useMediaAgendas.hook';
import { usePlayerStateChange } from './usePlayerStateChange';

interface iDocAudioPlayerProps {
  playerWrapperRef: React.MutableRefObject<HTMLDivElement | null>; // 播放器容器DOM元素引用
}

// 文档音频播放器
export const DocAudioPlayer: React.FC<iDocAudioPlayerProps> = (props) => {
  // 数据
  const { documentData } = documentHooks.useDocumentData();
  const { docPlayerData, updatePlayerStatus } =
    docPlayerHooks.useDocPlayerData();
  const { playerRecordTime } = docPlayerData || {};

  // 状态共享
  const { controller } = useDataHooks();
  const controllerRef = useRef<Controller>();
  useEffect(() => {
    controllerRef.current = controller;
  }, [controller]);

  /** 内部播放器状态 */
  // 内部状态引用
  interface iPlayerStatus {
    playerMode?: 'video' | 'audio'; // 播放器模式
    // 播放器基础状态
    playerCurtTime?: number; // 当前播放时间
    playerIsPlaying?: boolean; // 播放器是否在正在播放
    // 播放链接
    audioUrl?: string; // 音频播放地址
    audioSegments?: number[][]; // 音频分段数据(跳过空白片段用)
    audioSpectrum?: number[]; // 音频频谱数据
  }
  const playerRefState = useRef<iPlayerStatus>({});
  // 更新播放状态
  const updateAudioPlayerStatus = useCallback(
    (status: iPlayerStatus) => {
      playerRefState.current = {
        ...playerRefState.current,
        ...status,
      };
      updatePlayerStatus(status);
    },
    [updatePlayerStatus],
  );

  /** 音频操作方法 */
  const audioPlayerRef = useRef<iTWDocPlayerHandler>(null);
  // 指定时间开始播放
  const startPlayOnTimeCheckRef = useRef(false); // 节流
  const startPlayOnTime = useCallback((beginTime: number) => {
    // 非视频不处理
    if (playerRefState.current.playerMode !== 'audio') return;
    // 更新中不处理（加锁处理，避免多次触发）
    if (startPlayOnTimeCheckRef.current) return;
    startPlayOnTimeCheckRef.current = true;
    window.setTimeout(() => {
      startPlayOnTimeCheckRef.current = false;
    }, 100);
    // 播放器进行播放
    evtBus.emit(ParagraphsEvts.CURRENTTIME_TINGWU2, beginTime, true); // 原文区定位到指定时间
    audioPlayerRef.current?.audioStartPlayOnTime(beginTime); // 播放器切换到指定时间
  }, []);
  // 播放器切换到指定时间
  const playerToTimeCheckRef = useRef(false); // 节流

  const handlePlayerToTime = useCallback(
    (seekToTime: number) => {
      // 非视频不处理
      if (playerRefState.current.playerMode !== 'audio') return;
      // 更新中不处理（加锁处理，避免多次触发）
      if (playerToTimeCheckRef.current) return;
      playerToTimeCheckRef.current = true;
      window.setTimeout(() => {
        playerToTimeCheckRef.current = false;
      }, 100);
      // 如果时间一致，不需要变更
      const { playerCurtTime } = playerRefState.current;
      if (playerCurtTime === seekToTime) return;
      // 切换到指定时间(原文驱动，此处不需要切换原文区时间)

      audioPlayerRef.current?.audioPlayerToTime(seekToTime); // 播放器切换到指定时间
    },
    [playerRecordTime],
  );

  useEffect(() => {
    evtBus.on(DocPlayerEvts.START_PLAY_ON_TIME, startPlayOnTime);
    evtBus.on(DocPlayerEvts.PLAYER_TO_TIME, handlePlayerToTime);
    return () => {
      evtBus.off(DocPlayerEvts.START_PLAY_ON_TIME, startPlayOnTime);
      evtBus.off(DocPlayerEvts.PLAYER_TO_TIME, handlePlayerToTime);
    };
  }, [startPlayOnTime, handlePlayerToTime]);

  /** 播放器初始化 */
  // 切换播放器(音频 -> 视频，播放器内没有直接操作按钮)
  useEffect(() => {
    const audioPlayer = audioPlayerRef.current;
    if (!docPlayerData || !audioPlayer) return;
    // 播放器状态同步
    const { playerMode } = docPlayerData;
    const internalPlayerMode = playerRefState.current.playerMode;
    if (playerMode === internalPlayerMode) return;

    // 音频播放器
    if (playerMode === 'audio') {
      // 状态同步: 1. 初始化、2. 播放器切换
      if (!internalPlayerMode || internalPlayerMode !== 'audio') {
        // 1. 状态同步
        const {
          playerCurtTime,
          playerMuted,
          playerVolume,
          playerRate,
          skipBlankSegment,
          playerIsPlaying,
        } = docPlayerData;
        // 内部状态同步
        updateAudioPlayerStatus({
          playerMode,
          playerCurtTime,
          playerIsPlaying,
        });
        audioPlayer.syncToAudioPlayer({
          volume: playerVolume,
          muted: playerMuted,
          playbackRate: playerRate,
          curtTime: playerCurtTime,
          skipBlank: skipBlankSegment,
        });
        // 2. 播放同步
        if (playerIsPlaying) {
          setTimeout(() => {
            audioPlayer.audioStartPlayOnTime(playerCurtTime);
          }, 50);
        }
      }
    }
    // 切换到视频播放器；1.停止播放 2. 更新播放状态
    if (playerMode === 'video' && internalPlayerMode === 'audio') {
      playerRefState.current.playerMode = playerMode; // 更新内部播放器状态
      audioPlayer.audioPlayerPause(); // 暂停播放
      playerRefState.current.playerIsPlaying = false; // 更新内部播放器状态
    }
  }, [docPlayerData, docPlayerData?.playerMode, updateAudioPlayerStatus]);

  /** 音频状态监听 */
  const { onPlayerVolumeChange, onPlayerRateChange, onPlayerSkipBlankChange } =
    usePlayerStateChange();
  // 音频播放状态变更
  const onPlayerPlayStatusChange = useCallback(
    (isPlay: boolean) => {
      if (playerRefState.current.playerMode !== 'audio') return;
      // 开始播放，才需要更新开始播放的状态
      const _controller = controllerRef.current;
      // 播放状态变更，同步原文区 音字同步
      if (isPlay && _controller) {
        _controller.startPlayingVoiceWord();
      }
      // 保存状态
      updateAudioPlayerStatus({
        playerIsPlaying: isPlay,
      });
    },
    [updateAudioPlayerStatus],
  );
  // 播放器时间更新后，触发音字回显展示
  const { onPlayerTimeUpdateToDisplayText } = usePlayerStateChange();
  // 播放器 Seeking
  const onPlayerSeekedToDisplayText = debounce((curtTime: number) => {
    if (playerRefState.current.playerMode !== 'audio') return;

    // 音字对照功能同步，其他地方有监听此事件；强制进行滚动
    evtBus.emit(ParagraphsEvts.CURRENTTIME_TINGWU2, curtTime, true);
    // 保存状态
    updateAudioPlayerStatus({ playerCurtTime: curtTime });
  }, 50);

  // 音频时间更新
  const onAudioTimeUpdate = useCallback(
    (curtTime: number) => {
      if (playerRefState.current.playerMode !== 'audio') return;
      // 音字回听驱动更新
      onPlayerTimeUpdateToDisplayText(curtTime);
      // 更新内部状态
      updateAudioPlayerStatus({
        playerCurtTime: curtTime,
      });
    },
    [onPlayerTimeUpdateToDisplayText, updateAudioPlayerStatus],
  );

  // 摘要总结、标记
  const { mediaAgendas } = useMediaAgendas();
  const { markTokens } = useMediaMarkTokens();

  /** 播放器渲染 */
  const { docId, docScene } = documentData;
  // 无纪要
  if (!docId || !docScene) return null;
  // 无视频播放数据、非视频
  if (!docPlayerData || !docPlayerData.audioUrl) return null;

  // 播放器容器
  const { playerWrapperRef } = props;
  const { audioUrl, audioSpectrum, audioSegments } = docPlayerData;

  return (
    <TWDocAudioPlayer
      // 切换到指定时间、指定时间开始播放、高亮标记
      ref={audioPlayerRef}
      controller={controller}
      // 基础数据
      playerWrapperRef={playerWrapperRef}
      featureMode={
        [eDocScene.transShare].includes(docScene) ? 'share' : 'trans'
      }
      hotKeyEnabled={docPlayerData.playerMode === 'audio'}
      audioUrl={audioUrl}
      audioSpectrum={audioSpectrum}
      audioSegments={audioSegments}
      // 业务数据
      mediaAgendas={mediaAgendas}
      mediaTokens={markTokens}
      // jumpTipsTime={jumpTipsTime} // 记录播放进度
      // 事件监听
      onAudioVolumeChange={onPlayerVolumeChange}
      onAudioRateChange={onPlayerRateChange}
      onAudioSkipBlankChange={onPlayerSkipBlankChange}
      onAudioPlayStatusChange={onPlayerPlayStatusChange}
      onAudioTimeUpdate={onAudioTimeUpdate}
      onAudioSeek={onPlayerSeekedToDisplayText}
      // 事件上报
      eventReporter={() => {}}
    />
  );
};
