package jp.juggler.subwaytooter.dialog

import android.annotation.SuppressLint
import android.app.Activity
import android.text.method.LinkMovementMethod
import android.text.util.Linkify
import android.view.View
import androidx.annotation.StringRes
import androidx.appcompat.app.AlertDialog
import jp.juggler.subwaytooter.R
import jp.juggler.subwaytooter.databinding.DlgConfirmBinding
import jp.juggler.util.ui.dismissSafe
import kotlinx.coroutines.CancellationException
import kotlinx.coroutines.suspendCancellableCoroutine
import kotlin.coroutines.resume
import kotlin.coroutines.resumeWithException

object DlgConfirm {
    @SuppressLint("InflateParams")
    suspend inline fun Activity.confirm(
        message: String,
        isConfirmEnabled: Boolean,
        setConfirmEnabled: (newConfirmEnabled: Boolean) -> Unit,
    ) {
        if (!isConfirmEnabled) return
        val skipNext = suspendCancellableCoroutine { cont ->
            try {
                val views = DlgConfirmBinding.inflate(layoutInflater)
                views.tvMessage.text = message
                val dialog = AlertDialog.Builder(this)
                    .setView(views.root)
                    .setCancelable(true)
                    .setNegativeButton(R.string.cancel, null)
                    .setPositiveButton(R.string.ok) { _, _ ->
                        if (cont.isActive) cont.resume(views.cbSkipNext.isChecked)
                    }
                dialog.setOnDismissListener {
                    if (cont.isActive) cont.resumeWithException(CancellationException("dialog cancelled."))
                }
                dialog.show()
            } catch (ex: Throwable) {
                cont.resumeWithException(ex)
            }
        }
        if (skipNext) setConfirmEnabled(false)
    }

    suspend fun Activity.confirm(@StringRes messageId: Int, vararg args: Any?) =
        confirm(getString(messageId, *args))

    suspend fun Activity.confirm(message: CharSequence, title: CharSequence? = null) {
        suspendCancellableCoroutine { cont ->
            try {
                val views = DlgConfirmBinding.inflate(layoutInflater)
                views.tvMessage.text = message
                views.cbSkipNext.visibility = View.GONE

                val dialog = AlertDialog.Builder(this).apply {
                    setView(views.root)
                    setCancelable(true)
                    title?.let { setTitle(it) }
                    setNegativeButton(R.string.cancel, null)
                    setPositiveButton(R.string.ok) { _, _ ->
                        if (cont.isActive) cont.resume(Unit)
                    }
                }.create()
                dialog.setOnDismissListener {
                    if (cont.isActive) cont.resumeWithException(CancellationException("dialog closed."))
                }
                dialog.show()
                cont.invokeOnCancellation { dialog.dismissSafe() }
            } catch (ex: Throwable) {
                cont.resumeWithException(ex)
            }
        }
    }

    suspend fun Activity.okDialog(@StringRes messageId: Int, vararg args: Any?) =
        okDialog(getString(messageId, *args))

    suspend fun Activity.okDialog(message: CharSequence, title: CharSequence? = null) {
        suspendCancellableCoroutine { cont ->
            try {
                val views = DlgConfirmBinding.inflate(layoutInflater)

                views.cbSkipNext.visibility = View.GONE

                views.tvMessage.apply {
                    movementMethod = LinkMovementMethod.getInstance()
                    autoLinkMask = Linkify.WEB_URLS
                    text = message
                }

                val dialog = AlertDialog.Builder(this).apply {
                    setView(views.root)
                    setCancelable(true)
                    title?.let { setTitle(it) }
                    setPositiveButton(R.string.ok) { _, _ ->
                        if (cont.isActive) cont.resume(Unit)
                    }
                }.create()
                dialog.setOnDismissListener {
                    if (cont.isActive) cont.resumeWithException(CancellationException("dialog closed."))
                }
                dialog.show()
                cont.invokeOnCancellation { dialog.dismissSafe() }
            } catch (ex: Throwable) {
                cont.resumeWithException(ex)
            }
        }
    }
}
