import 'package:comunic/models/application_preferences.dart';
import 'package:shared_preferences/shared_preferences.dart';

/// Preferences helper
///
/// Stores current account tokens
///
/// @author Pierre HUBERT

enum PreferencesKeyList {
  USER_ID,
  LOGIN_TOKEN,
  ENABLE_DARK_THEME,
  FORCE_MOBILE_MODE,
  SHOW_PERFORMANCE_OVERLAY,
  PUSH_NOTIFICATIONS_STATUS,
  IS_TOUR_SEEN,
  FOREZ_GROUP,
}

const _PreferenceKeysName = {
  PreferencesKeyList.USER_ID: "user_id",
  PreferencesKeyList.LOGIN_TOKEN: "login_token",
  PreferencesKeyList.ENABLE_DARK_THEME: "dark_theme",
  PreferencesKeyList.FORCE_MOBILE_MODE: "force_mobile_mode",
  PreferencesKeyList.SHOW_PERFORMANCE_OVERLAY: "perfs_overlay",
  PreferencesKeyList.PUSH_NOTIFICATIONS_STATUS: "push_notifications_status",
  PreferencesKeyList.IS_TOUR_SEEN: "is_tour_seen",
  PreferencesKeyList.FOREZ_GROUP: "forez_group",
};

class PreferencesHelper {
  static PreferencesHelper? _instance;

  static Future<PreferencesHelper> getInstance() async {
    if (_instance == null) {
      _instance = PreferencesHelper._();
      await _init();
    }

    return _instance!;
  }

  static late SharedPreferences _sharedPreferences;

  PreferencesHelper._();

  static Future<void> _init() async {
    _sharedPreferences = await SharedPreferences.getInstance();
  }

  /// Set new login tokens
  Future<void> setLoginToken(String? token) async {
    if (token != null)
      await setString(PreferencesKeyList.LOGIN_TOKEN, token);
    else
      await removeKey(PreferencesKeyList.LOGIN_TOKEN);
  }

  /// Get current [LoginTokens]. Returns null if none or in case of failure
  String? getLoginToken() {
    try {
      final string = getString(PreferencesKeyList.LOGIN_TOKEN);
      return string;
    } on Exception catch (e) {
      print(e.toString());
      return null;
    }
  }

  bool containsKey(PreferencesKeyList key) {
    return _sharedPreferences.containsKey(_PreferenceKeysName[key]!);
  }

  Future<bool> removeKey(PreferencesKeyList key) async {
    return await _sharedPreferences.remove(_PreferenceKeysName[key]!);
  }

  Future<bool> setString(PreferencesKeyList key, String value) async {
    return await _sharedPreferences.setString(_PreferenceKeysName[key]!, value);
  }

  String? getString(PreferencesKeyList key) {
    return _sharedPreferences.getString(_PreferenceKeysName[key]!);
  }

  Future<bool> setBool(PreferencesKeyList key, bool value) async {
    return await _sharedPreferences.setBool(_PreferenceKeysName[key]!, value);
  }

  Future<bool> setInt(PreferencesKeyList key, int value) async {
    return await _sharedPreferences.setInt(_PreferenceKeysName[key]!, value);
  }

  int? getInt(PreferencesKeyList key) {
    return _sharedPreferences.getInt(_PreferenceKeysName[key]!);
  }

  bool getBool(PreferencesKeyList key, {bool alternative = false}) {
    final v = _sharedPreferences.getBool(_PreferenceKeysName[key]!);
    return v == null ? alternative : v;
  }

  /// Get all settings as an [ApplicationPreferences] object
  ApplicationPreferences get preferences => ApplicationPreferences(
      enableDarkMode: getBool(PreferencesKeyList.ENABLE_DARK_THEME),
      forceMobileMode: getBool(PreferencesKeyList.FORCE_MOBILE_MODE),
      showPerformancesOverlay:
          getBool(PreferencesKeyList.SHOW_PERFORMANCE_OVERLAY));

  /// Apply new preferences
  Future<void> setPreferences(ApplicationPreferences preferences) async {
    await setBool(
        PreferencesKeyList.ENABLE_DARK_THEME, preferences.enableDarkMode);
  }
}

PreferencesHelper? preferences() {
  if (PreferencesHelper._instance == null)
    throw Exception("Try to get preference before their initialization!");

  return PreferencesHelper._instance;
}