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

import 'package:get/get.dart';
import 'package:uuid/uuid.dart';

import '../../../common/api/index.dart';
import '../../../common/models/index.dart';
import '../../../common/utils/index.dart';
import '../../common/preview_image/index.dart';
import '../../common/video_player/index.dart';

typedef CloudDiskUploadProgressListener =  void Function(CloudDiskUploadFileInfo);

/// 网盘工具类 
/// 处理网盘单例数据等
class CloudDiskHelper {


  //私有构造函数
  CloudDiskHelper._internal();

  //保存单例
  static final CloudDiskHelper _singleton =
      CloudDiskHelper._internal();

  //工厂构造函数
  factory CloudDiskHelper() => _singleton;


  /// 上传数据列表
  /// 在进行中或已上传完成的的数据列表
  List<CloudDiskUploadFileInfo> uploadFileList = [];
  CloudDiskUploadProgressListener? listener;
  final _eventBus = EventBus();
  final Uuid _uuid = const Uuid();

  /// 队列处理进度通知
  final controller = StreamController<CloudDiskUploadFileInfo>();

  /// 在 global 中 初始化队列 
  void initProgressQueue() {
    controller.stream.listen((event) {
      if (listener != null) {
        listener!(event);
      }
    });
  }

  List<CloudDiskUploadFileInfo> getUploadList() {
    return uploadFileList;
  }


  /// 进度监听
  void setCloudDiskUploadProgressListener(CloudDiskUploadProgressListener listener) {
    this.listener = listener;
  }
  void clearCloudDiskUploadProgressListener() {
    listener = null;
  }

  /// 开始上传云盘文件
  uploadFile(File file, String folderId, bool isV3) {
    final fileInfo = CloudDiskUploadFileInfo(file: file, folderId: folderId, isV3: isV3);
    fileInfo.id = _uuid.v1(); //唯一编码
    if (fileInfo.folderId == null || fileInfo.file == null) {
      return;
    }
    uploadFileList.add(fileInfo);
    if (isV3) {
      _uploadV3File(fileInfo);
    } else {
      _uploadFile(fileInfo);
    }
  }

  /// FileAssembleService.to.uploadFileV3
  _uploadV3File(CloudDiskUploadFileInfo fileinfo) async {
    await FileAssembleService.to.uploadFileV3(fileinfo.folderId!, fileinfo.file!, onSendProgress: (p, l) {
      final progress = p / l;
      fileinfo.progress = progress;
      _uploadProgressAndNotify(fileinfo);
    });
    _uploadFinishAndNotify(fileinfo);
  }
 
  /// 上传 FileAssembleService.to.uploadFile
  _uploadFile(CloudDiskUploadFileInfo fileinfo) async {
    await FileAssembleService.to.uploadFile(fileinfo.folderId!, fileinfo.file!, onSendProgress: (p, l) {
      final progress = p / l;
      fileinfo.progress = progress;
      _uploadProgressAndNotify(fileinfo);
    });
    _uploadFinishAndNotify(fileinfo);
  }

  /// 更新上传进度
  _uploadProgressAndNotify(CloudDiskUploadFileInfo fileinfo, {bool finish = false}) {
    CloudDiskUploadFileInfo? item = uploadFileList.firstWhereOrNull((element) => element.id == fileinfo.id);
    if (item != null) {
      item.progress = fileinfo.progress;
      if (finish) {
        item.finishTime = DateTime.now();
      }
    }
    controller.add(fileinfo);
    if (finish) {
      _eventBus.emit(EventBus.clouddiskFileUploadedMsg, fileinfo);
    }
  }
  /// 上传结束
  _uploadFinishAndNotify(CloudDiskUploadFileInfo fileinfo) {
    OLogger.d('完成上传，${fileinfo.name}');
    fileinfo.progress = 1;
    _uploadProgressAndNotify(fileinfo, finish: true);
  }


  /// 下载文件 并打开
  downloadAndOpenFile(FileInfo fileInfo, {bool isV3 = false}) async {
    final fileId = fileInfo.id ?? '' ;
    if (fileId.isEmpty) {
      return;
    }
    final fileName = '${fileInfo.name}.${fileInfo.extension}';

    // 在线视频, ios下 目前内部的 download 地址不行，文件静态地址才行
    if (Platform.isAndroid && fileName.isVideoFileName) {
      _networkVideo(fileInfo, isV3: isV3);
      return;
    }
    
    Loading.show();
    
    String? filePath = await O2FilePathUtil.getCloudDiskFileDownloadLocalPath(fileId, fileName);
    if (filePath == null || filePath.isEmpty) {
      Loading.showError('cloud_disk_download_file_no_path'.tr);
      return;
    }
    final file = File(filePath);
    if (file.existsSync()) {
      Loading.dismiss();
      _openFile(filePath, fileName);
    } else {
      // 下载附件
      var donwloadUrl = FileAssembleService.to.fileDownloadUrl(fileId);
      if (isV3) {
        donwloadUrl = FileAssembleService.to.fileDownloadUrlV3(fileId);
      }
      try {
        await O2HttpClient.instance.downloadFile(donwloadUrl, filePath);
        Loading.dismiss();
        _openFile(filePath, fileName);
      } on Exception catch (e) {
        OLogger.e(e.toString());
        Loading.showError(e.toString());
      }
    }
  }

  /// 在线打开视频，不下载
  void _networkVideo(FileInfo fileInfo, {bool isV3 = false}) async {
    final fileId = fileInfo.id ?? '' ;
    var videoUrl = FileAssembleService.to.fileDownloadUrl(fileId, needStream: false);
    if (isV3) {
      videoUrl = FileAssembleService.to.fileDownloadUrlV3(fileId, needStream: false);
    }
    VideoPlayerPage.openNetworkVideo(videoUrl, title: fileInfo.name ?? '');
  }

  final channel = O2FlutterMethodChannelUtils();
  /// 打开文件
  void _openFile(String filePath, String fileName) {
    if (filePath.isImageFileName) {
      PreviewImagePage.open(filePath, fileName);
    } else if (filePath.isVideoFileName) {
      VideoPlayerPage.openLocalVideo(filePath, title: fileName);
    }  else { // 系统默认打开方式
      channel.openLocalFile(filePath);
    }
  }
}