package net.pokeranalytics.android.util import android.content.Context import android.os.Build import android.preference.PreferenceManager import android.view.View import io.realm.Realm import net.pokeranalytics.android.PokerAnalyticsApplication import net.pokeranalytics.android.R import net.pokeranalytics.android.model.realm.Bankroll import net.pokeranalytics.android.model.realm.ResultCaptureType import net.pokeranalytics.android.model.realm.Session import net.pokeranalytics.android.ui.extensions.openUrl import net.pokeranalytics.android.util.extensions.count import java.util.* class Preferences { interface PreferenceKey { val identifier: String } enum class Keys(override var identifier: String) : PreferenceKey { CURRENCY_CODE("CurrencyCode"), LOCALE_CODE("LocaleCode"), // FIRST_LAUNCH("firstLaunch"), STOP_SHOWING_DISCLAIMER("stopShowingDisclaimer"), STOP_SHOWING_DUPLICATE("stopShowingDuplicate"), STOP_SHOWING_DISCORD("stopShowingDiscord"), ACTIVE_FILTER_ID("ActiveFilterId"), LATEST_PURCHASE("latestPurchase"), PATCH_BREAK("patchBreaks"), PATCH_SESSION_SETS("patchSessionSet"), PATCH_TRANSACTION_TYPES_NAMES("patchTransactionTypesNames"), PATCH_BLINDS_FORMAT("patchBlindFormat"), PATCH_COMPUTABLE_RESULTS("patchPositiveSessions"), SHOW_STOP_NOTIFICATIONS("showStopNotifications"), ADD_NEW_TRANSACTION_TYPES("addNewTransactionTypes"), SHOW_VILLAIN_CARDS("showVillainCards"), BANKROLL_RESULT_CAPTURE_TYPE("bankrollResultCaptureType_"), LATEST_BLOG_POST_ID_RETRIEVED("latestBlogPostIdRetrieved"), LATEST_BLOG_POST_ID_DISPLAYED("latestBlogPostIdDisplayed"), LAST_BLOG_TIPS_RETRIEVAL("lastBlogTipsRetrieval"), SHOW_BLOG_TIPS("showBlogTips"), } enum class FeedMessage { DISCLAIMER, DISCORD, DUPLICATE; val resId: Int get() { return when (this) { DISCLAIMER -> R.string.disclaimer DUPLICATE -> R.string.longtap_to_duplicate DISCORD -> R.string.discord_feed_message } } val key: Keys get() { return when (this) { DISCLAIMER -> Keys.STOP_SHOWING_DISCLAIMER DUPLICATE -> Keys.STOP_SHOWING_DUPLICATE DISCORD -> Keys.STOP_SHOWING_DISCORD } } val actionResId: Int? get() { return when (this) { DISCORD -> R.string.join_discord else -> null } } fun action(context: Context): ((View) -> (Unit))? { return when (this) { DISCORD -> { { context.openUrl(URL.DISCORD.value) } } else -> null } } val dismissResId: Int get() { return when (this) { DISCORD -> R.string.good_for_you else -> R.string.iunderstand } } } companion object { fun setString(key: PreferenceKey, value: String, context: Context) { val preferences = PreferenceManager.getDefaultSharedPreferences(context) val editor = preferences.edit() editor.putString(key.identifier, value) editor.apply() } fun getString(key: Keys, context: Context): String? { val preferences = PreferenceManager.getDefaultSharedPreferences(context) return preferences.getString(key.identifier, null) } private fun setBoolean(key: PreferenceKey, value: Boolean, context: Context) { val preferences = PreferenceManager.getDefaultSharedPreferences(context) val editor = preferences.edit() editor.putBoolean(key.identifier, value) editor.apply() } private fun getBoolean(key: PreferenceKey, context: Context, defaultValue: Boolean? = false): Boolean { val preferences = PreferenceManager.getDefaultSharedPreferences(context) return preferences.getBoolean(key.identifier, defaultValue ?: false) } private fun setInt(key: PreferenceKey, value: Int, context: Context) { val preferences = PreferenceManager.getDefaultSharedPreferences(context) val editor = preferences.edit() editor.putInt(key.identifier, value) editor.apply() } private fun getInt(key: PreferenceKey, context: Context): Int { val preferences = PreferenceManager.getDefaultSharedPreferences(context) return preferences.getInt(key.identifier, -1) } private fun setLong(key: PreferenceKey, value: Long, context: Context) { val preferences = PreferenceManager.getDefaultSharedPreferences(context) val editor = preferences.edit() editor.putLong(key.identifier, value) editor.apply() } private fun getLong(key: PreferenceKey, context: Context): Long { val preferences = PreferenceManager.getDefaultSharedPreferences(context) return preferences.getLong(key.identifier, 0L) } fun setShowVillainCards(show: Boolean, context: Context) { setBoolean(Keys.SHOW_VILLAIN_CARDS, show, context) } fun getShowVillainCards(context: Context): Boolean { return getBoolean(Keys.SHOW_VILLAIN_CARDS, context, true) } fun setCurrencyCode(currencyCode: String, context: Context) { setString(Keys.CURRENCY_CODE, currencyCode, context) UserDefaults.setCurrencyValues(context) } fun setActiveFilterId(filterId: String, context: Context) { setString(Keys.ACTIVE_FILTER_ID, filterId, context) } fun getActiveFilterId(context: Context): String? { return getString(Keys.ACTIVE_FILTER_ID, context) } private fun getCurrencyCode(context: Context): String? { return getString(Keys.CURRENCY_CODE, context) } private fun getCurrencyLocale(context: Context): Locale? { getCurrencyCode(context)?.let { currencyCode -> UserDefaults.availableCurrencyLocales.firstOrNull { Currency.getInstance(it).currencyCode == currencyCode }?.let { return it } } return null } fun getDefaultCurrency(context: Context): Currency? { getCurrencyLocale(context)?.let { return Currency.getInstance(it) } return null } fun setShowStopNotifications(show: Boolean, context: Context) { setBoolean(Keys.SHOW_STOP_NOTIFICATIONS, show, context) } fun showStopNotifications(context: Context): Boolean { val defaultValue = (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) return getBoolean(Keys.SHOW_STOP_NOTIFICATIONS, context, defaultValue) } fun setStopShowingMessage(message: FeedMessage, context: Context) { setBoolean(message.key, true, context) } fun feedMessageToShow(context: Context): FeedMessage? { if (!getBoolean(Keys.STOP_SHOWING_DISCLAIMER, context)) { return FeedMessage.DISCLAIMER } val realm = Realm.getDefaultInstance() val sessionCount = realm.count(Session::class.java) realm.close() if (sessionCount > 1 && !getBoolean(Keys.STOP_SHOWING_DUPLICATE, context)) { return FeedMessage.DUPLICATE } if (!getBoolean(Keys.STOP_SHOWING_DISCORD, context) && PokerAnalyticsApplication.timeSinceInstall(context) > 1000 * 3600 * 24 * 30L) { return FeedMessage.DISCORD } return null } fun executeOnce(key: Keys, context: Context, executable: () -> Unit) { if (!getBoolean(key, context)) { executable.invoke() setBoolean(key, true, context) } } // fun executeOnceInThread(key: Keys, context: Context, executable: () -> Unit) { // // if (!getBoolean(key, context)) { // Thread { executable.invoke() } // setBoolean(key, true, context) // } // } fun setResultCaptureType(bankroll: Bankroll, type: ResultCaptureType, context: Context) { val key = "${Keys.BANKROLL_RESULT_CAPTURE_TYPE}${bankroll.id}" val preferences = PreferenceManager.getDefaultSharedPreferences(context) val editor = preferences.edit() editor.putInt(key, type.ordinal) editor.apply() } fun getResultCaptureType(bankroll: Bankroll, context: Context): ResultCaptureType? { val key = "${Keys.BANKROLL_RESULT_CAPTURE_TYPE}${bankroll.id}" val preferences = PreferenceManager.getDefaultSharedPreferences(context) return when (val ordinal = preferences.getInt(key, -1)) { -1 -> null else -> ResultCaptureType.values()[ordinal] } } fun setLatestRetrievedBlogPostId(id: Int, context: Context) { setInt(Keys.LATEST_BLOG_POST_ID_RETRIEVED, id, context) } private fun getLatestRetrievedBlogPostId(context: Context): Int { return getInt(Keys.LATEST_BLOG_POST_ID_RETRIEVED, context) } fun setBlogTipsTapped(context: Context) { setInt(Keys.LATEST_BLOG_POST_ID_DISPLAYED, getLatestRetrievedBlogPostId(context), context) } fun getLatestDisplayedBlogPostId(context: Context): Int { return getInt(Keys.LATEST_BLOG_POST_ID_DISPLAYED, context) } fun showBlogTips(show: Boolean, context: Context) { setLastBlogTipsRetrievalDate(0L, context) setBoolean(Keys.SHOW_BLOG_TIPS, show, context) } fun shouldShowBlogTips(context: Context): Boolean { return getBoolean(Keys.SHOW_BLOG_TIPS, context, true) } fun setLastBlogTipsRetrievalDate(date: Long, context: Context) { setLong(Keys.LAST_BLOG_TIPS_RETRIEVAL, date, context) } fun getLastBlogTipsRetrievalDate(context: Context): Long { return getLong(Keys.LAST_BLOG_TIPS_RETRIEVAL, context) } } } class UserDefaults private constructor(context: Context) { init { setCurrencyValues(context) } companion object : SingletonHolder(::UserDefaults) { lateinit var currency: Currency fun setCurrencyValues(context: Context) { currency = Preferences.getDefaultCurrency(context) ?: getLocaleCurrency() } val availableCurrencyLocales = Locale.getAvailableLocales().mapNotNull { try { Currency.getInstance(it) it } catch (e: Exception) { null } } /** * Return the locale currency, or en_US if there */ fun getLocaleCurrency(): Currency { return try { Currency.getInstance(Locale.getDefault()) } catch (ex: Exception) { when (Locale.getDefault().language) { "en" -> Currency.getInstance(Locale("en", "US")) "fr" -> Currency.getInstance(Locale("fr", "FR")) "es" -> Currency.getInstance(Locale("es", "ES")) "de" -> Currency.getInstance(Locale("de", "DE")) "ja" -> Currency.getInstance(Locale("ja", "JP")) "zh" -> Currency.getInstance(Locale("zh", "CN")) else -> Currency.getInstance(Locale("en", "US")) } } } } } open class SingletonHolder(creator: (A) -> T) { private var creator: ((A) -> T)? = creator @Volatile private var instance: T? = null fun init(context: A): T { val i = instance if (i != null) { return i } return synchronized(this) { val i2 = instance if (i2 != null) { i2 } else { val created = creator!!(context) instance = created creator = null created } } } }