package com.example.base.utils

/**
 * SharedPreferences封装类
 */

import android.content.Context
import com.google.gson.Gson
import com.google.gson.JsonSyntaxException
import com.google.gson.reflect.TypeToken


object SPUtils {

    private const val PREFERENCE_NAME = "kotlin_preference"

    /**
     * put string preferences

     * @param key   The name of the preference to modify
     * *
     * @param value The new value for the preference
     * *
     * @return True if the new values were successfully written to persistent storage.
     */
    fun putString(key: String, value: String): Boolean {
        val settings =
            Utils.getApp().getSharedPreferences(PREFERENCE_NAME, Context.MODE_PRIVATE)
        val editor = settings.edit()
        editor.putString(key, value)
        return editor.commit()
    }

    fun getString(key: String, defaultValue: String = ""): String {
        val settings =
            Utils.getApp().getSharedPreferences(PREFERENCE_NAME, Context.MODE_PRIVATE)
        return settings.getString(key, defaultValue) ?: ""
    }

    /**
     * put int preferences

     * @param key     The name of the preference to modify
     * *
     * @param value   The new value for the preference
     * *
     * @return True if the new values were successfully written to persistent storage.
     */
    fun putInt(key: String, value: Int): Boolean {
        val settings =
            Utils.getApp().getSharedPreferences(PREFERENCE_NAME, Context.MODE_PRIVATE)
        val editor = settings.edit()
        editor.putInt(key, value)
        return editor.commit()
    }

    /**
     * get int preferences

     * @param key          The name of the preference to retrieve
     * *
     * @param defaultValue Value to return if this preference does not exist
     * *
     * @return The preference value if it exists, or defValue. Throws ClassCastException if there is a preference with
     * * this name that is not a int
     */
    @JvmOverloads
    fun getInt(key: String, defaultValue: Int = -1): Int {
        val settings =
            Utils.getApp().getSharedPreferences(PREFERENCE_NAME, Context.MODE_PRIVATE)
        return settings.getInt(key, defaultValue)
    }

    /**
     * put long preferences

     * @param key   The name of the preference to modify
     * *
     * @param value The new value for the preference
     * *
     * @return True if the new values were successfully written to persistent storage.
     */
    fun putLong(key: String, value: Long): Boolean {
        val settings =
            Utils.getApp().getSharedPreferences(PREFERENCE_NAME, Context.MODE_PRIVATE)
        val editor = settings.edit()
        editor.putLong(key, value)
        return editor.commit()
    }

    /**
     * get long preferences

     * @param key          The name of the preference to retrieve
     * *
     * @param defaultValue Value to return if this preference does not exist
     * *
     * @return The preference value if it exists, or defValue. Throws ClassCastException if there is a preference with
     * * this name that is not a long
     */
    @JvmOverloads
    fun getLong(key: String, defaultValue: Long = -1): Long {
        val settings =
            Utils.getApp().getSharedPreferences(PREFERENCE_NAME, Context.MODE_PRIVATE)
        return settings.getLong(key, defaultValue)
    }

    /**
     * put float preferences

     * @param context
     * *
     * @param key     The name of the preference to modify
     * *
     * @param value   The new value for the preference
     * *
     * @return True if the new values were successfully written to persistent storage.
     */
    fun putFloat(context: Context, key: String, value: Float): Boolean {
        val settings = context.getSharedPreferences(PREFERENCE_NAME, Context.MODE_PRIVATE)
        val editor = settings.edit()
        editor.putFloat(key, value)
        return editor.commit()
    }

    /**
     * get float preferences

     * @param key          The name of the preference to retrieve
     * *
     * @param defaultValue Value to return if this preference does not exist
     * *
     * @return The preference value if it exists, or defValue. Throws ClassCastException if there is a preference with
     * * this name that is not a float
     */
    @JvmOverloads
    fun getFloat(key: String, defaultValue: Float = -1f): Float {
        val settings =
            Utils.getApp().getSharedPreferences(PREFERENCE_NAME, Context.MODE_PRIVATE)
        return settings.getFloat(key, defaultValue)
    }

    /**
     * put boolean preferences

     * @param key   The name of the preference to modify
     * *
     * @param value The new value for the preference
     * *
     * @return True if the new values were successfully written to persistent storage.
     */
    fun putBoolean(key: String, value: Boolean): Boolean {
        val settings =
            Utils.getApp().getSharedPreferences(PREFERENCE_NAME, Context.MODE_PRIVATE)
        val editor = settings.edit()
        editor.putBoolean(key, value)
        return editor.commit()
    }

    /**
     * get boolean preferences

     * @param key          The name of the preference to retrieve
     * *
     * @param defaultValue Value to return if this preference does not exist
     * *
     * @return The preference value if it exists, or defValue. Throws ClassCastException if there is a preference with
     * * this name that is not a boolean
     */
    @JvmOverloads
    fun getBoolean(key: String, defaultValue: Boolean = false): Boolean {
        val settings =
            Utils.getApp().getSharedPreferences(PREFERENCE_NAME, Context.MODE_PRIVATE)
        return settings.getBoolean(key, defaultValue)
    }

    /**
     * 是否已经存在
     */
    fun contains(key: String): Boolean {
        val settings = Utils.getApp().getSharedPreferences(PREFERENCE_NAME, Context.MODE_PRIVATE)
        return settings.contains(key)
    }

    /**
     * 删除
     */
    fun remove(key: String) {
        val settings = Utils.getApp().getSharedPreferences(PREFERENCE_NAME, Context.MODE_PRIVATE)
        settings.edit().remove(key).apply()
    }

    fun clearAllData(): Boolean {
        val settings = Utils.getApp().getSharedPreferences(PREFERENCE_NAME, Context.MODE_PRIVATE)
        val editor = settings.edit()
        editor.clear()
        return editor.commit()
    }

    fun <T> putObject(key: String, obj: T?) {
        if (obj == null) {
            putString(key, "")
        } else {
            val str = Gson().toJson(obj)
            putString(key, str)
        }
    }

    fun putObject(obj: Any?) {
        obj ?: return
        val str = Gson().toJson(obj)
        putString(obj::class.java.simpleName, str)
    }

    inline fun <reified T> putList(list: List<T>?) {
        list ?: return
        val str = Gson().toJson(list)
        putString("list_${T::class.java.simpleName}", str)
    }


    fun <T> getObject(key: String, clazz: Class<T>): T? {
        val str = getString(key)
        if (str.isEmpty()) {
            return null
        }
        return try {
            Gson().fromJson(str, clazz)
        } catch (e: JsonSyntaxException) {
            null
        }
    }

    fun <T> getObject(clazz: Class<T>): T? {
        val str = getString(clazz.simpleName)
        if (str.isEmpty()) {
            return null
        }
        return try {
            Gson().fromJson(str, clazz)
        } catch (e: JsonSyntaxException) {
            null
        }
    }

    inline fun <reified T> getList(): List<T> {
        val str = getString("list_${T::class.java.simpleName}")
        if (str.isEmpty()) {
            return emptyList()
        }
        return try {
            Gson().fromJson(str, object : TypeToken<List<T>?>() {}.type)
        } catch (e: java.lang.Exception) {
            emptyList()
        }
    }

}
