package yuku.afw.storage;
import android.annotation.TargetApi;
import android.content.SharedPreferences;
import android.content.res.Resources;
import android.os.Build;
import android.os.SystemClock;
import android.preference.PreferenceManager;
import android.support.annotation.BoolRes;
import android.support.annotation.IntegerRes;
import android.support.annotation.StringRes;
import android.util.Log;
import yuku.afw.App;
import yuku.afw.BuildConfig;
import java.util.HashSet;
import java.util.Map;
import java.util.Set;
import java.util.WeakHashMap;
public class Preferences {
private static final String TAG = Preferences.class.getSimpleName();
private static SharedPreferences cache;
private static boolean dirty = true;
private static SharedPreferences.Editor currentEditor;
private static int held = 0;
private static WeakHashMap<SharedPreferences.OnSharedPreferenceChangeListener, Void> observers = new WeakHashMap<>();
public static void invalidate() {
dirty = true;
}
private static SharedPreferences.Editor getEditor(SharedPreferences pref) {
if (currentEditor == null) {
currentEditor = pref.edit();
}
return currentEditor;
}
public static int getInt(Enum<?> key, int def) {
return getInt(key.toString(), def);
}
public static int getInt(String key, int def) {
SharedPreferences pref = read();
return pref.getInt(key, def);
}
public static float getFloat(Enum<?> key, float def) {
SharedPreferences pref = read();
return pref.getFloat(key.toString(), def);
}
public static float getFloat(String key, float def) {
SharedPreferences pref = read();
return pref.getFloat(key, def);
}
public static long getLong(Enum<?> key, long def) {
return getLong(key.toString(), def);
}
public static long getLong(String key, long def) {
SharedPreferences pref = read();
return pref.getLong(key, def);
}
public static String getString(Enum<?> key, String def) {
SharedPreferences pref = read();
return pref.getString(key.toString(), def);
}
public static String getString(String key, String def) {
SharedPreferences pref = read();
return pref.getString(key, def);
}
public static String getString(Enum<?> key) {
SharedPreferences pref = read();
return pref.getString(key.toString(), null);
}
public static String getString(String key) {
SharedPreferences pref = read();
return pref.getString(key, null);
}
public static boolean getBoolean(Enum<?> key, boolean def) {
return getBoolean(key.toString(), def);
}
public static boolean getBoolean(String key, boolean def) {
SharedPreferences pref = read();
return pref.getBoolean(key, def);
}
public static Object get(String key) {
SharedPreferences pref = read();
return pref.getAll().get(key);
}
public static Map<String, ?> getAll() {
SharedPreferences pref = read();
return pref.getAll();
}
public static Set<String> getAllKeys() {
return new HashSet<>(getAll().keySet());
}
public static void setInt(Enum<?> key, int val) {
setInt(key.toString(), val);
}
public static void setInt(String key, int val) {
SharedPreferences pref = read();
getEditor(pref).putInt(key, val);
commitIfNotHeld();
if (BuildConfig.DEBUG) Log.d(TAG, key + " = (int) " + val);
}
public static void setFloat(Enum<?> key, float val) {
setFloat(key.toString(), val);
}
public static void setFloat(String key, float val) {
SharedPreferences pref = read();
getEditor(pref).putFloat(key, val);
commitIfNotHeld();
if (BuildConfig.DEBUG) Log.d(TAG, key + " = (float) " + val);
}
public static void setLong(Enum<?> key, long val) {
setLong(key.toString(), val);
}
public static void setLong(String key, long val) {
SharedPreferences pref = read();
getEditor(pref).putLong(key, val);
commitIfNotHeld();
if (BuildConfig.DEBUG) Log.d(TAG, key + " = (long) " + val);
}
public static void setString(Enum<?> key, String val) {
setString(key.toString(), val);
}
public static void setString(String key, String val) {
SharedPreferences pref = read();
getEditor(pref).putString(key, val);
commitIfNotHeld();
if (BuildConfig.DEBUG) Log.d(TAG, key + " = (string) " + val);
}
public static void setString(@StringRes final int keyStringResId, String val) {
final Resources r = App.context.getResources();
final String key = r.getString(keyStringResId);
setString(key, val);
}
public static void setBoolean(Enum<?> key, boolean val) {
setBoolean(key.toString(), val);
}
public static void setBoolean(String key, boolean val) {
SharedPreferences pref = read();
getEditor(pref).putBoolean(key, val);
commitIfNotHeld();
if (BuildConfig.DEBUG) Log.d(TAG, key + " = (bool) " + val);
}
public static boolean contains(final Enum<?> key) {
SharedPreferences pref = read();
return pref.contains(key.toString());
}
public static boolean contains(final String key) {
SharedPreferences pref = read();
return pref.contains(key);
}
public static void remove(Enum<?> key) {
remove(key.toString());
}
public static void remove(String key) {
SharedPreferences pref = read();
getEditor(pref).remove(key);
commitIfNotHeld();
if (BuildConfig.DEBUG) Log.d(TAG, key + " removed");
}
public static int getInt(@StringRes final int keyStringResId, @IntegerRes final int defaultIntResId) {
final Resources r = App.context.getResources();
final String key = r.getString(keyStringResId);
final Object value = get(key);
if (value == null) {
return r.getInteger(defaultIntResId);
} else {
return (int) value;
}
}
public static boolean getBoolean(@StringRes final int keyStringResId, @BoolRes final int defaultBoolResId) {
final Resources r = App.context.getResources();
final String key = r.getString(keyStringResId);
final Object value = get(key);
if (value == null) {
return r.getBoolean(defaultBoolResId);
} else {
return (boolean) value;
}
}
public static String getString(@StringRes final int keyStringResId, @StringRes final int defaultStringResId) {
final Resources r = App.context.getResources();
final String key = r.getString(keyStringResId);
final Object value = get(key);
if (value == null) {
return r.getString(defaultStringResId);
} else {
return (String) value;
}
}
public static String getString(@StringRes final int keyStringResId) {
final Resources r = App.context.getResources();
final String key = r.getString(keyStringResId);
final Object value = get(key);
if (value == null) {
return null;
} else {
return (String) value;
}
}
@TargetApi(9) private synchronized static void commitIfNotHeld() {
if (held > 0) {
// don't do anything now
} else {
if (currentEditor != null) {
if (Build.VERSION.SDK_INT >= 9) {
currentEditor.apply();
} else {
currentEditor.commit();
}
currentEditor = null;
}
}
}
public synchronized static void hold() {
held++;
}
public synchronized static void unhold() {
if (held <= 0) {
throw new RuntimeException("unhold called too many times");
}
held--;
if (held == 0) {
if (currentEditor != null) {
if (Build.VERSION.SDK_INT >= 9) {
currentEditor.apply();
} else {
currentEditor.commit();
}
currentEditor = null;
}
}
}
public synchronized static void registerObserver(final SharedPreferences.OnSharedPreferenceChangeListener observer) {
SharedPreferences pref = read();
pref.registerOnSharedPreferenceChangeListener(observer);
observers.put(observer, null);
}
public synchronized static void unregisterObserver(final SharedPreferences.OnSharedPreferenceChangeListener observer) {
SharedPreferences pref = read();
pref.unregisterOnSharedPreferenceChangeListener(observer);
observers.remove(observer);
}
private synchronized static SharedPreferences read() {
SharedPreferences res;
if (dirty || cache == null) {
long start = 0;
if (BuildConfig.DEBUG) start = SystemClock.uptimeMillis();
res = PreferenceManager.getDefaultSharedPreferences(App.context);
if (BuildConfig.DEBUG) Log.d(TAG, "Preferences was read from disk in " + (SystemClock.uptimeMillis() - start) + " ms");
dirty = false;
// re-register observers if the SharedPreferences object changes
if (cache != null && res != cache && observers.size() > 0) {
for (final SharedPreferences.OnSharedPreferenceChangeListener observer : observers.keySet()) {
cache.unregisterOnSharedPreferenceChangeListener(observer);
res.registerOnSharedPreferenceChangeListener(observer);
}
}
cache = res;
} else {
res = cache;
}
return res;
}
}