package com.sambath.klaklouk_main.util


import android.app.Application
import android.content.Context
import android.content.SharedPreferences
import android.util.Log
import com.google.gson.GsonBuilder
import com.google.gson.reflect.TypeToken
import com.sambath.klaklouk_main.remote.BettingTypeData
import com.sambath.klaklouk_main.remote.ChannelData
import com.sambath.klaklouk_main.remote.User


/**
 * Singleton class for managing preferences for POJO or model class's object.

 */
object ModelPreferencesManager {

    //Shared Preference field used to save and retrieve JSON string
    lateinit var preferences: SharedPreferences

    //Name of Shared Preference file
    private const val PREFERENCES_FILE_NAME = "PREFERENCES_MODEL_FILE"

    /**
     * Call this first before retrieving or saving object.
     *
     * @param application Instance of application class
     */
    fun with(application: Application) {
        preferences = application.getSharedPreferences(
            PREFERENCES_FILE_NAME, Context.MODE_PRIVATE
        )
    }

    /**
     * Saves object into the Preferences.
     *
     * @param `object` Object of model class (of type [T]) to save
     * @param key Key with which Shared preferences to
     **/
    fun <T> put(`object`: T, key: String) {
        //Convert object to JSON String.
        val jsonString = GsonBuilder().create().toJson(`object`)
        //Save that String in SharedPreferences
        preferences.edit().putString(key, jsonString).apply()
    }

    fun putCfList(list: List<BettingTypeData>, key: String) {
        val jsonString = GsonBuilder().create().toJson(list)
        preferences.edit().putString(key, jsonString).apply()
    }

    fun putUser(user: User, key: String) {
        val jsonString = GsonBuilder().create().toJson(user)
        Log.d("saveUser", "put" + jsonString)
        preferences.edit().putString(key, jsonString).apply()
    }

    fun putChannel(channel: ChannelData, key: String) {
        val jsonString = GsonBuilder().create().toJson(channel)
        preferences.edit().putString(key, jsonString).apply()
    }

    fun putChannelList(list: List<Int>, key: String) {
        val jsonString = GsonBuilder().create().toJson(list)
        preferences.edit().putString(key, jsonString).apply()
    }

    /**
     * Used to retrieve object from the Preferences.
     *
     * @param key Shared Preference key with which object was saved.
     **/
    fun getCfList(key: String): List<BettingTypeData>? {
        val value = preferences.getString(key, null)
        val type = object : TypeToken<List<BettingTypeData>>() {}.type
        return GsonBuilder().create().fromJson<List<BettingTypeData>>(value, type)
    }

    fun getChannel(key: String): ChannelData? {
        val value = preferences.getString(key, null)
        val type = object : TypeToken<ChannelData>() {}.type
        return GsonBuilder().create().fromJson<ChannelData>(value, type)
    }

    fun getChannelList(key: String): List<Int>? {
        val value = preferences.getString(key, null)
        val type = object : TypeToken<List<Int>>() {}.type
        return GsonBuilder().create().fromJson<List<Int>>(value, type)
    }

    fun getUser(key: String): User? {
        val value = preferences.getString(key, null)
        val type = object : TypeToken<User>() {}.type
        return GsonBuilder().create().fromJson<User>(value, type)
    }

    inline fun <reified T> get(key: String): T? {
        //We read JSON String which was saved.
        val value = preferences.getString(key, null)
        //JSON String was found which means object can be read.
        //We convert this JSON String to model object. Parameter "c" (of
        //type Class < T >" is used to cast.
        return GsonBuilder().create().fromJson(value, T::class.java)
    }
}