import 'dart:async';
import 'dart:io';

import 'package:connectivity/connectivity.dart';
import 'package:flutter/material.dart';
import 'package:flutter/services.dart';
import 'package:gz_orientation/gz_orientation.dart';
import 'package:gz_video_player/video_definition.dart';
import 'package:gz_video_player/video_play_options.dart';
import 'package:gz_video_player/video_speed.dart';
import 'package:gz_video_player/video_style.dart';
import 'package:gz_video_player/widget/brightness.dart';
import 'package:gz_video_player/widget/default_progress_bar.dart';
import 'package:gz_video_player/widget/linear_progress_bar.dart';
import 'package:gz_video_player/widget/video_bottom_bar.dart';
import 'package:gz_video_player/widget/video_definition_side_bar.dart';
import 'package:gz_video_player/widget/video_loading_view.dart';
import 'package:gz_video_player/widget/video_speed_bar.dart';
import 'package:gz_video_player/widget/video_top_bar.dart';
import 'package:gz_video_player/widget/vidoe_estimated_time_bar.dart';
import 'package:gz_video_player/widget/volume.dart';
import 'package:screen_brightness/screen_brightness.dart';
import 'package:video_player/video_player.dart';
import 'package:visibility_detector/visibility_detector.dart';
import 'package:wakelock/wakelock.dart';

export 'package:video_player/video_player.dart';

class GZVideoPlayer extends StatefulWidget {
  GZVideoPlayer({
    super.key,
    required this.dataSource,
    required this.sourceType,
    VideoPlayOptions? playOptions,
    VideoStyle? videoStyle,
    this.brightnessWidget,
    this.volumeWidget,
    this.children,
    this.restoreVertical = true,
    this.onInit,
    this.onPlay,
    this.onTimeUpdate,
    this.onPause,
    this.onEnded,
    this.onVolume,
    this.onBrightness,
    this.onNetwork,
    this.onFullscreen,
    this.onPop,
    this.onProgressDrag,
    this.onSpeedChange,
    this.onDefinitionChange,
  })  : playOptions = playOptions ?? VideoPlayOptions(),
        videoStyle = videoStyle ?? VideoStyle();

  /// 视频资源
  final dynamic dataSource;
  final DataSourceType sourceType;

  /// 播放器自定义属性
  final VideoPlayOptions playOptions;
  final VideoStyle videoStyle;
  final List<Widget>? children;
  final Widget? brightnessWidget;
  final Widget? volumeWidget;

  /// 播放器释放时是否恢复竖屏，默认恢复竖屏
  final bool restoreVertical;

  /// 初始化完成回调事件
  final ValueChanged<VideoPlayerController>? onInit;

  /// 播放开始回调
  final ValueChanged<VideoPlayerValue>? onPlay;

  /// 播放开始回调
  final ValueChanged<VideoPlayerValue>? onTimeUpdate;

  /// 播放暂停回调
  final ValueChanged<VideoPlayerValue>? onPause;

  /// 播放结束回调
  final ValueChanged<VideoPlayerValue>? onEnded;

  /// 播放声音大小回调
  final ValueChanged<double>? onVolume;

  /// 屏幕亮度回调
  final ValueChanged<double>? onBrightness;

  /// 网络变化回调
  final ValueChanged<String>? onNetwork;

  /// 屏幕亮度回调
  final ValueChanged<bool>? onFullscreen;

  /// 顶部控制栏点击返回回调
  final ValueChanged<VideoPlayerValue>? onPop;

  /// 进度被拖拽的回调
  final VideoProgressDragHandle? onProgressDrag;

  /// 倍速改变的回调
  final ValueChanged<VideoSpeedItem>? onSpeedChange;

  /// 清晰度改变回调
  final ValueChanged<VideoDefinitionItem>? onDefinitionChange;

  @override
  State<GZVideoPlayer> createState() => GZVideoPlayerState();

  static GZVideoPlayerState of(BuildContext context) {
    final GZVideoPlayerState? result =
        context.findAncestorStateOfType<GZVideoPlayerState>();
    if (result != null) {
      return result;
    }
    throw Exception('未找到 JLVideoPlayerState');
  }
}

class GZVideoPlayerState extends State<GZVideoPlayer>
    with SingleTickerProviderStateMixin, WidgetsBindingObserver {
  /// 控制器 - 快进 seekTo 暂停 pause 播放 play 摧毁 dispose
  late VideoPlayerController _controller;

  late AnimationController _controlBarAnimationController;
  late Animation<double> _controlTopBarAnimation;
  late Animation<double> _controlBottomBarAnimation;

  /// 清晰度控制器
  AnimationController? _definitionBarController;

  /// 是否全屏
  bool _fullScreened = false;
  bool _initialized = false;

  /// 屏幕亮度
  final ValueNotifier<double> _brightness = ValueNotifier(0.0);
  double? _originBrightness;

  /// 视频音量
  final ValueNotifier<double> _volume = ValueNotifier(1.0);

  /// 预估滑动时间
  final EstimatedTimeNotifier _estimatedTimeNotifier = EstimatedTimeNotifier();

  /// 是否显示控制拦
  bool _showMenu = false;

  /// 是否正在缓冲
  bool _checkBuffing = false;
  bool _isBuffing = false;

  /// 是否结束
  bool _isEnded = false;
  Timer? _showTime;
  String _position = "--:--";
  String _duration = "--:--";

  /// 是否隐藏速度栏
  bool _hiddenSpeed = true;

  /// 倍数按钮标题
  String _speedTitle = '';

  /// 倍数item
  VideoSpeedItem _speedItem = VideoSpeedItem();

  /// 清晰度按钮标题
  String _definitionTitle = '';

  /// 获取屏幕大小
  Size get screenSize => MediaQuery.of(context).size;

  /// 是否显示
  bool _hasShow = false;

  /// 多播放器实例设置唯一key
  Key key = Key(DateTime.now().toString());

  /// 视频比例
  double _playerAspectRatio = 1.0;

  dynamic _dataSource;
  DataSourceType _sourceType = DataSourceType.network;

  late StreamSubscription<ConnectivityResult> _subscription;

  @override
  void initState() {
    super.initState();

    /// 控制拦动画
    _controlBarAnimationController = AnimationController(
        duration: const Duration(milliseconds: 300), vsync: this);
    _controlTopBarAnimation = Tween(
            begin: -(widget.videoStyle.videoTopBarStyle.height +
                widget.videoStyle.videoTopBarStyle.margin.vertical * 2),
            end: 0.0)
        .animate(_controlBarAnimationController);
    _controlBottomBarAnimation = Tween(
            begin: -(widget.videoStyle.videoTopBarStyle.height +
                widget.videoStyle.videoControlBarStyle.margin.vertical * 2),
            end: 0.0)
        .animate(_controlBarAnimationController);

    var widgetsBinding = WidgetsBinding.instance;
    widgetsBinding.addObserver(this);

    /// 网络监听
    _subscription = Connectivity()
        .onConnectivityChanged
        .listen((ConnectivityResult result) {
      // Got a new connectivity status!
      widget.onNetwork?.call(result.toString().split('.')[1]);
    });

    ///运行设备横竖屏
    SystemChrome.setPreferredOrientations([
      DeviceOrientation.portraitUp,
      DeviceOrientation.landscapeLeft,
      DeviceOrientation.landscapeRight,
    ]);

    /// 常亮
    Wakelock.toggle(enable: true);

    /// 倍数按钮标题
    _speedTitle = widget.videoStyle.videoSpeedButtonStyle.title;

    /// 清晰度按钮标题
    _definitionTitle = widget.videoStyle.videoDefinitionButtonStyle.title;
    _resetDefinitionTitle();
    _initPlayer();
  }

  Future<void> initBrightness() async {
    double brightness = await ScreenBrightness().current;
    _brightness.value = brightness;
    _originBrightness = brightness;
  }

  @override
  void didUpdateWidget(GZVideoPlayer oldWidget) {
    if (oldWidget.dataSource != widget.dataSource ||
        oldWidget.sourceType != widget.sourceType) {
      _resetDefinitionTitle();
      _updateDataSource(type: widget.sourceType, source: widget.dataSource);
    }
    super.didUpdateWidget(oldWidget);
  }

  @override
  void dispose() {
    _clearHideControlBarTimer();
    _controller.dispose();
    _controlBarAnimationController.dispose();

    ///恢复设备竖屏
    if (widget.restoreVertical) {
      if (Platform.isIOS) {
        GzOrientation.forceOrientation(DeviceOrientation.portraitUp);
        GzOrientation.setPreferredOrientations([DeviceOrientation.portraitUp]);
      } else {
        SystemChrome.setPreferredOrientations([DeviceOrientation.portraitUp]);
      }
    }

    Wakelock.toggle(enable: false);
    _subscription.cancel();
    _brightness.dispose();
    _volume.dispose();
    _estimatedTimeNotifier.dispose();
    if (_originBrightness != null) {
      ScreenBrightness().setScreenBrightness(_originBrightness!);
    }
    WidgetsBinding.instance.removeObserver(this);
    super.dispose();
  }

  @override
  void didChangeMetrics() {
    WidgetsBinding.instance.addPostFrameCallback((timeStamp) {
      if (!mounted || !_hasShow) return;
      var orientation = MediaQuery.of(context).orientation;
      bool fullscreen = false;
      if (orientation == Orientation.landscape) {
        //横屏
        fullscreen = true;
        SystemChrome.setEnabledSystemUIMode(
          SystemUiMode.manual,
          overlays: [],
        );
      } else if (orientation == Orientation.portrait) {
        fullscreen = false;
        SystemChrome.setEnabledSystemUIMode(
          SystemUiMode.manual,
          overlays: SystemUiOverlay.values,
        );
      }
      if (fullscreen != _fullScreened) {
        setState(() {
          _fullScreened = !_fullScreened;
          _navigateLocally(context);
          //触发全屏事件
          widget.onFullscreen?.call(_fullScreened);
        });
      }
    });
  }

  void _updateDataSource({
    required DataSourceType type,
    required dynamic source,
    VoidCallback? initializeCallback,
  }) async {
    _sourceType = type;
    _dataSource = source;
    VideoPlayerController tempController = _createVideoPlayerController(
      type: type,
      source: source,
    );

    /// 释放老的 controller
    await _controller.pause();
    _controller.removeListener(_listener);
    _controller.dispose();

    /// 设置新的 controller 并开启监听和初始化
    _controller = tempController;
    _controller.addListener(_listener);
    _controller.initialize().then((_) {
      _handleInit();
      initializeCallback?.call();
    });
    setState(() {});
  }

  void resetVideoPlayer() {
    setState(() {
      _isEnded = true;
      _position = _duration;
      // _duration = "--:--";
      _controller.value =
          const VideoPlayerValue(duration: Duration(seconds: 0));
    });
  }

  void _resetDefinitionTitle() {
    if (widget.playOptions.definitionList.isNotEmpty) {
      for (VideoDefinitionItem item in widget.playOptions.definitionList) {
        if (widget.dataSource == item.dataSource) {
          _definitionTitle = item.title;
          break;
        }
      }
    }
  }

  void _listener() {
    if (!mounted) {
      return;
    }
    if (_controller.value.isInitialized) {
      var oPosition = _controller.value.position;
      var oDuration = _controller.value.duration;

      widget.onTimeUpdate?.call(_controller.value);

      if (_controller.value.buffered.isEmpty) {
        setState(() {
          _checkBuffing = true;
        });
      }
      if (_checkBuffing) {
        setState(() {
          _isBuffing = _controller.value.isBuffering;
          if (!_isBuffing) {
            _checkBuffing = false;
          }
        });
      }
      // debugPrint("error: " + controller.value.errorDescription);

      if (_controller.value.isPlaying) {
        setState(() {
          if (oDuration.inHours == 0) {
            var strPosition = oPosition.toString().split('.')[0];
            var strDuration = oDuration.toString().split('.')[0];
            _position =
                "${strPosition.split(':')[1]}:${strPosition.split(':')[2]}";
            _duration =
                "${strDuration.split(':')[1]}:${strDuration.split(':')[2]}";
          } else {
            _position = oPosition.toString().split('.')[0];
            _duration = oDuration.toString().split('.')[0];
          }
        });
      } else {
        if (oPosition >= oDuration) {
          resetVideoPlayer();
          if (widget.onEnded != null) {
            widget.onEnded!(_controller.value);
          }
        }
      }

      _isBuffing = _controller.value.isBuffering;
      // setState(() {});
    }
  }

  void _handleInit() {
    debugPrint("初始化完成");
    setVolume(_volume.value);
    widget.onInit?.call(_controller);
    _initialized = true;
    _playerAspectRatio = _controller.value.aspectRatio;
    setState(() {});
    if (widget.playOptions.autoplay) {
      if (widget.playOptions.startPosition.inSeconds != 0) {
        seekTo(widget.playOptions.startPosition);
      }
      _controller.play();
      _isEnded = false;
    }
    Future.delayed(const Duration(milliseconds: 1500), () {
      _controller.setPlaybackSpeed(_speedItem.speed);
    });
  }

  void _initPlayer() {
    if (widget.dataSource == null || widget.dataSource == "") return;
    _dataSource = widget.dataSource;
    _sourceType = widget.sourceType;
    _controller = _createVideoPlayerController(
      source: widget.dataSource,
      type: widget.sourceType,
    )
      ..addListener(_listener)
      ..initialize().then((_) => _handleInit())
      ..setLooping(widget.playOptions.loop);
  }

  /// ios seekTo 会导致播发速度重置
  /// 统一处理 seekTo 后1.5秒 重设播放速度
  void seekTo(Duration position) {
    if (_controller.value.isInitialized &&
        position.inSeconds <= _controller.value.duration.inSeconds &&
        position.inSeconds >= 0) {
      if (Platform.isIOS) {
        _controller.seekTo(position);
        Future.delayed(const Duration(milliseconds: 1500), () {
          _controller.setPlaybackSpeed(_speedItem.speed);
          debugPrint(
              '-----> playbackSpeed = ${_controller.value.playbackSpeed}');
        });
      } else {
        _controller.seekTo(position);
      }
    }
  }

  void setVolume(double volume) {
    double vol = volume;
    if (vol <= 0.0) {
      vol = 0.0;
    }
    if (vol >= 1.0) {
      vol = 1.0;
    }
    if (_controller.value.isInitialized) {
      widget.onVolume?.call(vol);
      _controller.setVolume(vol);
    }
  }

  /// 点击播放或暂停
  void togglePlay() {
    _createHideControlBarTimer();

    if (_controller.value.isPlaying) {
      _controller.pause();
      widget.onPause?.call(_controller.value);
    } else {
      _controller.play();
      widget.onPlay?.call(_controller.value);
    }
    setState(() {});
  }

  /// 点击全屏或取消
  void toggleFullScreen() {
    if (_fullScreened) {
      if (Platform.isIOS) {
        GzOrientation.forceOrientation(DeviceOrientation.portraitUp);
      } else {
        SystemChrome.setPreferredOrientations([DeviceOrientation.portraitUp]);
      }
    } else {
      if (Platform.isIOS) {
        GzOrientation.forceOrientation(DeviceOrientation.landscapeRight);
      } else {
        SystemChrome.setPreferredOrientations(
            [DeviceOrientation.landscapeLeft]);
      }
    }
  }

  /// 显示或隐藏菜单栏
  void toggleControls() {
    _clearHideControlBarTimer();

    if (!_showMenu) {
      _showMenu = true;
      _createHideControlBarTimer();
    } else {
      _showMenu = false;
    }
    setState(() {
      if (_showMenu) {
        _controlBarAnimationController.forward();
      } else {
        _controlBarAnimationController.reverse();
      }
    });
  }

  void _createHideControlBarTimer() {
    _clearHideControlBarTimer();

    ///如果是播放状态5秒后自动隐藏
    _showTime = Timer(const Duration(milliseconds: 5000), () {
      if (_controller.value.isPlaying) {
        if (_showMenu) {
          setState(() {
            _showMenu = false;
            _controlBarAnimationController.reverse();
          });
        }
      }
    });
  }

  void _clearHideControlBarTimer() {
    _showTime?.cancel();
  }

  /// 视频快退
  void fastRewind() {
    _createHideControlBarTimer();

    setState(() {
      debugPrint(_controller.value.position.toString());
      var currentPosition = _controller.value.position;
      seekTo(Duration(
          seconds: currentPosition.inSeconds - widget.playOptions.seekSeconds));
    });
  }

  /// 视频快进
  void fastForward() {
    _createHideControlBarTimer();

    setState(() {
      var currentPosition = _controller.value.position;
      seekTo(Duration(
          seconds: currentPosition.inSeconds + widget.playOptions.seekSeconds));
    });
  }

  /// 显示或隐藏速度栏
  void toggleSpeedControls() {
    setState(() {
      _hiddenSpeed = !_hiddenSpeed;
    });
  }

  /// 创建video controller
  VideoPlayerController _createVideoPlayerController({
    required DataSourceType type,
    required dynamic source,
  }) {
    switch (type) {
      case DataSourceType.asset:
        return VideoPlayerController.asset(source);
      case DataSourceType.file:
        return VideoPlayerController.file(File(source));
      case DataSourceType.contentUri:
        return VideoPlayerController.contentUri(Uri.parse(source));
      case DataSourceType.network:
        return VideoPlayerController.networkUrl(Uri.parse(source));
    }
  }

  /// 计算设备的宽高比
  double _calculateAspectRatio(BuildContext context) {
    final width = screenSize.width;
    final height = screenSize.height;

    /// return widget.playOptions.aspectRatio ?? controller.value.aspectRatio;
    return width > height ? width / height : height / width;
  }

  /// 动态生成进度条组件
  List<Widget> _generateVideoProgressChildren() {
    Map<String, Widget> videoProgressWidgets = {
      'rewind': Padding(
          padding: const EdgeInsets.symmetric(horizontal: 2),
          child: GestureDetector(
            onTap: () {
              fastRewind();
            },
            child: widget.videoStyle.videoControlBarStyle.rewindIcon,
          )),
      'play': Padding(
        padding: const EdgeInsets.symmetric(horizontal: 2),
        child: GestureDetector(
          onTap: () {
            togglePlay();
          },
          child: _controller.value.isPlaying
              ? widget.videoStyle.videoControlBarStyle.pauseIcon
              : widget.videoStyle.videoControlBarStyle.playIcon,
        ),
      ),
      'forward': Padding(
          padding: const EdgeInsets.symmetric(horizontal: 2),
          child: GestureDetector(
            onTap: () {
              fastForward();
            },
            child: widget.videoStyle.videoControlBarStyle.forwardIcon,
          )),

      ///线条视频进度条
      'progress': Expanded(
        child: Container(
          padding: const EdgeInsets.symmetric(horizontal: 8),
          child: VideoLinearProgressBar(
            _controller,
            allowScrubbing: widget.playOptions.allowScrubbing,
            onProgressDrag: (Duration position, Duration duration) {
              widget.onProgressDrag?.call(position, duration);
              _estimatedTimeNotifier.update(
                position: position,
                duration: duration,
              );
            },
            onDragEnd: () {
              _estimatedTimeNotifier.dragEnd();
            },
            onSeekTo: (Duration position) {
              seekTo(position);
            },
            padding:
                widget.videoStyle.videoControlBarStyle.progressStyle.padding,
            progressStyle: widget.videoStyle.videoControlBarStyle.progressStyle,
          ),
        ),
      ),

      ///默认视频进度条
      'basic-progress': Expanded(
        child: Container(
          padding: const EdgeInsets.symmetric(horizontal: 4),
          child: VideoDefaultProgressBar(
            controller: _controller,
            allowScrubbing: widget.playOptions.allowScrubbing,
            progressStyle: widget.videoStyle.videoControlBarStyle.progressStyle,
          ),
        ),
      ),
      'time': Padding(
        padding: widget.videoStyle.videoControlBarStyle.timePadding,
        child: Text(
          "$_position / $_duration",
          style: widget.videoStyle.videoControlBarStyle.timeTextStyle,
        ),
      ),
      'position-time': Padding(
        padding: widget.videoStyle.videoControlBarStyle.timePadding,
        child: Text(
          _position,
          style: widget.videoStyle.videoControlBarStyle.timeTextStyle,
        ),
      ),
      'duration-time': Padding(
        padding: widget.videoStyle.videoControlBarStyle.timePadding,
        child: Text(
          _duration,
          style: widget.videoStyle.videoControlBarStyle.timeTextStyle,
        ),
      ),
      'speed': Padding(
        padding: const EdgeInsets.symmetric(horizontal: 2),
        child: GestureDetector(
          onTap: toggleSpeedControls,
          child: Text(
            _speedTitle,
            style: widget.videoStyle.videoSpeedButtonStyle.textStyle,
          ),
        ),
      ),
      'definition': widget.playOptions.definitionList.isNotEmpty
          ? Padding(
              padding: const EdgeInsets.symmetric(horizontal: 2),
              child: GestureDetector(
                onTap: () {
                  if (_showMenu) {
                    toggleControls();
                  }
                  _definitionBarController?.forward();
                },
                child: Text(
                  _definitionTitle,
                  style: widget.videoStyle.videoSpeedButtonStyle.textStyle,
                ),
              ),
            )
          : const SizedBox(),
      'fullscreen': Padding(
        padding: const EdgeInsets.symmetric(horizontal: 2),
        child: GestureDetector(
          onTap: toggleFullScreen,
          child: _fullScreened
              ? widget.videoStyle.videoControlBarStyle.fullscreenExitIcon
              : widget.videoStyle.videoControlBarStyle.fullscreenIcon,
        ),
      ),
    };

    List<Widget> videoProgressChildrens = [];
    var userSpecifyItem = widget.videoStyle.videoControlBarStyle.itemList;

    for (var i = 0; i < userSpecifyItem.length; i++) {
      videoProgressChildrens.add(videoProgressWidgets[userSpecifyItem[i]]!);
    }

    return videoProgressChildrens;
  }

  /// 内置组件
  List<Widget> _videoBuiltInChildrens() {
    return [
      /// 顶部控制拦
      widget.videoStyle.videoTopBarStyle.show
          ? VideoTopBar(
              animation: _controlTopBarAnimation,
              videoTopBarStyle: widget.videoStyle.videoTopBarStyle,
              videoControlBarStyle: widget.videoStyle.videoControlBarStyle,
              onPop: () {
                if (_fullScreened) {
                  toggleFullScreen();
                } else {
                  widget.onPop?.call(
                    const VideoPlayerValue(duration: Duration(seconds: 0)),
                  );
                }
              })
          : const Align(),

      /// 是否显示播放按钮
      widget.videoStyle.showPlayIcon &&
              _initialized &&
              (!_controller.value.isPlaying && !_isEnded) &&
              !_isBuffing
          ? Align(
              alignment: Alignment.center,
              child: GestureDetector(
                onTap: () {
                  if (!_controller.value.isPlaying) {
                    togglePlay();
                  }
                },
                child: widget.videoStyle.playIcon,
              ),
            )
          : const SizedBox(),

      /// 是否显示重播按钮
      _initialized && _isEnded
          ? Align(
              alignment: Alignment.center,
              child: GestureDetector(
                onTap: () {
                  _isEnded = false;
                  _updateDataSource(
                    source: _dataSource,
                    type: _sourceType,
                  );
                },
                child: widget.videoStyle.replayIcon,
              ),
            )
          : const SizedBox(),

      /// 主字幕
      widget.videoStyle.videoSubtitlesStyle.mainTitle ??
          Align(
            alignment: Alignment.bottomCenter,
            child: Container(
              padding: const EdgeInsets.fromLTRB(10, 0, 10, 30),
              child: Text("",
                  maxLines: 2,
                  textAlign: TextAlign.center,
                  style: TextStyle(
                      color:
                          widget.videoStyle.videoSubtitlesStyle.mainTitleColor,
                      fontSize: widget
                          .videoStyle.videoSubtitlesStyle.mainTitleFontSize)),
            ),
          ),

      /// 辅字幕
      widget.videoStyle.videoSubtitlesStyle.subTitle ??
          Align(
            alignment: Alignment.bottomCenter,
            child: Container(
              padding: const EdgeInsets.all(10),
              child: Text("",
                  maxLines: 2,
                  textAlign: TextAlign.center,
                  style: TextStyle(
                      color:
                          widget.videoStyle.videoSubtitlesStyle.subTitleColor,
                      fontSize: widget
                          .videoStyle.videoSubtitlesStyle.subTitleFontSize)),
            ),
          ),

      /// 底部控制拦
      VideoBottomBar(
        animation: _controlBottomBarAnimation,
        videoControlBarStyle: widget.videoStyle.videoControlBarStyle,
        children: _generateVideoProgressChildren(),
      ),

      /// 中间速度栏
      VideoSpeedBar(
        hidden: _hiddenSpeed,
        speedItemList: widget.playOptions.speedList,
        style: widget.videoStyle.videoSpeedItemStyle,
        onTapItem: (int index) {
          VideoSpeedItem item = widget.playOptions.speedList[index];
          _speedItem = item;
          _speedTitle = item.title;
          toggleSpeedControls();
          _controller.setPlaybackSpeed(item.speed);
          widget.onSpeedChange?.call(item);
        },
      ),

      /// 清晰度设置栏
      VideoDefinitionSideBar(
        itemList: widget.playOptions.definitionList,
        videoDefinitionItemStyle: widget.videoStyle.videoDefinitionItemStyle,
        onInit: (AnimationController definitionBarController) {
          _definitionBarController = definitionBarController;
        },
        onTapItem: (int index) {
          Duration position = _controller.value.position;
          VideoDefinitionItem item = widget.playOptions.definitionList[index];
          _updateDataSource(
            type: item.sourceType,
            source: item.dataSource,
            initializeCallback: () {
              seekTo(position);
            },
          );
          _isBuffing = true;
          _definitionTitle = item.title;
          widget.onDefinitionChange?.call(item);
          setState(() {});
        },
      ),

      /// 预估时间栏
      VideoEstimatedTimeBar(notifier: _estimatedTimeNotifier),

      widget.brightnessWidget ??
          BrightnessWidget(
            brightness: _brightness,
            videoBrightnessStyle: widget.videoStyle.videoBrightnessStyle,
          ),

      widget.volumeWidget ??
          VolumeWidget(
            volume: _volume,
            videoVolumeStyle: widget.videoStyle.videoVolumeStyle,
          ),

      /// Loading
      !_initialized || _isBuffing
          ? VideoLoadingView(loadingStyle: widget.videoStyle.videoLoadingStyle)
          : const Align()
    ];
  }

  @override
  Widget build(BuildContext context) {
    /// Video children
    final videoChildrens = <Widget>[
      /// 视频区域
      GestureDetector(
        //点击
        onTap: () {
          //显示或隐藏菜单栏和进度条
          toggleControls();
        },
        //双击
        onDoubleTap: () {
          if (!_controller.value.isInitialized) return;
          togglePlay();
        },

        /// 水平滑动 - 调节视频进度
        onHorizontalDragStart: (DragStartDetails details) {
          if (!_controller.value.isInitialized) return;
          if (_controller.value.isPlaying) {
            _controller.pause();
          }
        },
        onHorizontalDragUpdate: (DragUpdateDetails details) {
          if (!_controller.value.isInitialized) return;
          if (!_showMenu) {
            setState(() {
              _showMenu = true;
            });
            _createHideControlBarTimer();
          }
          var currentPosition = _controller.value.position;
          if (details.primaryDelta != null) {
            late Duration position;
            if (details.primaryDelta! > 0) {
              int milliseconds = currentPosition.inMilliseconds +
                  widget.playOptions.progressGestureUnit;
              milliseconds =
                  milliseconds > _controller.value.duration.inMilliseconds
                      ? _controller.value.duration.inMilliseconds
                      : milliseconds;
              position = Duration(milliseconds: milliseconds);
            } else {
              int milliseconds = currentPosition.inMilliseconds -
                  widget.playOptions.progressGestureUnit;
              milliseconds = milliseconds < 0 ? 0 : milliseconds;
              position = Duration(milliseconds: milliseconds);
            }
            seekTo(position);
            _estimatedTimeNotifier.update(
              position: position,
              duration: _controller.value.duration,
            );
          }
        },
        onHorizontalDragEnd: (DragEndDetails details) {
          if (!_controller.value.isPlaying) {
            _controller.play();
          }
          _estimatedTimeNotifier.dragEnd();
        },

        /// 垂直滑动 - 调节亮度以及音量
        onVerticalDragStart: (DragStartDetails details) {
          if (!_controller.value.isInitialized) return;
        },
        onVerticalDragUpdate: (DragUpdateDetails details) async {
          if (!_controller.value.isInitialized ||
              details.primaryDelta == null) {
            return;
          }
          // 右侧垂直滑动 - 音量调节
          if (details.globalPosition.dx >= (screenSize.width / 2)) {
            _volume.value = _controller.value.volume;
            if (details.primaryDelta! > 0) {
              //往下滑动
              _volume.value = _controller.value.volume -
                  widget.playOptions.volumeGestureUnit;
              widget.onVolume?.call(_volume.value);
              if (_volume.value <= 0) {
                _volume.value = 0.0;
              }
              widget.onVolume?.call(_volume.value);
              _controller.setVolume(_volume.value);
            } else {
              //往上滑动
              _volume.value = _controller.value.volume +
                  widget.playOptions.volumeGestureUnit;
              widget.onVolume?.call(_volume.value);
              if (_volume.value >= 1) {
                _volume.value = 1.0;
              }
              widget.onVolume?.call(_volume.value);
              _controller.setVolume(_volume.value);
            }
            _volume.value = _controller.value.volume;
          } else {
            if (_originBrightness == null) {
              await initBrightness();
            }
            // 左侧垂直滑动 - 亮度调节
            if (details.primaryDelta! > 0) {
              //往下滑动
              _brightness.value =
                  _brightness.value - widget.playOptions.brightnessGestureUnit;
              widget.onBrightness?.call(_brightness.value);
              if (_brightness.value <= 0) {
                _brightness.value = 0.0;
              }
              widget.onBrightness?.call(_brightness.value);
              await ScreenBrightness().setScreenBrightness(_brightness.value);
            } else {
              //往上滑动
              _brightness.value =
                  _brightness.value + widget.playOptions.brightnessGestureUnit;
              widget.onBrightness?.call(_brightness.value);
              if (_brightness.value >= 1) {
                _brightness.value = 1.0;
              }
              widget.onBrightness?.call(_brightness.value);
              await ScreenBrightness().setScreenBrightness(_brightness.value);
            }
          }
        },
        onVerticalDragEnd: (DragEndDetails details) {},

        /// 长按 2 倍速播放
        onLongPress: () {
          if (!_controller.value.isInitialized) return;
          VideoSpeedItem item = VideoSpeedItem(speed: 2.0, title: '2X');
          _controller.setPlaybackSpeed(item.speed);
          widget.onSpeedChange?.call(item);
          _speedTitle = item.title;
          setState(() {});
        },

        /// 取消长按恢复之前选择的速度播放
        onLongPressUp: () {
          if (!_controller.value.isInitialized) return;
          _controller.setPlaybackSpeed(_speedItem.speed);
          widget.onSpeedChange?.call(_speedItem);
          _speedTitle = _speedItem.title;
          setState(() {});
        },

        ///视频播放器
        child: ClipRect(
          child: Container(
            width: double.infinity,
            height: double.infinity,
            color: Colors.black,
            child: Center(
              child: AspectRatio(
                aspectRatio: _playerAspectRatio,
                child: VideoPlayer(_controller),
              ),
            ),
          ),
        ),
      ),

      ///控制拦以及(可拓展)元素
    ];

    /// 内置元素
    videoChildrens.addAll(_videoBuiltInChildrens());

    /// 自定义拓展元素
    videoChildrens.addAll(widget.children ?? []);

    /// 构建video
    return VisibilityDetector(
      key: key,
      onVisibilityChanged: (VisibilityInfo info) {
        _hasShow = info.visibleFraction >= 0.9;
      },
      child: AspectRatio(
        aspectRatio: _fullScreened
            ? _calculateAspectRatio(context)
            : widget.playOptions.aspectRatio,

        /// build 所有video组件
        child: Stack(children: videoChildrens),
      ),
    );
  }

  void _navigateLocally(context) async {
    ModalRoute? modalRoute = ModalRoute.of(context);
    if (!_fullScreened) {
      if (modalRoute != null && modalRoute.willHandlePopInternally) {
        Navigator.of(context).pop();
      }
      return;
    }
    modalRoute?.addLocalHistoryEntry(LocalHistoryEntry(onRemove: () {
      if (_fullScreened) toggleFullScreen();
    }));
  }
}
