package bou.amine.apps.readerforselfossv2.android.settings

import android.content.Intent
import android.net.Uri
import android.os.Bundle
import android.text.Editable
import android.text.InputFilter
import android.text.InputType
import android.text.TextWatcher
import android.widget.Toast
import androidx.appcompat.app.AppCompatActivity
import androidx.appcompat.app.AppCompatDelegate
import androidx.core.widget.addTextChangedListener
import androidx.preference.EditTextPreference
import androidx.preference.Preference
import androidx.preference.PreferenceFragmentCompat
import bou.amine.apps.readerforselfossv2.android.R
import bou.amine.apps.readerforselfossv2.android.databinding.ActivitySettingsBinding
import bou.amine.apps.readerforselfossv2.android.sendSilentlyWithAcraWithName
import bou.amine.apps.readerforselfossv2.service.AppSettingsService
import com.mikepenz.aboutlibraries.LibsBuilder
import org.kodein.di.DIAware
import org.kodein.di.android.closestDI
import org.kodein.di.instance

private const val TITLE_TAG = "settingsActivityTitle"

class SettingsActivity : AppCompatActivity(),
        PreferenceFragmentCompat.OnPreferenceStartFragmentCallback, DIAware {
    override val di by closestDI()

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        val binding = ActivitySettingsBinding.inflate(layoutInflater)

        setContentView(binding.root)
        if (savedInstanceState == null) {
            supportFragmentManager
                    .beginTransaction()
                    .replace(R.id.settings, MainPreferenceFragment())
                    .commit()
        } else {
            title = savedInstanceState.getCharSequence(TITLE_TAG)
        }
        supportFragmentManager.addOnBackStackChangedListener {
            if (supportFragmentManager.backStackEntryCount == 0) {
                setTitle(R.string.title_activity_settings)
            }
        }

        setSupportActionBar(binding.toolbar)

        supportActionBar?.setDisplayHomeAsUpEnabled(true)
        supportActionBar?.setDisplayShowHomeEnabled(true)
        supportActionBar?.title = title
    }

    override fun onSaveInstanceState(outState: Bundle) {
        super.onSaveInstanceState(outState)
        // Save current activity title so we can set it again after a configuration change
        outState.putCharSequence(TITLE_TAG, title)
    }

    override fun onSupportNavigateUp(): Boolean {
        return if (supportFragmentManager.popBackStackImmediate()) {
            supportActionBar?.title = getText(R.string.title_activity_settings)
            false
        } else {
            super.onBackPressed()
            true
        }
    }

    override fun onPreferenceStartFragment(
            caller: PreferenceFragmentCompat,
            pref: Preference
    ): Boolean {
        // Instantiate the new Fragment
        val args = pref.extras
        val fragment = supportFragmentManager.fragmentFactory.instantiate(
                classLoader,
                pref.fragment
        ).apply {
            arguments = args
            setTargetFragment(caller, 0)
        }
        // Replace the existing Fragment with the new Fragment
        supportFragmentManager.beginTransaction()
                .replace(R.id.settings, fragment)
                .addToBackStack(null)
                .commit()
        title = pref.title
        supportActionBar?.title = title
        return true
    }

    class MainPreferenceFragment : PreferenceFragmentCompat() {
        override fun onCreatePreferences(savedInstanceState: Bundle?, rootKey: String?) {
            setPreferencesFromResource(R.xml.pref_main, rootKey)

            preferenceManager.findPreference<Preference>("currentMode")?.onPreferenceChangeListener = Preference.OnPreferenceChangeListener { _, newValue ->
                AppCompatDelegate.setDefaultNightMode(newValue.toString().toInt()) // ListPreference Only takes string-arrays ¯\_(ツ)_/¯
                true
            }

            preferenceManager.findPreference<Preference>("action_about")?.onPreferenceClickListener = Preference.OnPreferenceClickListener { _ ->
                context?.let {
                    LibsBuilder()
                        .withAboutIconShown(true)
                        .withAboutVersionShown(true)
                        .start(it)
                }
                true
            }
        }
    }

    class GeneralPreferenceFragment : PreferenceFragmentCompat() {
        override fun onCreatePreferences(savedInstanceState: Bundle?, rootKey: String?) {
            setPreferencesFromResource(R.xml.pref_general, rootKey)

            val editTextPreference = preferenceManager.findPreference<EditTextPreference>("prefer_api_items_number")
            editTextPreference?.setOnBindEditTextListener { editText ->
                editText.inputType = InputType.TYPE_CLASS_NUMBER
                editText.filters = arrayOf(
                        InputFilter { source, _, _, dest, _, _ ->
                            try {
                                val input: Int = (dest.toString() + source.toString()).toInt()
                                if (input in 1..200) return@InputFilter null
                            } catch (nfe: NumberFormatException) {
                                nfe.sendSilentlyWithAcraWithName("GeneralPreferenceFragment")
                                Toast.makeText(activity, R.string.items_number_should_be_number, Toast.LENGTH_LONG).show()
                            }
                            ""
                        }
                )
            }
        }
    }

    class ArticleViewerPreferenceFragment : PreferenceFragmentCompat() {
        override fun onCreatePreferences(savedInstanceState: Bundle?, rootKey: String?) {
            setPreferencesFromResource(R.xml.pref_viewer, rootKey)

            val fontSize = preferenceManager.findPreference<EditTextPreference>("reader_font_size")
            fontSize?.setOnBindEditTextListener { editText ->
                editText.inputType = InputType.TYPE_CLASS_NUMBER
                editText.addTextChangedListener { object : TextWatcher {
                    override fun beforeTextChanged(charSequence: CharSequence, i: Int, i1: Int, i2: Int) {}
                    override fun onTextChanged(charSequence: CharSequence, i: Int, i1: Int, i2: Int) {}
                    override fun afterTextChanged(editable: Editable) {
                        try {
                            editText.textSize = editable.toString().toInt().toFloat()
                        } catch (e: NumberFormatException) {
                            e.sendSilentlyWithAcraWithName("ArticleViewerPreferenceFragment > afterTextChanged")
                        }
                    }
                } }
                editText.filters = arrayOf(
                        InputFilter { source, _, _, dest, _, _ ->
                            try {
                                val input = (dest.toString() + source.toString()).toInt()
                                if (input > 0) return@InputFilter null
                            } catch (nfe: NumberFormatException) {
                                nfe.sendSilentlyWithAcraWithName("ArticleViewerPreferenceFragment > filters")
                            }
                            ""
                        }
                )
            }
        }
    }

    class OfflinePreferenceFragment : PreferenceFragmentCompat() {
        override fun onCreatePreferences(savedInstanceState: Bundle?, rootKey: String?) {
            setPreferencesFromResource(R.xml.pref_offline, rootKey)
        }
    }

    class ThemePreferenceFragment : PreferenceFragmentCompat() {
        override fun onCreatePreferences(savedInstanceState: Bundle?, rootKey: String?) {
            setPreferencesFromResource(R.xml.pref_theme, rootKey)

            preferenceManager.findPreference<Preference>("currentMode")?.onPreferenceChangeListener = Preference.OnPreferenceChangeListener { _, newValue ->
                AppCompatDelegate.setDefaultNightMode(newValue.toString().toInt()) // ListPreference Only takes string-arrays ¯\_(ツ)_/¯
                true
            }
        }
    }

    class LinksPreferenceFragment : PreferenceFragmentCompat() {
        private fun openUrl(uri: Uri?) {
            val browserIntent = Intent(Intent.ACTION_VIEW, uri)
            startActivity(browserIntent)
        }

        override fun onCreatePreferences(savedInstanceState: Bundle?, rootKey: String?) {
            setPreferencesFromResource(R.xml.pref_links, rootKey)

            preferenceManager.findPreference<Preference>("trackerLink")?.onPreferenceClickListener = Preference.OnPreferenceClickListener {
                openUrl(Uri.parse(AppSettingsService.trackerUrl))
                true
            }

            preferenceManager.findPreference<Preference>("sourceLink")?.onPreferenceClickListener = Preference.OnPreferenceClickListener {
                openUrl(Uri.parse(AppSettingsService.sourceUrl))
                false
            }

            preferenceManager.findPreference<Preference>("translation")?.onPreferenceClickListener = Preference.OnPreferenceClickListener {
                openUrl(Uri.parse(AppSettingsService.translationUrl))
                false
            }
        }
    }

    class ExperimentalPreferenceFragment : PreferenceFragmentCompat() {
        override fun onCreatePreferences(savedInstanceState: Bundle?, rootKey: String?) {
            setPreferencesFromResource(R.xml.pref_experimental, rootKey)
        }
    }
}