package com.qimai.android.widgetlib.popup

import android.content.Context
import android.graphics.Color
import android.graphics.Point
import android.graphics.drawable.ColorDrawable
import android.graphics.drawable.Drawable
import android.os.Build
import android.view.*
import android.widget.FrameLayout
import android.widget.PopupWindow

/**
 *   created by wangwei   ON 2019-08-22  email:wangwei_5521@163.com
 *   @version 1.1.1
 *   @Description
 **/
abstract class AbsQMBasePopup(open var context: Context) {


    protected var mWindow = PopupWindow()

    private lateinit var mRootViewWrapper: FrameLayout
    private lateinit var mWindowManager: WindowManager


    protected open var mDismissListener: PopupWindow.OnDismissListener? = null

    abstract fun config(): WindowConfig

    var touchOutside = false
        set(value) {
            field = value
            mWindow.isOutsideTouchable = value
        }


    fun isShowing(): Boolean {
        return mWindow.isShowing
    }


    fun build(): AbsQMBasePopup {
        setContentView(contentView = config().mContentView)

        mWindow.width =
            if (config().mWindowWidth == -1) ViewGroup.LayoutParams.MATCH_PARENT else config().mWindowWidth
        mWindow.height =
            if (config().mWindowHeight == -1) ViewGroup.LayoutParams.WRAP_CONTENT else config().mWindowHeight
        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP_MR1) {
            mWindow.isAttachedInDecor = false
        }
        if (config().mBackground == null) {
            mWindow.setBackgroundDrawable(ColorDrawable(Color.TRANSPARENT))
        } else {
            mWindow.setBackgroundDrawable(config().mBackground)
        }

        mWindow.isTouchable = true
        mWindow.isFocusable = config().isOutsideTouchable
        mWindow.isOutsideTouchable = config().isOutsideTouchable

        // 在相关的View被移除时，window也自动移除。避免当Fragment退出后，Fragment中弹出的PopupWindow还存在于界面上。
        config().mAnchorView.addOnAttachStateChangeListener(object :
            View.OnAttachStateChangeListener {
            override fun onViewAttachedToWindow(v: View) {

            }

            override fun onViewDetachedFromWindow(v: View) {
                if (isShowing()) {
                    dismiss()
                }
            }
        })
        return this
    }

    fun dimBehind(dim: Float) {
        if (!::mWindowManager.isInitialized)
            mWindowManager = context.getSystemService(Context.WINDOW_SERVICE) as WindowManager
        if (!isShowing()) {
            throw RuntimeException("should call after method show() or in onShowEnd()")
        }
        val decorView = getDecorView()
        if (decorView != null) {
            val p = decorView.layoutParams as WindowManager.LayoutParams
            p.flags = p.flags or WindowManager.LayoutParams.FLAG_DIM_BEHIND
            p.dimAmount = dim
            mWindowManager.updateViewLayout(decorView, p)
        }
    }

    protected abstract fun onShowBegin(contentView: View): Point

    protected abstract fun onShowEnd()


    fun dismiss() {
        if (isShowing())
            mWindow.dismiss()
    }

    fun show() {
        if (!isShowing()) {
            val point = onShowBegin(mWindow.contentView)
            mWindow.showAtLocation(config().mAnchorView, config().mGravity, point.x, point.y)
            onShowEnd()
        }
    }


    fun setContentView(contentView: View) {
        mRootViewWrapper = FrameLayout(contentView.context)
        mRootViewWrapper.layoutParams = ViewGroup.LayoutParams(
            ViewGroup.LayoutParams.MATCH_PARENT,
            ViewGroup.LayoutParams.WRAP_CONTENT
        )
        mRootViewWrapper.addView(contentView)
        mWindow.contentView = mRootViewWrapper
        mWindow.setTouchInterceptor(View.OnTouchListener { v, event ->
            if (event.action == MotionEvent.ACTION_OUTSIDE && config().isOutsideTouchable) {
                mWindow.dismiss()
                return@OnTouchListener false
            }
            false
        })
        mWindow.setOnDismissListener {
            this@AbsQMBasePopup.onDismiss()
            if (mDismissListener != null) {
                mDismissListener!!.onDismiss()
            }
        }
        configViewEnd(mWindow.contentView)

    }

    open protected fun configViewEnd(contentView: View) {}


    protected fun onDismiss() {}

    private fun getDecorView(): View? {
        var decorView: View? = null
        try {
            decorView = if (mWindow.background == null) {
                if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
                    mWindow.contentView.parent as View
                } else {
                    mWindow.contentView
                }
            } else {
                if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
                    mWindow.contentView.parent.parent as View
                } else {
                    mWindow.contentView.parent as View
                }
            }
        } catch (ignore: Exception) {
            // irgnore
        }

        return decorView
    }

    class WindowConfig {
        var mWindowWidth = -1
        var mWindowHeight = -1
        var mAnimationStyle: Int = -1
        var mGravity: Int = Gravity.CENTER
        var mBackground: Drawable? = null
        lateinit var mContentView: View
        lateinit var mAnchorView: View
        var isOutsideTouchable = true
    }
}