package ch.threema.app.preference

import android.content.Context
import android.util.AttributeSet
import androidx.preference.CheckBoxPreference
import ch.threema.app.managers.ServiceManager
import ch.threema.app.preference.service.SynchronizedBooleanSetting
import ch.threema.base.utils.getThreemaLogger
import kotlinx.coroutines.CoroutineScope
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.Job
import kotlinx.coroutines.launch

private val logger = getThreemaLogger("SynchronizedCheckBoxPreference")

class SynchronizedCheckBoxPreference : CheckBoxPreference {
    @Suppress("unused")
    constructor(context: Context, attrs: AttributeSet?, defStyleAttr: Int, defStyleRes: Int) : super(context, attrs, defStyleAttr, defStyleRes)

    @Suppress("unused")
    constructor(context: Context, attrs: AttributeSet?, defStyleAttr: Int) : super(context, attrs, defStyleAttr)

    @Suppress("unused")
    constructor(context: Context, attrs: AttributeSet?) : super(context, attrs)

    private val synchronizedSetting: SynchronizedBooleanSetting?

    private var stateCollector: Job? = null

    init {
        val serviceManager = ServiceManager.get()
        if (serviceManager != null) {
            synchronizedSetting = serviceManager.synchronizedSettingsService.getSynchronizedBooleanSettingByKey(key)

            if (synchronizedSetting == null) {
                logger.error("Could not get synchronized setting with key '$key'")
                disablePreference()
            }
        } else {
            logger.error("Cannot get synchronized setting with key '$key' as the service manager is null")
            synchronizedSetting = null
        }
    }

    override fun onClick() {
        if (synchronizedSetting == null) {
            logger.error("Cannot click on preference with key {} because its setting is null", key)
            return
        }
        super.onClick()
    }

    override fun onAttached() {
        super.onAttached()

        if (synchronizedSetting == null) {
            return
        }

        stateCollector = CoroutineScope(Dispatchers.Main).launch {
            synchronizedSetting.asStateFlow().collect { value ->
                mChecked = value
                notifyDependencyChange(shouldDisableDependents())
                notifyChanged()
            }
        }
    }

    override fun onDetached() {
        super.onDetached()

        stateCollector?.cancel()
    }

    override fun persistBoolean(value: Boolean): Boolean {
        return if (synchronizedSetting != null) {
            logger.debug("Setting value {}", value)

            // Only set the value again if it is different to prevent unnecessary reflection
            if (synchronizedSetting.get() != value) {
                synchronizedSetting.setFromLocal(value)
            }
            true
        } else {
            logger.error("Cannot persist preference with key '$key' as the synchronized setting is unavailable")
            false
        }
    }

    override fun setEnabled(enabled: Boolean) {
        if (enabled && synchronizedSetting == null) {
            // We cannot enable this preference if the synchronized setting is null
            return
        }

        super.setEnabled(enabled)
    }

    private fun disablePreference() {
        isEnabled = false
    }
}
