package com.adealink.weparty.commonui.dialogfragment

import android.content.Context
import android.content.DialogInterface
import android.os.Bundle
import android.util.Log
import android.view.KeyEvent
import android.view.LayoutInflater
import android.view.View
import android.view.ViewGroup
import android.view.Window
import androidx.annotation.CallSuper
import androidx.annotation.LayoutRes
import androidx.fragment.app.DialogFragment
import androidx.fragment.app.FragmentManager
import androidx.fragment.app.FragmentTransaction
import com.adealink.frame.aab.util.compatInflateView
import com.adealink.frame.aab.util.installSplitCompat
import com.google.firebase.Firebase
import com.google.firebase.crashlytics.crashlytics
import com.qmuiteam.qmui.widget.dialog.QMUITipDialog

inline fun <reified F : BaseDialogFragment> showDialogFragment(
    fm: FragmentManager,
    args: Bundle? = null,
): F {
    val f = F::class.java.newInstance().apply {
        arguments = args
    }
    f.show(fm)
    return f
}

inline fun <reified F : BaseDialogFragment> showDialogFragment(
    ft: FragmentTransaction,
    args: Bundle? = null,
): F {
    val f = F::class.java.newInstance().apply {
        arguments = args
    }
    f.show(ft)
    return f
}

open class BaseDialogFragment(@LayoutRes open val layoutId: Int) : DialogFragment() {

    companion object {
        private const val TAG = "BaseDialogFragment"
    }

    @Volatile
    private var isShow = false

    open val fgTag: String? = null
    private var loadingDialog: QMUITipDialog? = null
    open val cancelable: Boolean = true
    open var canceledOnTouchOutside: Boolean = true
        set(value) {
            field = value
            dialog?.setCanceledOnTouchOutside(value)
        }
    private var dismissCallback: (() -> Unit)? = null
    private var clickCallback: ((tag: Any?) -> Unit)? = null

    override fun onAttach(context: Context) {
        super.onAttach(context)
        installSplitCompat(context)
    }

    @CallSuper
    override fun onCreateView(
        inflater: LayoutInflater,
        container: ViewGroup?, savedInstanceState: Bundle?,
    ): View? {
        return compatInflateView(inflater.context, layoutId, container, false)
    }

    @CallSuper
    override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
        super.onViewCreated(view, savedInstanceState)
        com.adealink.frame.log.Log.i(TAG," onViewCreated... ${javaClass.simpleName}")
        Firebase.crashlytics.log("BaseFragment onResume: ${javaClass.simpleName}")
        initViews()
        initComponents()
        observeViewModel()
        loadData()
    }

    fun isViewCreated(): Boolean {
        return isAdded && view != null
    }

    open fun initViews() {

    }

    open fun observeViewModel() {

    }

    open fun loadData() {

    }

    open fun show(transaction: FragmentTransaction): Int {
        return show(transaction, fgTag)
    }

    override fun show(transaction: FragmentTransaction, tag: String?): Int {
        return if (!this.isShow && !this.isAdded && !this.isVisible) {
            this.isShow = true
            try {
                super.show(transaction, tag)
            } catch (e: Exception) {
                e.printStackTrace()
                this.dismissAllowingStateLoss()
                -1
            }
        } else {
            -1
        }
    }

    open fun show(manager: FragmentManager) {
        show(manager, fgTag)
    }

    override fun show(manager: FragmentManager, tag: String?) {
        if (!this.isShow && !this.isAdded && !this.isVisible) {
            this.isShow = true
            val ft = manager.beginTransaction()
            val prev = manager.findFragmentByTag(tag)
            if (prev != null) {
                ft.remove(prev)
            }
            try {
                ft.add(this, tag)
                ft.commitAllowingStateLoss()
            } catch (var6: Exception) {
                var6.printStackTrace()
                this.dismissAllowingStateLoss()
            }

        }
    }

    private fun initLoadingDialog() {
        if (loadingDialog == null) {
            loadingDialog = QMUITipDialog.Builder(context)
                .setIconType(QMUITipDialog.Builder.ICON_TYPE_LOADING)
                .create()
        }
    }

    fun showLoading() {
        initLoadingDialog()
        loadingDialog?.show()
    }

    fun dismissLoading() {
        loadingDialog?.dismiss()
    }

    override fun dismiss() {
        this.dismissAllowingStateLoss()
        dismissLoading()
    }

    @CallSuper
    override fun onActivityCreated(savedInstanceState: Bundle?) {
        if (this.dialog == null) {
            this.showsDialog = false
        }
        //必须设置为无标题栏，否则4.4.2会出现一条蓝线.这个方法必须在setContentView之前，所以在onActivityCreated之前
        //https://stackoverflow.com/questions/37738690/dialogfragment-has-blue-line-on-top-in-android-4-4-2
        val window = dialog?.window
        try {
            window?.requestFeature(Window.FEATURE_NO_TITLE)
        } catch (ex: Exception) {
            Log.e(TAG, "requestFeature exception : $ex")
        }
        super.onActivityCreated(savedInstanceState)
    }

    open fun initComponents() {}

    override fun dismissAllowingStateLoss() {
        if (!this.isDetached && !this.isHidden) {
            try {
                super.dismissAllowingStateLoss()
            } catch (e: Exception) {
                e.printStackTrace()
            }
        }
    }

    override fun onDismiss(dialog: DialogInterface) {
        super.onDismiss(dialog)
        this.isShow = false
        dismissCallback?.invoke()
    }

    fun setDismissCallback(dismissCallback: (() -> Unit)?): BaseDialogFragment {
        this.dismissCallback = dismissCallback
        return this
    }

    fun setClickCallback(clickCallback: ((tag: Any?) -> Unit)?): BaseDialogFragment {
        this.clickCallback = clickCallback
        return this
    }

    fun getClickCallback(): ((tag: Any?) -> Unit)? {
        return clickCallback
    }

    override fun onDestroyView() {
        super.onDestroyView()
        this.isShow = false
    }

    @CallSuper
    override fun onStart() {
        try {
            super.onStart()
            isCancelable = cancelable
            dialog?.setCanceledOnTouchOutside(canceledOnTouchOutside)
            val dialog = dialog ?: return
            val window = dialog.window ?: return
            resetWindowAttributes(window)
        } catch (e: Exception) {
            e.printStackTrace()
            Log.d(TAG, "onStart exception, exception message = ${e.message}")
        }
    }

    open fun isShowing(): Boolean {
        return isShow
    }

    open fun resetWindowAttributes(window: Window) {

    }

    //点击返回键不消失
    open fun blockBackEvent() {
        dialog?.setOnKeyListener(object : DialogInterface.OnKeyListener {
            override fun onKey(dialog: DialogInterface?, keyCode: Int, event: KeyEvent?): Boolean {
                if (keyCode == KeyEvent.KEYCODE_BACK) {
                    return true
                }
                return false
            }
        })
    }
}