@file:Suppress("unused")

package com.zxhy.solarmasterace.dialog

import android.app.Dialog
import android.content.Context
import android.content.DialogInterface
import android.view.KeyEvent
import androidx.annotation.StringRes
import androidx.appcompat.app.AlertDialog
import androidx.fragment.app.Fragment
import com.google.android.material.dialog.MaterialAlertDialogBuilder

//typealias用于给类取别名 将AlertBuilderFactory<D>重新定义为一个匿名函数，返回它的父类
typealias AlertBuilderFactory<D> = (Context) -> AlertBuilder<D>

val Material: AlertBuilderFactory<DialogInterface> = { context ->
    object : AlertDialogBuilder() {
        override val builder: AlertDialog.Builder = MaterialAlertDialogBuilder(context)
    }
}

//默认的构造工厂
private var defaultAlertBuilderFactory: AlertBuilderFactory<*> = Material

//region  简易的消息弹窗

//基于上下文扩展的 简易的消息弹窗
fun Context.alert(
    message: CharSequence,
    title: CharSequence? = null,
    block: (AlertBuilder<*>.() -> Unit)? = null
) {
    alert(defaultAlertBuilderFactory, message, title, block)
}


//基于Fragment扩展的建议弹窗
fun Fragment.alert(
    message: CharSequence,
    title: CharSequence? = null,
    block: (AlertBuilder<*>.() -> Unit)? = null
) {
    requireContext().alert(message, title, block)
}


private inline fun <D : DialogInterface> Context.alert(
    factory: AlertBuilderFactory<D>,
    message: CharSequence,
    title: CharSequence?,
    noinline block: (AlertBuilder<D>.() -> Unit)? = null
) {
    alertDialog(factory) {
        title?.let { this.title = it }
        this.message = message
        block?.invoke(this)
    }.show()
}


//endregion

//region 单项选择弹窗
fun Context.selector(
    items: List<CharSequence>,
    title: CharSequence?,
    onItemSelected: (dialog: DialogInterface, index: Int) -> Unit
) {
    alertDialog(defaultAlertBuilderFactory) {
        title?.let { this.title = it }
        items(items, onItemSelected)
    }.show()
}

fun Fragment.selector(
    items: List<CharSequence>,
    title: CharSequence?,
    onItemSelected: (dialog: DialogInterface, index: Int) -> Unit
) {
    requireContext().selector(items, title, onItemSelected)
}


private inline fun <D : DialogInterface> Context.selector(
    factory: AlertBuilderFactory<D>,
    items: List<CharSequence>,
    title: CharSequence?,
    noinline onItemSelected: (dialog: DialogInterface, index: Int) -> Unit
) {
    alertDialog(factory) {
        title?.let { this.title = it }
        items(items, onItemSelected)
    }.show()
}

//endregion

//region 单项选择
fun Context.singleChoice(
    items: List<CharSequence>,
    title: CharSequence? = null,
    defaultItem: Int = -1, //默认没有选中项目
    onItemSelected: (DialogInterface, Int) -> Unit
) {
    singleChoice(defaultAlertBuilderFactory, items, title, defaultItem, onItemSelected)
}

fun Fragment.singleChoice(
    items: List<CharSequence>,
    title: CharSequence? = null,
    defaultItem: Int = -1,//默认没有选中项目
    onItemSelected: (DialogInterface, Int) -> Unit
) {
    requireContext().singleChoice(items, title, defaultItem, onItemSelected)
}

private fun Context.singleChoice(
    factory: AlertBuilderFactory<DialogInterface>,
    items: List<CharSequence>,
    title: CharSequence?,
    defaultItem: Int = -1,//默认没有选中项目
    onItemSelected: (DialogInterface, Int) -> Unit
) {
    alertDialog(factory) {
        title?.let { this.title = title }
        choiceItems(items, defaultItem, onItemSelected)
    }.show()
}


//endregion

//region 多项选择
fun Context.multiChoice(
    items: List<CharSequence>,
    defaultItems: BooleanArray, //必须设备每一个项目的选中情况
    title: CharSequence? = null,
    block: (AlertBuilder<DialogInterface>.() -> Unit)? = null, //用于添加按钮
    onItemSelected: (dialog: DialogInterface, index: Int, isChecked: Boolean) -> Unit
) {
    multiChoice(defaultAlertBuilderFactory, items, defaultItems, title, block, onItemSelected)
}

fun Fragment.multiChoice(
    items: List<CharSequence>,
    defaultItems: BooleanArray,  //必须设备每一个项目的选中情况
    title: CharSequence? = null,
    block: (AlertBuilder<DialogInterface>.() -> Unit)? = null, //用于添加按钮
    onItemSelected: (dialog: DialogInterface, index: Int, isChecked: Boolean) -> Unit
) {
    requireContext().multiChoice(items, defaultItems, title, block, onItemSelected)
}

private inline fun <D : DialogInterface> Context.multiChoice(
    factory: AlertBuilderFactory<D>,
    items: List<CharSequence>,  //必须设备每一个项目的选中情况
    defaultItems: BooleanArray,
    title: CharSequence?,
    noinline block: (AlertBuilder<D>.() -> Unit)? = null, //用于添加按钮
    noinline onItemSelected: (dialog: DialogInterface, index: Int, isChecked: Boolean) -> Unit
) {
    alertDialog(factory) {
        title?.let { this.title = it }
        multiChoiceItems(items, defaultItems) { dialog, index, isChecked ->
            onItemSelected(dialog, index, isChecked)
        }
        //提供外部处理
        block?.invoke(this)
    }.show()
}
//endregion

//region 事件响应
//监听取消
fun DialogInterface.doOnCancel(block: (DialogInterface) -> Unit) {
    check(this is Dialog)
    setOnCancelListener(block)
}

fun Dialog.doOnCancel(block: (DialogInterface) -> Unit) {
    setOnCancelListener(block)
}

//监听展示
fun DialogInterface.doOnShow(block: (DialogInterface) -> Unit) {
    check(this is Dialog)
    setOnShowListener(block)
}

fun Dialog.doOnShow(block: (DialogInterface) -> Unit) {
    setOnShowListener(block)
}

//监听驳回dismiss
fun DialogInterface.doOnDismiss(block: (DialogInterface) -> Unit) {
    check(this is Dialog)
    setOnDismissListener(block)
}

fun Dialog.doOnDismiss(block: (DialogInterface) -> Unit) {
    setOnDismissListener(block)
}


//监听返回按钮 一般用于返回键的拦截KeyEvent.KEYCODE_BACK
fun DialogInterface.doOnKeyPressed(handler: (DialogInterface, keyCode: Int, e: KeyEvent) -> Boolean) {
    check(this is Dialog)
    setOnKeyListener(handler)
}

fun Dialog.keyListener(handler: (DialogInterface, keyCode: Int, e: KeyEvent) -> Boolean) {
    setOnKeyListener(handler)
}

//endregion

//region 添加按钮
//确认按钮
fun AlertBuilder<*>.okButton(onClicked: (dialog: DialogInterface) -> Unit) =
    positiveButton(android.R.string.ok, onClicked)

//取消按钮
fun AlertBuilder<*>.cancelButton(onClicked: (dialog: DialogInterface) -> Unit = { it.dismiss() }) =
    negativeButton(android.R.string.cancel, onClicked)

//中性按钮
fun AlertBuilder<*>.neutralButton(
    buttonText: String,
    onClicked: (dialog: DialogInterface) -> Unit = { it.dismiss() }
) = neutralPressed(buttonText, onClicked)
//endregion


//统一的弹窗处理
inline fun <D : DialogInterface> Context.alertDialog(
    factory: AlertBuilderFactory<D>,
    block: AlertBuilder<D>.() -> Unit
) = factory(this).apply(block)


//统一的接口，用于管理属性
interface AlertBuilder<out D : DialogInterface> {
    //上下文
    val context: Context

    //标题
    var title: CharSequence

    //标题
    var message: CharSequence

    //确认按钮
    fun positiveButton(buttonText: String, onClicked: (dialog: DialogInterface) -> Unit)
    fun positiveButton(
        @StringRes buttonTextResource: Int,
        onClicked: (dialog: DialogInterface) -> Unit
    )

    //取消按钮
    fun negativeButton(buttonText: String, onClicked: (dialog: DialogInterface) -> Unit)
    fun negativeButton(
        @StringRes buttonTextResource: Int,
        onClicked: (dialog: DialogInterface) -> Unit
    )

    //中性按压事件
    fun neutralPressed(buttonText: String, onClicked: (dialog: DialogInterface) -> Unit)
    fun neutralPressed(
        @StringRes buttonTextResource: Int,
        onClicked: (dialog: DialogInterface) -> Unit
    )


    //选择列表
    fun items(
        items: List<CharSequence>,
        onItemSelected: (dialog: DialogInterface, index: Int) -> Unit
    )

    //单项确认
    fun choiceItems(
        items: List<CharSequence>,
        checkedIndex: Int,
        onItemSelected: (DialogInterface, Int) -> Unit
    )

    //多项确认
    fun multiChoiceItems(
        items: List<CharSequence>,
        checkedItems: BooleanArray,
        onItemSelected: (DialogInterface, Int, Boolean) -> Unit
    )

    //驳回
    fun onDismissed(handler: (DialogInterface) -> Unit)

    //取消
    fun onCancelled(handler: (DialogInterface) -> Unit)

    //按键处理 常用于返回键的拦截
    fun onKeyPressed(handler: (DialogInterface, keyCode: Int, e: KeyEvent) -> Boolean)


    //是否可以取消
    fun isCancel(cancel: Boolean)


    //创建
    fun build(): D

    //展示
    fun show(): D


}

//Alert的构造器
abstract class AlertDialogBuilder : AlertBuilder<AlertDialog> {
    //提供用于创建实例
    abstract val builder: AlertDialog.Builder

    //上下文
    override val context: Context get() = builder.context

    //标题
    override var title: CharSequence
        get() = throw NotImplementedError("Property does not have a getter")
        set(value) {
            builder.setTitle(value)
        }

    //消息
    override var message: CharSequence
        get() = throw NotImplementedError("Property does not have a getter")
        set(value) {
            builder.setMessage(value)
        }

    //消极的按钮
    override fun negativeButton(buttonText: String, onClicked: (DialogInterface) -> Unit) {
        builder.setNegativeButton(buttonText) { dialog, _ ->
            onClicked(dialog)
        }
    }

    //消极按钮
    override fun negativeButton(buttonTextResource: Int, onClicked: (DialogInterface) -> Unit) {
        builder.setNegativeButton(buttonTextResource) { dialog, _ ->
            onClicked(dialog)
        }
    }

    //中性按钮
    override fun neutralPressed(buttonText: String, onClicked: (DialogInterface) -> Unit) {
        builder.setNeutralButton(buttonText) { dialog, _ ->
            onClicked(dialog)
        }
    }

    //中性按钮
    override fun neutralPressed(buttonTextResource: Int, onClicked: (DialogInterface) -> Unit) {
        builder.setNeutralButton(buttonTextResource) { dialog, _ ->
            onClicked(dialog)
        }
    }

    //积极按钮
    override fun positiveButton(buttonText: String, onClicked: (DialogInterface) -> Unit) {
        builder.setPositiveButton(buttonText) { dialog, _ ->
            onClicked(dialog)
        }
    }

    override fun positiveButton(buttonTextResource: Int, onClicked: (DialogInterface) -> Unit) {
        builder.setPositiveButton(buttonTextResource) { dialog, _ ->
            onClicked(dialog)
        }
    }

    override fun items(
        items: List<CharSequence>,
        onItemSelected: (dialog: DialogInterface, index: Int) -> Unit
    ) {
        builder.setItems(items.toTypedArray(), onItemSelected)
    }

    override fun choiceItems(
        items: List<CharSequence>,
        checkedIndex: Int,
        onItemSelected: (DialogInterface, Int) -> Unit
    ) {
        builder.setSingleChoiceItems(items.toTypedArray(), checkedIndex, onItemSelected)
    }


    override fun multiChoiceItems(
        items: List<CharSequence>,
        checkedItems: BooleanArray,
        onItemSelected: (DialogInterface, Int, Boolean) -> Unit
    ) {
        builder.setMultiChoiceItems(items.toTypedArray(), checkedItems, onItemSelected)
    }

    override fun onDismissed(handler: (DialogInterface) -> Unit) {
        builder.setOnDismissListener(handler)
    }

    override fun onCancelled(handler: (DialogInterface) -> Unit) {
        builder.setOnCancelListener(handler)
    }

    override fun onKeyPressed(handler: (DialogInterface, keyCode: Int, e: KeyEvent) -> Boolean) {
        builder.setOnKeyListener(handler)
    }


    override fun isCancel(cancel: Boolean) {
        builder.setCancelable(false)
    }


    //构建
    override fun build(): AlertDialog {
        return builder.create()
    }

    //展示
    override fun show(): AlertDialog {
        return builder.show()
    }


}