import 'package:flutter/foundation.dart';
import 'package:rasadyar_core/core.dart';

class HiveLocalStorage implements ILocalStorage {
  @override
  Future init() async {
    if (kIsWeb) {
      Hive.init('hive_storage_rasadyar');
    } else {
      await Hive.initFlutter();
    }
  }

  @override
  Future<void> openBox<T>(
    String boxName, {
    HiveCipher? encryptionCipher,
    bool crashRecovery = true,
    String? path,
    Uint8List? bytes,
    String? collection,
  }) async {
    var exist = await Hive.boxExists(boxName);
    if (!exist || !Hive.isBoxOpen(boxName)) {
      await Hive.openBox<T>(
        boxName,
        encryptionCipher: encryptionCipher,
        crashRecovery: crashRecovery,
      );
    }
  }

  @override
  T? read<T>({required String boxName, required String key}) {
    try {
      Box? box = getBox(boxName);
      return box?.get(key) as T?;
    } on Exception catch (e) {
      eLog(e);
      return null;
    }
  }

  @override
  List<T>? readBox<T>({required String boxName}) {
    try {
      Box? box = getBox<T>(boxName);
      return box?.values.cast<T>().toList();
    } on Exception catch (e) {
      eLog(e);
      return null;
    }
  }

  @override
  Future<void> add<T>({required String boxName, required dynamic value}) async {
    Box<dynamic>? box = getBox<T>(boxName);
    await box?.add(value);
  }

  @override
  Future<void> addAll<T>({required String boxName, required Iterable values}) async {
    Box<dynamic>? box = getBox<T>(boxName);
    await box?.addAll(values);
  }

  Box<T>? getBox<T>(String boxName) {
    final box = Hive.box<T>(boxName);
    return box;
  }

  @override
  Future<void> clear(String boxName) async {
    await Hive.box(boxName).clear();
  }

  @override
  Future<void> close(String boxName) async => await Hive.box(boxName).close();

  @override
  Future<void> deleteValue<T>({required String boxName, required String key}) async {
    Box<dynamic>? box = getBox<T>(boxName);
    await box?.delete(key);
  }

  @override
  Future<void> save<T>({required String boxName, required String key, required value}) async {
    Box<dynamic>? box = getBox<T>(boxName);
    await box?.put(key, value);
  }

  @override
  Future<void> saveAll<T>({required String boxName, required Map entries}) async {
    Box<dynamic>? box = getBox<T>(boxName);
    await box?.putAll(entries);
  }

  @override
  Future<void> saveAt<T>({required String boxName, required int index, required value}) async {
    Box<dynamic>? box = getBox<T>(boxName);
    await box?.putAt(index, value);
  }
}
