package com.adealink.weparty.commonui.widget

import android.annotation.SuppressLint
import android.content.DialogInterface
import android.graphics.Color
import android.graphics.Typeface
import android.graphics.drawable.ColorDrawable
import android.net.Uri
import android.os.Bundle
import android.os.CountDownTimer
import android.text.method.LinkMovementMethod
import android.util.Log
import android.view.Gravity
import android.view.View
import android.view.WindowManager
import android.widget.TextView
import androidx.annotation.ColorRes
import androidx.core.view.isVisible
import androidx.fragment.app.FragmentManager
import com.adealink.frame.aab.util.getCompatString
import com.adealink.frame.mvvm.view.viewBinding
import com.adealink.frame.util.DisplayUtil
import com.adealink.weparty.R
import com.adealink.weparty.commonui.dialogfragment.BaseDialogFragment
import com.adealink.weparty.commonui.ext.gone
import com.adealink.weparty.commonui.ext.show
import com.adealink.weparty.databinding.LayoutCommonDialogBinding
import com.facebook.common.util.UriUtil

open class CommonDialog : BaseDialogFragment(R.layout.layout_common_dialog) {

    /**
     * 点击返回键是否可取消
     */
    private var mCancelable: Boolean = false

    /**
     * 点击外部是否可取消
     */
    private var mCanceledOnTouchOutside: Boolean = false

    /**
     * 点击确定
     */
    var onPositive: (() -> Unit)? = null

    /**
     * 点击取消
     */
    var onNegative: (() -> Unit)? = null

    /**
     * 弹窗收起
     */
    var onDismiss: (() -> Unit)? = null

    /**
     * 弹窗默认的取消事件
     */
    var onCancelListener: DialogInterface.OnCancelListener? = null

    /**
     * 顶部图片
     */
    private var headerIconUri: Uri? = null

    /**
     * 标题颜色
     */
    private var titleColor: Int = 0

    var customMessageView: View? = null

    private val binding by viewBinding(LayoutCommonDialogBinding::bind)

    private var isDismissAfterClick = true

    override val cancelable: Boolean
        get() = mCancelable
    override var canceledOnTouchOutside: Boolean
        get() = mCanceledOnTouchOutside
        set(value) {
            mCanceledOnTouchOutside = value
            dialog?.setCanceledOnTouchOutside(value)
        }
    private var positiveCountDownTimer: CountDownTimer? = null
    private var countDownTimerFormat: ((Long) -> String)? = null //倒计时格式化函数
    private var countDownFinishCallback: (() -> Unit)? = null //倒计时结束回调

    override fun onStart() {
        super.onStart()
        val window = dialog?.window
        window?.setLayout(
            (DisplayUtil.getScreenWidth() * 0.8).toInt(),
            WindowManager.LayoutParams.WRAP_CONTENT
        )
        window?.setBackgroundDrawable(ColorDrawable(Color.TRANSPARENT))
        dialog?.setCancelable(mCancelable)
        dialog?.setCanceledOnTouchOutside(mCanceledOnTouchOutside)
        dialog?.setOnCancelListener(onCancelListener)
    }

    override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
        super.onViewCreated(view, savedInstanceState)
        initEvent()
    }

    override fun onDismiss(dialog: DialogInterface) {
        super.onDismiss(dialog)
        onDismiss?.invoke()
    }

    override fun initViews() {
        //header
        initHeader()
        //title + message
        initTitleMessageView()

        isDismissAfterClick = arguments?.getBoolean(KEY_IS_DISMISS_AFTER_CLICK, true) ?: true
        //确认按钮
        val confirmText = arguments?.getCharSequence(KEY_POSITIVE_TEXT)
        val showDefaultConfirm = arguments?.getBoolean(KEY_SHOW_DEFAULT_CONFIRM)
        if (confirmText.isNullOrEmpty()) {
            if (showDefaultConfirm == false) {
                binding.tvConfirm.visibility = View.GONE
            }
        } else {
            binding.tvConfirm.text = confirmText
        }
        val positiveCountDownMS = arguments?.getLong(KEY_POSITIVE_COUNTDOWN_MS) ?: 0
        val isClickableWhenCountDown = arguments?.getBoolean(KEY_IS_CLICKABLE_WHEN_COUNTDOWN, false) ?: false
        if (binding.tvConfirm.isVisible && positiveCountDownMS > 0L) {
            binding.tvConfirm.isEnabled = isClickableWhenCountDown
            positiveCountDownTimer?.cancel()
            positiveCountDownTimer = object : CountDownTimer(positiveCountDownMS, 1000L) {
                @SuppressLint("SetTextI18n")
                override fun onTick(millisUntilFinished: Long) {
                    binding.tvConfirm.text = "${millisUntilFinished / 1000}s"
                    countDownTimerFormat?.let {
                        binding.tvConfirm.text = it.invoke(millisUntilFinished)
                    }
                }

                override fun onFinish() {
                    binding.tvConfirm.isEnabled = true
                    binding.tvConfirm.text = when(confirmText.isNullOrEmpty()) {
                        true -> getCompatString(R.string.commonui_confirm)
                        else -> confirmText
                    }
                    countDownFinishCallback?.invoke()
                }

            }
            positiveCountDownTimer?.start()
        }
        //取消按钮
        val cancelText = arguments?.getCharSequence(KEY_NEGATIVE_TEXT)
        val showDefaultCancel = arguments?.getBoolean(KEY_SHOW_DEFAULT_CANCEL)
        if (cancelText.isNullOrEmpty()) {
            if (showDefaultCancel == true) {
                binding.tvCancel.visibility = View.VISIBLE
            }
        } else {
            binding.tvCancel.text = cancelText
            binding.tvCancel.visibility = View.VISIBLE
        }
    }

    private fun initHeader() {
        //头图
        headerIconUri = arguments?.getParcelable(KEY_HEADER_ICON_URI)
        if (headerIconUri != null) {
            binding.headerIv.visibility = View.VISIBLE
            binding.headerIv.setImageURI(headerIconUri, true)
        }
        //顶部关闭按钮
        val showTopCloseBtn = arguments?.getBoolean(KEY_SHOW_TOP_CLOSE_BTN) ?: false
        if (showTopCloseBtn) {
            binding.topCloseBtn.show()
            binding.topCloseBtn.setOnClickListener {
                dismissAllowingStateLoss()
            }
        } else {
            binding.topCloseBtn.gone()
        }
    }

    private fun initTitleMessageView() {
        // 顶部背景图
        val topBgRes = arguments?.getInt(KEY_TOP_BG_RES) ?: 0
        if (topBgRes != 0) {
            binding.ivTopBg.visibility = View.VISIBLE
            binding.ivTopBg.setImageResource(topBgRes)
        } else {
            binding.ivTopBg.visibility = View.GONE
        }

        //标题上面的图片
        val topImageUri: Uri? = arguments?.getParcelable(KEY_TOP_IMG_URI)
        val topImageWidth = arguments?.getInt(KEY_TOP_IMG_WIDTH) ?: 0
        val topImageHeight = arguments?.getInt(KEY_TOP_IMG_HEIGHT) ?: 0
        if (topImageUri != null) {
            binding.ivTop.visibility = View.VISIBLE
            val lp = binding.ivTop.layoutParams
            lp.width = topImageWidth
            lp.height = topImageHeight
            binding.ivTop.layoutParams = lp
            binding.ivTop.setImageURI(topImageUri, true)
        } else {
            binding.ivTop.visibility = View.GONE
        }

        val title = arguments?.getCharSequence(KEY_TITLE)
        val msg = arguments?.getCharSequence(KEY_MESSAGE)
        val msgGravity = arguments?.getInt(KEY_MESSAGE_GRAVITY)
        titleColor = arguments?.getInt(KEY_TITLE_COLOR) ?: 0
        //若标题为空，内容展示在标题的位置上
        if (title.isNullOrEmpty()) {
            binding.tvMessage.visibility = View.GONE
            initMessageView(binding.tvTitle, msg, msgGravity)
        } else {
            binding.tvTitle.text = title
            initMessageView(binding.tvMessage, msg, msgGravity)
        }

        //自定义messageView
        if (customMessageView != null) {
            binding.flSubBlock.visibility = View.VISIBLE
            binding.flSubBlock.addView(customMessageView)
        }
    }

    private fun initEvent() {
        binding.tvConfirm.setOnClickListener {
            onPositive?.invoke()
            if (isDismissAfterClick) {
                dismissAllowingStateLoss()
            }
        }

        binding.tvCancel.setOnClickListener {
            onNegative?.invoke()
            if (isDismissAfterClick) {
                dismissAllowingStateLoss()
            }
        }
    }

    private fun initMessageView(messageView: TextView, message: CharSequence?, gravity: Int?) {
        if (message.isNullOrEmpty()) {
            messageView.visibility = View.GONE
            return
        }
        messageView.text = message
        messageView.visibility = View.VISIBLE
        gravity?.let { messageView.gravity = it }
        messageView.typeface = Typeface.DEFAULT
        messageView.linksClickable = true
        messageView.highlightColor = Color.TRANSPARENT
        messageView.movementMethod = LinkMovementMethod.getInstance()
    }

    override fun show(manager: FragmentManager) {
        show(manager, TAG)
    }

    override fun onDestroyView() {
        super.onDestroyView()
        positiveCountDownTimer?.cancel()
    }

    override fun isShowing() = dialog?.isShowing ?: false

    private fun isDialogAlive() = isAdded && !isDetached && dialog != null

    companion object {
        private const val TAG = "CommonDialog"
        private const val KEY_TITLE = "title"
        private const val KEY_MESSAGE = "message"
        private const val KEY_POSITIVE_TEXT = "positive_text"
        private const val KEY_NEGATIVE_TEXT = "negative_text"
        private const val KEY_MESSAGE_GRAVITY = "message_gravity"
        private const val KEY_SHOW_DEFAULT_CANCEL = "show_default_cancel"
        private const val KEY_SHOW_DEFAULT_CONFIRM = "show_default_confirm"
        private const val KEY_IS_DISMISS_AFTER_CLICK = "is_dismiss_after_click"
        private const val KEY_HEADER_ICON_URI = "header_icon_uri"
        private const val KEY_TITLE_COLOR = "title_color"
        private const val KEY_TOP_BG_RES = "top_bg_res"
        private const val KEY_TOP_IMG_URI = "top_img_uri"
        private const val KEY_TOP_IMG_WIDTH = "top_img_width"
        private const val KEY_TOP_IMG_HEIGHT = "top_img_height"
        private const val KEY_SHOW_TOP_CLOSE_BTN = "key_show_top_close_btn"
        private const val KEY_POSITIVE_COUNTDOWN_MS = "positive_countdown_ms"
        private const val KEY_IS_CLICKABLE_WHEN_COUNTDOWN = "is_clickable_when_countdown" //倒计时期间能否点击按钮

        @JvmStatic
        fun newInstance(
            headerIconUri: Uri? = null,
            title: CharSequence? = null,
            message: CharSequence? = null,
            messageGravity: Int = Gravity.CENTER,

            positiveText: CharSequence?,
            onPositive: (() -> Unit)? = null,
            showDefaultConfirm: Boolean,

            negativeText: CharSequence?,
            onNegative: (() -> Unit)? = null,
            showDefaultCancel: Boolean,

            cancelable: Boolean,
            onDismiss: (() -> Unit)? = null,
            canceledOnTouchOutside: Boolean,
            onCancelListener: DialogInterface.OnCancelListener? = null,
            isDismissAfterClick: Boolean = true,
            titleColor: Int = 0,
            customMessageView: View? = null,
            topBgRes: Int = 0,
            topImageUri: Uri? = null,
            topImageWidth: Int,
            topImageHeight: Int,
            showTopCloseBtn: Boolean,
            positiveCountDownMS: Long = 0,
            isClickableWhenCountDown: Boolean = false,
            countDownTimerFormat: ((Long) -> String)? = null,
            countDownFinishCallback: (() -> Unit)? = null
        ): CommonDialog {

            val bundle = Bundle()
            bundle.putCharSequence(KEY_TITLE, title)
            bundle.putCharSequence(KEY_MESSAGE, message)
            bundle.putInt(KEY_MESSAGE_GRAVITY, messageGravity)
            bundle.putCharSequence(KEY_POSITIVE_TEXT, positiveText)
            bundle.putCharSequence(KEY_NEGATIVE_TEXT, negativeText)
            bundle.putBoolean(KEY_SHOW_DEFAULT_CONFIRM, showDefaultConfirm)
            bundle.putBoolean(KEY_SHOW_DEFAULT_CANCEL, showDefaultCancel)
            bundle.putBoolean(KEY_IS_DISMISS_AFTER_CLICK, isDismissAfterClick)
            bundle.putParcelable(KEY_HEADER_ICON_URI, headerIconUri)
            bundle.putInt(KEY_TITLE_COLOR, titleColor)
            bundle.putInt(KEY_TOP_BG_RES, topBgRes)
            bundle.putParcelable(KEY_TOP_IMG_URI, topImageUri)
            bundle.putInt(KEY_TOP_IMG_WIDTH, topImageWidth)
            bundle.putInt(KEY_TOP_IMG_HEIGHT, topImageHeight)
            bundle.putBoolean(KEY_SHOW_TOP_CLOSE_BTN, showTopCloseBtn)
            bundle.putLong(KEY_POSITIVE_COUNTDOWN_MS, positiveCountDownMS)
            bundle.putBoolean(KEY_IS_CLICKABLE_WHEN_COUNTDOWN, isClickableWhenCountDown)
            val dialog = CommonDialog()
            dialog.countDownTimerFormat = countDownTimerFormat
            dialog.countDownFinishCallback = countDownFinishCallback
            dialog.onNegative = onNegative
            dialog.onPositive = onPositive
            dialog.onDismiss = onDismiss
            dialog.onCancelListener = onCancelListener
            dialog.mCancelable = cancelable
            dialog.mCanceledOnTouchOutside = canceledOnTouchOutside
            dialog.customMessageView = customMessageView
            dialog.arguments = bundle
            return dialog
        }
    }

    class Builder {
        private var headerIconUri: Uri? = null
        private var title: CharSequence? = null
        private var message: CharSequence? = null
        private var messageGravity: Int = Gravity.CENTER

        private var positiveText: CharSequence? = null
        private var onPositive: (() -> Unit)? = null
        private var showDefaultConfirm: Boolean = true

        private var negativeText: CharSequence? = null
        private var onNegative: (() -> Unit)? = null
        private var showDefaultCancel: Boolean = false

        private var cancelable: Boolean = false
        private var onDismiss: (() -> Unit)? = null
        private var canceledOnTouchOutside: Boolean = false
        private var onCancelListener: DialogInterface.OnCancelListener? = null
        private var isDismissAfterClick: Boolean = true

        private var titleColor: Int = 0
        private var topImageUri: Uri? = null
        private var customMessageView: View? = null
        private var topBgRes: Int = 0
        private var topImageWidth: Int = 0
        private var topImageHeight: Int = 0
        private var showTopCloseBtn: Boolean = false
        private var positiveCountDownMS: Long = 0
        private var isClickableWhenCountDown: Boolean = false //倒计时期间能否点击按钮
        private var countDownTimerFormat: ((Long) -> String)? = null //倒计时格式化函数
        private var countDownFinishCallback: (() -> Unit)? = null //倒计时结束回调

        fun showTopClosetButton(show: Boolean): Builder {
            showTopCloseBtn = show
            return this
        }

        fun topBgResource(resourceId: Int): Builder {
            topBgRes = resourceId
            return this
        }

        fun customMessageView(view: View): Builder {
            customMessageView = view
            return this
        }

        fun topImageResource(resourceId: Int): Builder {
            topImageUri = UriUtil.getUriForResourceId(resourceId)
            return this
        }

        fun topImageResource(resourceId: Int, width: Int, height: Int): Builder {
            topImageUri = UriUtil.getUriForResourceId(resourceId)
            topImageWidth = width
            topImageHeight = height
            return this
        }

        fun topImageUrl(url: String, width: Int, height: Int): Builder {
            topImageUri = UriUtil.parseUriOrNull(url)
            topImageWidth = width
            topImageHeight = height
            return this
        }

        fun headerIconResource(resourceId: Int): Builder {
            headerIconUri = UriUtil.getUriForResourceId(resourceId)
            return this
        }

        fun headerIconUrl(url: String): Builder {
            headerIconUri = UriUtil.parseUriOrNull(url)
            return this
        }

        fun title(title: CharSequence): Builder {
            this.title = title
            return this
        }

        fun message(message: CharSequence): Builder {
            this.message = message
            return this
        }

        fun positiveText(positiveText: CharSequence): Builder {
            this.positiveText = positiveText
            return this
        }

        fun setShowDefaultCancel(showDefaultCancel: Boolean): Builder {
            this.showDefaultCancel = showDefaultCancel
            return this
        }

        fun onPositive(onPositive: () -> Unit): Builder {
            this.onPositive = onPositive
            return this
        }

        fun negativeText(negativeText: CharSequence): Builder {
            this.negativeText = negativeText
            return this
        }

        fun positiveCountDownMS(ms: Long): Builder {
            this.positiveCountDownMS = ms
            return this
        }

        fun onNegative(onNegative: () -> Unit): Builder {
            this.onNegative = onNegative
            return this
        }

        fun cancelable(cancelable: Boolean): Builder {
            this.cancelable = cancelable
            return this
        }

        fun canceledOnTouchOutside(canceledOnTouchOutside: Boolean): Builder {
            this.canceledOnTouchOutside = canceledOnTouchOutside
            return this
        }

        fun onDismiss(onDismiss: () -> Unit): Builder {
            this.onDismiss = onDismiss
            return this
        }

        fun titleColor(@ColorRes color: Int): Builder {
            this.titleColor = color
            return this
        }

        fun messageGravity(gravity: Int): Builder {
            this.messageGravity = gravity
            return this
        }

        fun dismissAfterClick(dismiss: Boolean): Builder {
            this.isDismissAfterClick = dismiss
            return this
        }

        fun isClickableWhenCountDown(isClickable: Boolean): Builder {
            this.isClickableWhenCountDown = isClickable
            return this
        }

        fun countDownTimerFormat(format: (Long) -> String): Builder {
            this.countDownTimerFormat = format
            return this
        }

        fun countDownFinishCallback(callback: () -> Unit): Builder {
            this.countDownFinishCallback = callback
            return this
        }

        fun build(): CommonDialog {
            return newInstance(
                headerIconUri,
                title,
                message,
                messageGravity,
                positiveText,
                onPositive,
                showDefaultConfirm,
                negativeText,
                onNegative,
                showDefaultCancel,
                cancelable,
                onDismiss,
                canceledOnTouchOutside,
                onCancelListener,
                isDismissAfterClick,
                titleColor,
                customMessageView,
                topBgRes,
                topImageUri,
                topImageWidth,
                topImageHeight,
                showTopCloseBtn,
                positiveCountDownMS,
                isClickableWhenCountDown,
                countDownTimerFormat,
                countDownFinishCallback
            )
        }

        fun show(manager: FragmentManager?) {
            manager?.let {
                build().show(it)
            } ?: Log.i(TAG, "fragment manager is null, show dialog failed")
        }

        fun show(manager: FragmentManager?, tag: String) {
            manager?.let {
                build().show(it, tag)
            }
        }
    }
}