package de.storchp.fdroidbuildstatus.utils

import android.content.Context
import android.content.SharedPreferences
import androidx.appcompat.app.AppCompatDelegate
import androidx.core.content.edit
import androidx.preference.PreferenceManager
import de.storchp.fdroidbuildstatus.R
import de.storchp.fdroidbuildstatus.model.BuildCycle
import de.storchp.fdroidbuildstatus.model.BuildlogType
import de.storchp.fdroidbuildstatus.model.MetadataLinkType
import de.storchp.fdroidbuildstatus.model.StatusFilter

class PreferencesService(private val context: Context) {
    private val preferences: SharedPreferences =
        PreferenceManager.getDefaultSharedPreferences(context)

    fun isFavouritesFilter(): Boolean {
        return preferences.getBoolean(context.getString(R.string.PREF_FAVOURITES_FILTER), false)
    }

    fun isNotifyPublish(): Boolean {
        return preferences.getBoolean(context.getString(R.string.PREF_NOTIFY_PUBLISH), false)
    }

    fun isNotifyRunningBuilds(): Boolean {
        return preferences.getBoolean(context.getString(R.string.PREF_NOTIFY_RUNNING_BUILDS), false)
    }

    fun isNotifyFinishedBuilds(): Boolean {
        return preferences.getBoolean(
            context.getString(R.string.PREF_NOTIFY_FINISHED_BUILDS),
            false
        )
    }

    fun isBackgroundNotificationsEnabled(): Boolean {
        return isNotifyRunningBuilds() || isNotifyFinishedBuilds() || isNotifyPublish()
    }

    fun disableBackgroundNotifications() {
        putBoolean(R.string.PREF_NOTIFY_PUBLISH, false)
        putBoolean(R.string.PREF_NOTIFY_RUNNING_BUILDS, false)
        putBoolean(R.string.PREF_NOTIFY_FINISHED_BUILDS, false)
    }

    fun setFavouritesFilter(show: Boolean) {
        putBoolean(R.string.PREF_FAVOURITES_FILTER, show)
    }

    fun getBuildCycleFilter(): BuildCycle {
        return try {
            BuildCycle.valueOf(
                preferences.getString(
                    context.getString(R.string.PREF_BUILD_CYCLE_FILTER),
                    BuildCycle.BUILD.toString()
                )!!
            )
        } catch (_: Exception) {
            BuildCycle.BUILD
        }
    }

    fun setBuildCycleFilter(buildCycle: BuildCycle) {
        putString(R.string.PREF_BUILD_CYCLE_FILTER, buildCycle.name)
    }

    fun getMetadataLinkType(): MetadataLinkType {
        return try {
            MetadataLinkType.valueOf(
                preferences.getString(
                    context.getString(R.string.PREF_METADATA_LINK_TYPE),
                    MetadataLinkType.ASK.toString()
                )!!
            )
        } catch (_: Exception) {
            MetadataLinkType.ASK
        }
    }

    fun setMetadataLinkType(metadataLinkType: MetadataLinkType) {
        putString(R.string.PREF_METADATA_LINK_TYPE, metadataLinkType.name)
    }

    fun getBuildlogType(): BuildlogType {
        return try {
            BuildlogType.valueOf(
                preferences.getString(
                    context.getString(R.string.PREF_BUILDLOG_TYPE),
                    BuildlogType.ASK.toString()
                )!!
            )
        } catch (_: Exception) {
            BuildlogType.ASK
        }
    }

    fun setBuildlogType(buildlogType: BuildlogType) {
        putString(R.string.PREF_BUILDLOG_TYPE, buildlogType.name)
    }

    fun getUpdateInterval(): Long {
        return try {
            preferences.getString(
                context.getString(R.string.PREF_UPDATE_INTERVAL),
                Time.FIVE_HOURS.toString()
            )!!
                .toLong()
        } catch (_: NumberFormatException) {
            Time.FIVE_HOURS
        }
    }

    /**
     * @return [androidx.appcompat.app.AppCompatDelegate].MODE_*
     */
    private fun getDefaultNightMode(): Int {
        val defaultValue = context.getString(R.string.night_mode_default)
        val value = preferences.getString(context.getString(R.string.night_mode_key), defaultValue)
        return value!!.toInt()
    }

    fun applyDefaultNightMode() {
        applyNightMode(getDefaultNightMode())
    }

    fun applyNightMode(nightMode: Int) {
        AppCompatDelegate.setDefaultNightMode(nightMode)
    }

    private fun putBoolean(key: Int, value: Boolean) {
        preferences.edit {
            putBoolean(context.getString(key), value)
        }
    }

    private fun putString(key: Int, value: String?) {
        preferences.edit {
            if (value == null) {
                remove(context.getString(key))
            } else {
                putString(context.getString(key), value.trim { it <= ' ' })
            }
        }
    }

    private fun putLong(@Suppress("SameParameterValue") key: Int, value: Long) {
        preferences.edit {
            putLong(context.getString(key), value)
        }
    }

    fun getLastUpdateLoaded(): Long {
        return preferences.getLong(context.getString(R.string.PREF_LAST_UPDATE_LOADED), 0L)
    }

    fun setLastUpdateLoadedNow() {
        putLong(R.string.PREF_LAST_UPDATE_LOADED, System.currentTimeMillis())
    }

    fun setRepoIndexLoaded() {
        putBoolean(R.string.PREF_REPO_INDEX_LOADED, true)
    }

    fun isRepoIndexLoaded(): Boolean {
        return preferences.getBoolean(context.getString(R.string.PREF_REPO_INDEX_LOADED), false)
    }

    fun getMaxLogLines(): Int {
        return preferences.getString(context.getString(R.string.PREF_MAX_LOG_LINES), "1000")!!
            .toInt()
    }

    fun getStatusFilter(): StatusFilter {
        return try {
            StatusFilter.valueOf(
                preferences.getString(
                    context.getString(R.string.PREF_STATUS_FILTER),
                    StatusFilter.NONE.toString()
                )!!
            )
        } catch (_: Exception) {
            StatusFilter.NONE
        }
    }

    fun setStatusFilter(statusFilter: StatusFilter) {
        putString(R.string.PREF_STATUS_FILTER, statusFilter.name)
    }
}