package com.nivesh.production.partnerOnBoarding.db

import android.content.Context
import android.content.SharedPreferences
import com.nivesh.production.partnerOnBoarding.interfaces.IPreferenceHelper

open class PreferenceManager(context: Context) : IPreferenceHelper {
    private val preferenceName = "NiveshFDSDK"
    private var preferences: SharedPreferences = context.getSharedPreferences(preferenceName, Context.MODE_PRIVATE)

    companion object {
        const val KEY_CLIENT_CODE = "ClientCode"
        const val KEY_PARTNER_CODE = "PartnerCode"
        const val KEY_GET_TOKEN = "GetToken"
        const val IS_FIRST_TIME = "IS FIRST TIME"
    }


    override fun setClientCode(appName: String) {
        preferences[KEY_CLIENT_CODE] = appName
    }

    override fun getClientCode(): String {
        return preferences[KEY_CLIENT_CODE] ?: ""
    }

    override fun setPartnerCode(partnerCode: String) {
         preferences[KEY_PARTNER_CODE] = partnerCode
    }

    override fun getPartnerCode(): String {
        return preferences[KEY_PARTNER_CODE] ?: ""
    }

    override fun setToken(appName: String) {
        preferences[KEY_GET_TOKEN] = appName
    }

    override fun getToken(): String {
        return preferences[KEY_GET_TOKEN] ?: ""
    }


    override fun setIsFirstTime(appName: Boolean) {
        preferences[IS_FIRST_TIME] = appName
    }

    override fun getFirstTime(): Boolean {
        return preferences[IS_FIRST_TIME] ?: false
    }


    override fun clearPrefs() {
        preferences.edit().clear().apply()
    }

}


/**
 * SharedPreferences extension function, to listen the edit() and apply() fun calls
 * on every SharedPreferences operation.
 */
private inline fun SharedPreferences.edit(operation: (SharedPreferences.Editor) -> Unit) {
    val editor = this.edit()
    operation(editor)
    editor.apply()
}

/**
 * puts a key value pair in shared prefs if doesn't exists, otherwise updates value on given [key]
 */
private operator fun SharedPreferences.set(key: String, value: Any?) {
    when (value) {
        is String? -> edit { it.putString(key, value) }
        is Int -> edit { it.putInt(key, value) }
        is Boolean -> edit { it.putBoolean(key, value) }
        is Float -> edit { it.putFloat(key, value) }
        is Long -> edit { it.putLong(key, value) }
        else -> throw UnsupportedOperationException("Not yet implemented")
    }
}

/**
 * finds value on given key.
 * [T] is the type of value
 * @param defaultValue optional default value - will take null for strings, false for bool and -1 for numeric values if [defaultValue] is not specified
 */
private inline operator fun <reified T : Any> SharedPreferences.get(
    key: String,
    defaultValue: T? = null
): T? {
    return when (T::class) {
        String::class -> getString(key, defaultValue as? String) as T?
        Int::class -> getInt(key, defaultValue as? Int ?: -1) as T?
        Boolean::class -> getBoolean(key, defaultValue as? Boolean ?: false) as T?
        Float::class -> getFloat(key, defaultValue as? Float ?: -1f) as T?
        Long::class -> getLong(key, defaultValue as? Long ?: -1) as T?
        else -> throw UnsupportedOperationException("Not yet implemented")
    }
}