content: import 'dart:async';
  import 'dart:io';
  
  import 'package:equatable/equatable.dart';
  import 'package:flutter_bloc/flutter_bloc.dart';
  import 'package:flutter_social_videos_downloader/src/features/social_videos_downloader/domain/entities/video.dart';
  import 'package:path_provider/path_provider.dart';
  import 'package:video_thumbnail/video_thumbnail.dart';
  
  import '../../../../../core/helpers/dir_helper.dart';
  import '../../../../../core/helpers/permission_helper.dart';
  import '../../../../../core/utils/app_enums.dart';
  import '../../../../../core/utils/app_strings.dart';
  import '../../../domain/entities/download_item.dart';
  import '../../../domain/entities/video_item.dart';
  import '../../../domain/usecase/get_video_usecase.dart';
  import '../../../domain/usecase/save_video_usecase.dart';
  
  part 'downloader_event.dart';
  
  part 'downloader_state.dart';
  
  class DownloaderBloc extends Bloc<DownloaderEvent, DownloaderState> {
    final GetVideoUseCase getVideoUseCase;
    final SaveVideoUseCase saveVideoUseCase;
  
    DownloaderBloc({
      required this.getVideoUseCase,
      required this.saveVideoUseCase,
    }) : super(DownloaderInitial()) {
      on<LoadOldDownloads>(_loadOldDownloads);
      on<DownloaderGetVideo>(_getVideo);
      on<DownloaderSaveVideo>(_saveVideo);
    }
  
    List<DownloadItem> newDownloads = [];
  
    Future<void> _getVideo(
      DownloaderGetVideo event,
      Emitter<DownloaderState> emit,
    ) async {
      emit(const DownloaderGetVideoLoading());
      final result = await getVideoUseCase(event.videoLink);
      result.fold(
        (left) => emit(DownloaderGetVideoFailure(left.message)),
        (right) => emit(DownloaderGetVideoSuccess(right)),
      );
    }
  
    Future<void> _saveVideo(
      DownloaderSaveVideo event,
      Emitter<DownloaderState> emit,
    ) async {
      // bool checkPermissions = await PermissionsHelper.checkPermission();
      // if (!checkPermissions) {
      //   emit(const DownloaderSaveVideoFailure(AppStrings.permissionsRequired));
      //   return;
      // }
      final path = await _getPathById(event.video.rId);
      //final path = 'dummy_path';
      final selectedLink = event.video.videoLinks
          .firstWhere((videoLink) => videoLink.quality == event.selectedLink)
          .link;
      final link = _processLink(selectedLink);
      DownloadItem item = DownloadItem(
        video: event.video,
        selectedLink: selectedLink,
        status: DownloadStatus.downloading,
        path: path,
      );
      SaveVideoParams params = SaveVideoParams(savePath: path, videoLink: link);
      int index = _checkIfItemIsExistInDownloads(item);
      _addItem(index, item);
      emit(const DownloaderSaveVideoLoading());
  
      final result = await saveVideoUseCase.call(params);
      result.fold(
        (failure) {
          _updateItem(index, item.copyWith(status: DownloadStatus.error));
          emit(DownloaderSaveVideoFailure(failure.message));
        },
        (right) {
          _updateItem(index, item.copyWith(status: DownloadStatus.success));
          emit(DownloaderSaveVideoSuccess(message: right, path: path));
        },
      );
    }
  
    String _processLink(String link) {
      bool isCorrectLink = link.endsWith(".mp4");
      if (!isCorrectLink) link += ".mp4";
      return link;
    }
  
    Future<String> _getPathById(String id) async {
      final appPath = await DirHelper.getAppPath();
      return "$appPath/$id.mp4";
    }
  
    _updateItem(int index, DownloadItem item) {
      if (index == -1) {
        newDownloads.last = item;
      } else {
        newDownloads[index] = item;
      }
    }
  
    _addItem(int index, DownloadItem item) {
      if (index == -1) {
        newDownloads.add(item);
      } else {
        newDownloads[index] = item.copyWith(status: DownloadStatus.downloading);
      }
    }
  
    int _checkIfItemIsExistInDownloads(DownloadItem item) {
      int index = -1;
      for (int i = 0; i < newDownloads.length; i++) {
        if (newDownloads[i].video == item.video) {
          index = i;
          return index;
        }
      }
      return index;
    }
  
    List<VideoItem> oldDownloads = [];
  
    Future<void> _loadOldDownloads(
      LoadOldDownloads event,
      Emitter<DownloaderState> emit,
    ) async {
      emit(const OldDownloadsLoading());
      oldDownloads.clear();
      final path = await DirHelper.getAppPath();
      final directory = Directory(path);
      final files = await directory.list().toList();
      final newDownloadedVideosPaths = newDownloads.map((e) => e.path);
      for (final file in files) {
        if (file is File && file.path.endsWith('.mp4')) {
          final videoPath = file.path;
          if (newDownloadedVideosPaths.contains(videoPath)) continue;
          final thumbnailPath = await VideoThumbnail.thumbnailFile(
            video: videoPath,
            thumbnailPath: (await getTemporaryDirectory()).path,
            imageFormat: ImageFormat.PNG,
            quality: 30,
          );
          oldDownloads
              .add(VideoItem(path: videoPath)..thumbnailPath = thumbnailPath);
        }
      }
      emit(OldDownloadsLoadingSuccess(downloads: oldDownloads));
    }
  }
  