package xyz.apiote.bimba.czwek.settings

import android.content.Context
import android.content.Intent
import android.content.SharedPreferences
import android.net.ConnectivityManager
import android.os.Bundle
import android.util.Log
import androidx.activity.result.contract.ActivityResultContracts
import androidx.appcompat.app.AppCompatActivity
import androidx.appcompat.content.res.AppCompatResources
import androidx.core.content.edit
import androidx.core.widget.addTextChangedListener
import com.google.android.material.dialog.MaterialAlertDialogBuilder
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.MainScope
import kotlinx.coroutines.launch
import kotlinx.coroutines.withContext
import org.yaml.snakeyaml.error.YAMLException
import xyz.apiote.bimba.czwek.R
import xyz.apiote.bimba.czwek.api.Bimba
import xyz.apiote.bimba.czwek.api.Server
import xyz.apiote.bimba.czwek.api.TrafficFormatException
import xyz.apiote.bimba.czwek.api.getBimba
import xyz.apiote.bimba.czwek.databinding.ActivityServerChooserBinding
import xyz.apiote.bimba.czwek.settings.feeds.FeedChooserActivity

class ServerChooserActivity : AppCompatActivity() {
	private var _binding: ActivityServerChooserBinding? = null
	private val binding get() = _binding!!

	private val activityLauncher =
		registerForActivityResult(ActivityResultContracts.StartActivityForResult()) {
			if (!preferences.getBoolean("inFeedsTransaction", true)) {
				finish()
			}
		}

	private lateinit var preferences: SharedPreferences

	override fun onCreate(savedInstanceState: Bundle?) {
		super.onCreate(savedInstanceState)
		preferences = getSharedPreferences("shp", MODE_PRIVATE)

		if (intent.getBooleanExtra("simple", false)) {
			setServer("bimba.apiote.xyz", "")
			checkServer(true)
		} else {

			_binding = ActivityServerChooserBinding.inflate(layoutInflater)
			setContentView(binding.root)

			preferences.edit(true) {
				putBoolean("inFeedsTransaction", true)
			}

			binding.button.isEnabled = false
			binding.serverField.editText!!.addTextChangedListener { editable ->
				binding.button.isEnabled = !editable.isNullOrBlank()
			}

			if (!preferences.getBoolean("firstRun", true)) {
				Server.get(this).let { server ->
					binding.serverField.editText!!.setText(server.host)
					binding.tokenField.editText!!.setText(server.token)
				}
			}

			binding.button.setOnClickListener {
				setServer(
					binding.serverField.editText!!.text.toString(),
					binding.tokenField.editText!!.text.toString()
				)
				checkServer(false)
			}
		}
	}

	private fun showDialog(
		title: Int, description: Int, icon: Int, onPositive: (() -> Unit)?
	) {
		MaterialAlertDialogBuilder(this).setIcon(AppCompatResources.getDrawable(this, icon))
			.setTitle(getString(title)).setMessage(getString(description))
			.setNegativeButton(resources.getString(R.string.cancel)) { _, _ -> }.apply {
				if (onPositive != null) {
					setPositiveButton(resources.getString(R.string.cont)) { _, _ ->
						onPositive()
					}
				}
			}.show()
	}

	private fun checkServer(isSimple: Boolean) {
		val cm = getSystemService(Context.CONNECTIVITY_SERVICE) as ConnectivityManager
		MainScope().launch {
			val result = getBimba(cm, Server.get(this@ServerChooserActivity))
			if (result.error != null) {
				showDialog(R.string.error, result.error.stringResource, result.error.imageResource, null)
				Log.w(
					"ServerChooser", "${result.error.statusCode}, ${getString(result.error.stringResource)}"
				)
				return@launch
			}
			val bimba = try {
				withContext(Dispatchers.IO) {
					Bimba.unmarshal(result.stream!!)
				}
			} catch (e: YAMLException) {
				Log.w("ServerChooser", e.message ?: "YAML error")
				showDialog(R.string.error, R.string.error_traffic_spec, R.drawable.error_server, null)
				return@launch
			} catch (e: TrafficFormatException) {
				Log.w("ServerChooser", e.message)
				showDialog(R.string.error, R.string.error_traffic_spec, R.drawable.error_server, null)
				return@launch
			}
			val token = preferences.getString("token", "")
			updateServer(bimba.servers[0]["url"]!!)

			if (bimba.isPrivate() && token == "") {
				showDialog(R.string.error, R.string.server_private_question, R.drawable.error_sec, null)
				return@launch
			}
			if (bimba.isRateLimited() && token == "" && !isSimple) {
				showDialog(
					R.string.rate_limit, R.string.server_rate_limited_question, R.drawable.error_limit
				) {
					runFeedsActivity()
				}
				return@launch
			}
			runFeedsActivity()
		}
	}

	private fun setServer(hostname: String, token: String) {
		preferences.edit(true) {
			putString("host", hostname)
			putString("token", token)
		}
	}

	private fun updateServer(apiPath: String) {
		preferences.edit(true) {
			putString("apiPath", apiPath)
		}
	}

	private fun runFeedsActivity() {
		activityLauncher.launch(Intent(this, FeedChooserActivity::class.java))
		if (intent.getBooleanExtra("simple", false)) {
			finish()
		}
	}
}