content: // ignore_for_file: depend_on_referenced_packages
  import 'dart:io';
  import 'package:isar/isar.dart';
  import 'package:mangayomi/eval/model/source_preference.dart';
  import 'package:mangayomi/main.dart';
  import 'package:mangayomi/models/category.dart';
  import 'package:mangayomi/models/changed.dart';
  import 'package:mangayomi/models/chapter.dart';
  import 'package:mangayomi/models/custom_button.dart';
  import 'package:mangayomi/models/download.dart';
  import 'package:mangayomi/models/update.dart';
  import 'package:mangayomi/models/history.dart';
  import 'package:mangayomi/models/manga.dart';
  import 'package:mangayomi/models/settings.dart';
  import 'package:mangayomi/models/source.dart';
  import 'package:mangayomi/models/sync_preference.dart';
  import 'package:mangayomi/models/track.dart';
  import 'package:mangayomi/models/track_preference.dart';
  import 'package:mangayomi/utils/extensions/string_extensions.dart';
  import 'package:path_provider/path_provider.dart';
  import 'package:permission_handler/permission_handler.dart';
  import 'package:path/path.dart' as path;
  
  class StorageProvider {
    static bool _hasPermission = false;
    Future<bool> requestPermission() async {
      if (_hasPermission) return true;
      if (Platform.isAndroid) {
        Permission permission = Permission.manageExternalStorage;
        if (await permission.isGranted) {
          return true;
        } else {
          final result = await permission.request();
          if (result == PermissionStatus.granted) {
            _hasPermission = true;
            return true;
          }
          return false;
        }
      }
      return true;
    }
  
    Future<void> deleteBtDirectory() async {
      final d = await getBtDirectory();
      await Directory(d!.path).delete(recursive: true);
    }
  
    Future<void> deleteTmpDirectory() async {
      final d = await getTmpDirectory();
      await Directory(d!.path).delete(recursive: true);
    }
  
    Future<Directory?> getDefaultDirectory() async {
      Directory? directory;
      if (Platform.isAndroid) {
        directory = Directory("/storage/emulated/0/Mangayomi/");
      } else {
        final dir = await getApplicationDocumentsDirectory();
        directory = Directory(path.join(dir.path, 'Mangayomi'));
      }
      return directory;
    }
  
    Future<Directory?> getMpvDirectory() async {
      final defaultDirectory = await getDefaultDirectory();
      String dbDir = path.join(defaultDirectory!.path, 'mpv');
      await Directory(dbDir).create(recursive: true);
      return Directory(dbDir);
    }
  
    Future<Directory?> getBtDirectory() async {
      final gefaultDirectory = await getDefaultDirectory();
      String dbDir = path.join(gefaultDirectory!.path, 'torrents');
      await Directory(dbDir).create(recursive: true);
      return Directory(dbDir);
    }
  
    Future<Directory?> getTmpDirectory() async {
      final gefaultDirectory = await getDirectory();
      String dbDir = path.join(gefaultDirectory!.path, 'tmp');
      await Directory(dbDir).create(recursive: true);
      return Directory(dbDir);
    }
  
    Future<Directory?> getIosBackupDirectory() async {
      final gefaultDirectory = await getDefaultDirectory();
      String dbDir = path.join(gefaultDirectory!.path, 'backup');
      await Directory(dbDir).create(recursive: true);
      return Directory(dbDir);
    }
  
    Future<Directory?> getDirectory() async {
      Directory? directory;
      String dPath = isar.settings.getSync(227)!.downloadLocation ?? "";
      if (Platform.isAndroid) {
        directory = Directory(
          dPath.isEmpty ? "/storage/emulated/0/Mangayomi/" : "$dPath/",
        );
      } else {
        final dir = await getApplicationDocumentsDirectory();
        final p = dPath.isEmpty ? dir.path : dPath;
        directory = Directory(path.join(p, 'Mangayomi'));
      }
      return directory;
    }
  
    Future<Directory?> getMangaMainDirectory(Chapter chapter) async {
      final manga = chapter.manga.value!;
      final itemType = chapter.manga.value!.itemType;
      final itemTypePath = itemType == ItemType.manga
          ? "Manga"
          : itemType == ItemType.anime
          ? "Anime"
          : "Novel";
      final dir = await getDirectory();
      return Directory(
        path.join(
          dir!.path,
          'downloads',
          itemTypePath,
          '${manga.source} (${manga.lang!.toUpperCase()})',
          manga.name!.replaceForbiddenCharacters('_'),
        ),
      );
    }
  
    Future<Directory?> getMangaChapterDirectory(
      Chapter chapter, {
      Directory? mangaMainDirectory,
    }) async {
      final basedir = mangaMainDirectory ?? await getMangaMainDirectory(chapter);
      String scanlator = chapter.scanlator?.isNotEmpty ?? false
          ? "${chapter.scanlator!.replaceForbiddenCharacters('_')}_"
          : "";
      return Directory(
        path.join(
          basedir!.path,
          scanlator + chapter.name!.replaceForbiddenCharacters('_').trim(),
        ),
      );
    }
  
    Future<Directory?> getDatabaseDirectory() async {
      final dir = await getApplicationDocumentsDirectory();
      if (Platform.isAndroid || Platform.isIOS || Platform.isMacOS) {
        return dir;
      } else {
        String dbDir = path.join(dir.path, 'Mangayomi', 'databases');
        await Directory(dbDir).create(recursive: true);
        return Directory(dbDir);
      }
    }
  
    Future<Directory?> getGalleryDirectory() async {
      String gPath = (await getDirectory())!.path;
      if (Platform.isAndroid) {
        gPath = "/storage/emulated/0/Pictures/Mangayomi/";
      } else {
        gPath = path.join(gPath, 'Pictures');
      }
      await Directory(gPath).create(recursive: true);
      return Directory(gPath);
    }
  
    Future<Isar> initDB(String? path, {bool? inspector = false}) async {
      Directory? dir;
      if (path == null) {
        dir = await getDatabaseDirectory();
      } else {
        dir = Directory(path);
      }
  
      final isar = await Isar.open(
        [
          MangaSchema,
          ChangedPartSchema,
          ChapterSchema,
          CategorySchema,
          CustomButtonSchema,
          UpdateSchema,
          HistorySchema,
          DownloadSchema,
          SourceSchema,
          SettingsSchema,
          TrackPreferenceSchema,
          TrackSchema,
          SyncPreferenceSchema,
          SourcePreferenceSchema,
          SourcePreferenceStringValueSchema,
        ],
        directory: dir!.path,
        name: "mangayomiDb",
        inspector: inspector!,
      );
  
      final settings = await isar.settings.filter().idEqualTo(227).findFirst();
      if (settings == null) {
        await isar.writeTxn(() async {
          isar.settings.put(Settings());
        });
      }
  
      final prefs = await isar.trackPreferences
          .filter()
          .syncIdIsNotNull()
          .findAll();
      await isar.writeTxn(() async {
        for (final pref in prefs) {
          await isar.trackPreferences.put(pref..refreshing = true);
        }
      });
  
      final customButton = await isar.customButtons
          .filter()
          .idIsNotNull()
          .findFirst();
      if (customButton == null) {
        await isar.writeTxn(() async {
          await isar.customButtons.put(
            CustomButton(
              title: "+85 s",
              codePress:
                  """local intro_length = mp.get_property_native("user-data/current-anime/intro-length")
  aniyomi.right_seek_by(intro_length)""",
              codeLongPress:
                  """aniyomi.int_picker("Change intro length", "%ds", 0, 255, 1, "user-data/current-anime/intro-length")""",
              codeStartup: """function update_button(_, length)
    if length ~= nil then
      if length == 0 then
  	  aniyomi.hide_button()
  	  return
  	else
  	  aniyomi.show_button()
  	end
      aniyomi.set_button_title("+" .. length .. " s")
    end
  end
  
  if \$isPrimary then
    mp.observe_property("user-data/current-anime/intro-length", "number", update_button)
  end""",
              isFavourite: true,
              pos: 0,
              updatedAt: DateTime.now().millisecondsSinceEpoch,
            ),
          );
        });
      }
  
      return isar;
    }
  }
  