/*
Montréal Just in Case
Copyright (C) 2011 Mudar Noufal <mn@mudar.ca>
Geographic locations of public safety services. A Montréal Open Data
project.
This file is part of Montréal Just in Case.
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package ca.mudar.mtlaucasou.data;
import android.annotation.SuppressLint;
import android.content.Context;
import android.content.SharedPreferences;
import android.preference.PreferenceManager;
import android.text.TextUtils;
import java.util.Date;
import java.util.HashSet;
import java.util.Locale;
import java.util.Set;
import ca.mudar.mtlaucasou.Const;
import ca.mudar.mtlaucasou.R;
import ca.mudar.mtlaucasou.model.LayerType;
import ca.mudar.mtlaucasou.model.MapType;
import ca.mudar.mtlaucasou.util.MapUtils;
import static ca.mudar.mtlaucasou.util.LogUtils.makeLogTag;
public class UserPrefs implements
Const.PrefsNames {
private static final String TAG = makeLogTag("Settings");
private static UserPrefs instance;
private SharedPreferences mPrefs;
private SharedPreferences.Editor mPrefsEditor;
public static UserPrefs getInstance(Context context) {
if (instance == null) {
instance = new UserPrefs(context);
}
return instance;
}
public static SharedPreferences getSharedPrefs(Context context) {
return context.getSharedPreferences(Const.APP_PREFS_NAME, Context.MODE_PRIVATE);
}
public static void setDefaultValues(Context context) {
PreferenceManager.setDefaultValues(context,
Const.APP_PREFS_NAME,
Context.MODE_PRIVATE,
R.xml.prefs_defaults,
false);
}
private UserPrefs(Context context) {
mPrefs = getSharedPrefs(context);
}
@SuppressLint("CommitPrefEdits")
private SharedPreferences.Editor edit() {
if (mPrefsEditor == null) {
mPrefsEditor = mPrefs.edit();
}
return mPrefsEditor;
}
public boolean hasLoadedData() {
final boolean hasLoadedData = mPrefs.getBoolean(HAS_LOADED_DATA, false);
if (!hasLoadedData) {
// The answer can be true only once. We need commit() instead of apply()
// to avoid possible delay-related issues.
edit().putBoolean(HAS_LOADED_DATA, true)
.commit();
}
return hasLoadedData;
}
public boolean hasAcceptedEula(Context context) {
return mPrefs.getBoolean(HAS_ACCEPTED_EULA, false) || hasAcceptedEulaLegacy(context);
}
/**
* Legacy: EULA settings were stored in the default SharedPreferences.
* For some reason, that seemed like a good idea at the time!
*
* @param context The Context
* @return true if user had accepted EULA in version 1.0
*/
private boolean hasAcceptedEulaLegacy(Context context) {
final SharedPreferences sp = PreferenceManager.getDefaultSharedPreferences(context);
return sp.getBoolean(HAS_ACCEPTED_EULA, false);
}
public void setHasAcceptedEula() {
edit().putBoolean(HAS_ACCEPTED_EULA, true)
.commit();
}
public String getLanguage() {
return mPrefs.getString(LANGUAGE, Locale.getDefault().getLanguage());
}
public void setLanguage(String language) {
edit().putString(LANGUAGE, language)
.commit();
}
public String getUnitsSystem() {
return mPrefs.getString(UNITS_SYSTEM, Const.PrefsValues.UNITS_ISO);
}
public void setUnitsSystem(String units) {
edit().putString(UNITS_SYSTEM, units)
.apply();
}
public boolean isPermissionDeniedForEver() {
return mPrefs.getBoolean(PERMISSION_DENIED_FOR_EVER, false);
}
public void setPermissionDeniedForEver(boolean denied) {
edit().putBoolean(PERMISSION_DENIED_FOR_EVER, denied)
.apply();
}
@SuppressWarnings("WrongConstant")
@MapType
public String getLastMapType() {
return mPrefs.getString(LAST_MAP_TYPE, Const.MapTypes._DEFAULT);
}
public void setLastMapType(@MapType String mapType) {
edit().putString(LAST_MAP_TYPE, mapType)
.apply();
}
@LayerType
public Set<String> getEnabledLayers() {
return mPrefs.getStringSet(LAYERS_ENABLED, Const.PrefsValues.DEFAULT_LAYERS);
}
public boolean isLayerEnabled(@LayerType String layerType) {
return mPrefs.getStringSet(LAYERS_ENABLED, Const.PrefsValues.DEFAULT_LAYERS)
.contains(layerType);
}
public void setLayerEnabledForced(@MapType String mapType, @LayerType String layerType) {
if (MapUtils.isMultiLayerMapType(mapType)) {
setLayerEnabled(layerType, true, true);
}
}
public void setLayerEnabled(@LayerType String layerType, boolean enabled) {
setLayerEnabled(layerType, enabled, false);
}
private void setLayerEnabled(@LayerType String layerType, boolean enabled, boolean commit) {
if (TextUtils.isEmpty(layerType)) {
return;
}
// We need to make a copy of the hashset, not just get a reference
final Set<String> enabledLayers = new HashSet<>(mPrefs.getStringSet(LAYERS_ENABLED,
Const.PrefsValues.DEFAULT_LAYERS));
boolean result = false;
if (enabled && !enabledLayers.contains(layerType)) {
result = enabledLayers.add(layerType);
} else if (!enabled) {
result = enabledLayers.remove(layerType);
}
if (result) {
final SharedPreferences.Editor editor = edit().putStringSet(LAYERS_ENABLED, enabledLayers);
if (commit) {
editor.commit();
} else {
editor.apply();
}
}
}
/**
* Check if the API dataset has updates for the requested dataset item
*
* @param key The local dataset key
* @param updatedAt The remote dataset date to compare to
* @return true if updates are needed
*/
public boolean isApiDataNewer(String key, Date updatedAt) {
return Long.compare(mPrefs.getLong(key, Const.UNKNOWN_VALUE), updatedAt.getTime()) < 0;
}
public void setDataUpdatedAt(String key, Date updatedAt) {
edit().putLong(key, updatedAt.getTime())
.apply();
}
public boolean shouldDisplayLayersShowcase() {
final boolean isFirst = mPrefs.getBoolean(SHOWCASE_LAYERS, true);
if (isFirst) {
edit().putBoolean(SHOWCASE_LAYERS, false)
.apply();
}
return isFirst;
}
}