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

import 'i_local_storage.dart';

class HiveLocalStorage implements ILocalStorage {
  HiveLocalStorage() {
    Hive.initFlutter();
  }

  final Map<String, Box> _boxes = {};

  @override
  Future init() async => await Hive.initFlutter();

  @override
  Future<void> openBox<T>(
    String boxName, {
    HiveCipher? encryptionCipher,
    bool crashRecovery = true,
    String? path,
    Uint8List? bytes,
    String? collection,
  }) async {
    if (!_boxes.containsKey(boxName)) {
      final box = await Hive.openBox<T>(
        boxName,
        encryptionCipher: encryptionCipher,
        crashRecovery: crashRecovery,
      );
      _boxes[boxName] = box;
    }
  }

  @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
  Future<void> add({required String boxName, required dynamic value}) async {
    Box<dynamic>? box = getBox(boxName);
    await box?.add(value);
  }

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

  Box<T>? getBox<T>(String boxName) {
    final box = _boxes[boxName];
    if (box is Box<T>) {
      return box;
    } else {
      throw Exception('Box $boxName is not of exist');
    }
  }

  @override
  Future<void> clear(String boxName) async {
    await _boxes[boxName]?.clear();
  }

  @override
  Future<void> close(String boxName) async => await _boxes[boxName]?.close();

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

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

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

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