package com.rc.core.ui.widget

import android.content.Context
import android.content.res.TypedArray
import android.util.AttributeSet
import android.view.View
import android.view.ViewGroup
import android.widget.RelativeLayout
import androidx.annotation.LayoutRes
import com.rc.core.R

/**
 * info
 *
 * @author ReiChin_
 */
class MultipleStatusView @JvmOverloads constructor(
    context: Context,
    attrs: AttributeSet? = null,
    defStyleAttr: Int = 0
) :
    RelativeLayout(context, attrs, defStyleAttr) {

    companion object {
        private const val STATUS_CONTENT = 0x00
        private const val STATUS_LOADING = 0x01
        private const val STATUS_EMPTY = 0x02
        private const val STATUS_ERROR = 0x03
        private const val STATUS_NO_NETWORK = 0x04

        private val DEFAULT_LAYOUT_PARAMS =
            LayoutParams(LayoutParams.MATCH_PARENT, LayoutParams.MATCH_PARENT)

        private const val NULL_RESOURCE_ID = -1
    }

    private var mEmptyView: View? = null
    private var mErrorView: View? = null
    private var mLoadingView: View? = null
    private var mNoNetworkView: View? = null
    private var mContentView: View? = null
    private var mEmptyViewResId = NULL_RESOURCE_ID
    private var mErrorViewResId = NULL_RESOURCE_ID
    private var mLoadingViewResId = NULL_RESOURCE_ID
    private var mNoNetworkViewResId = NULL_RESOURCE_ID
    private var mContentViewResId = NULL_RESOURCE_ID

    private var mViewStatus = -1

    private val mOtherIds = ArrayList<Int>()

    init {
        val a: TypedArray =
            context.obtainStyledAttributes(attrs, R.styleable.MultipleStatusView, defStyleAttr, 0)
        mEmptyViewResId = a.getResourceId(
            R.styleable.MultipleStatusView_emptyView,
            R.layout.view_multiple_empty_view
        )
        mErrorViewResId = a.getResourceId(
            R.styleable.MultipleStatusView_errorView,
            R.layout.view_multiple_error_view
        )
        mLoadingViewResId = a.getResourceId(
            R.styleable.MultipleStatusView_loadingView,
            R.layout.view_multiple_loading_view
        )
        mNoNetworkViewResId = a.getResourceId(
            R.styleable.MultipleStatusView_noNetworkView,
            R.layout.view_multiple_no_network_view
        )
        mContentViewResId =
            a.getResourceId(R.styleable.MultipleStatusView_contentView, NULL_RESOURCE_ID)
        a.recycle()
    }

    override fun onFinishInflate() {
        super.onFinishInflate()
        showContent()
    }

    override fun onDetachedFromWindow() {
        super.onDetachedFromWindow()
        clear(mEmptyView, mLoadingView, mErrorView, mNoNetworkView)
        if (mOtherIds.isNotEmpty()) {
            mOtherIds.clear()
        }
        if (null != mOnRetryClickListener) {
            mOnRetryClickListener = null
        }
        if (null != mViewStatusListener) {
            mViewStatusListener = null
        }
    }

    /**
     * 获取当前状态
     *
     * @return 视图状态
     */
    fun getViewStatus() = mViewStatus

    private var mOnRetryClickListener: ((view: View) -> Unit)? = null

    /**
     * 设置重试点击事件
     *
     * @param listener 重试点击事件
     */
    fun setOnRetryClickListener(listener: (view: View) -> Unit) {
        this.mOnRetryClickListener = listener
    }

    /**
     * 显示空视图
     *
     * @param view         自定义视图
     * @param layoutParams 布局参数
     */
    fun showEmpty(
        @LayoutRes layoutId: Int = mEmptyViewResId,
        view: View = mEmptyView ?: View.inflate(context, layoutId, null),
        layoutParams: ViewGroup.LayoutParams = DEFAULT_LAYOUT_PARAMS
    ) {
        changeViewStatus(STATUS_EMPTY)
        if (null == mEmptyView) {
            mEmptyView = view
            val emptyRetryView: View? = mEmptyView!!.findViewById(R.id.empty_retry_view)
            if (null != mOnRetryClickListener && null != emptyRetryView) {
                emptyRetryView.setOnClickListener(mOnRetryClickListener)
            }
            mOtherIds.add(mEmptyView!!.id)
            addView(mEmptyView, 0, layoutParams)
        }
        showViewById(mEmptyView!!.id)
    }

    /**
     * 显示错误视图
     *
     * @param view         自定义视图
     * @param layoutParams 布局参数
     */
    fun showError(
        @LayoutRes layoutId: Int = mErrorViewResId,
        view: View = mErrorView ?: View.inflate(context, layoutId, null),
        layoutParams: ViewGroup.LayoutParams = DEFAULT_LAYOUT_PARAMS
    ) {
        changeViewStatus(STATUS_ERROR)
        if (null == mErrorView) {
            mErrorView = view
            val errorRetryView: View? = mErrorView!!.findViewById(R.id.error_retry_view)
            if (null != mOnRetryClickListener && null != errorRetryView) {
                errorRetryView.setOnClickListener(mOnRetryClickListener)
            }
            mOtherIds.add(mErrorView!!.id)
            addView(mErrorView, 0, layoutParams)
        }
        showViewById(mErrorView!!.id)
    }

    /**
     * 显示加载中视图
     *
     * @param view         自定义视图
     * @param layoutParams 布局参数
     */
    fun showLoading(
        @LayoutRes layoutId: Int = mLoadingViewResId,
        view: View = mLoadingView ?: View.inflate(context, layoutId, null),
        layoutParams: ViewGroup.LayoutParams = DEFAULT_LAYOUT_PARAMS
    ) {
        changeViewStatus(STATUS_LOADING)
        if (null == mLoadingView) {
            mLoadingView = view
            mOtherIds.add(mLoadingView!!.id)
            addView(mLoadingView, 0, layoutParams)
        }
        showViewById(mLoadingView!!.id)
    }

    /**
     * 显示无网络视图
     *
     * @param view         自定义视图
     * @param layoutParams 布局参数
     */
    fun showNoNetwork(
        @LayoutRes layoutId: Int = mNoNetworkViewResId,
        view: View = mNoNetworkView ?: View.inflate(context, layoutId, null),
        layoutParams: ViewGroup.LayoutParams = DEFAULT_LAYOUT_PARAMS
    ) {
        changeViewStatus(STATUS_NO_NETWORK)
        if (null == mNoNetworkView) {
            mNoNetworkView = view
            val noNetworkRetryView: View? =
                mNoNetworkView!!.findViewById(R.id.no_network_retry_view)
            if (null != mOnRetryClickListener && null != noNetworkRetryView) {
                noNetworkRetryView.setOnClickListener(mOnRetryClickListener)
            }
            mOtherIds.add(mNoNetworkView!!.id)
            addView(mNoNetworkView, 0, layoutParams)
        }
        showViewById(mNoNetworkView!!.id)
    }

    /**
     * 显示内容视图
     *
     * @param view         自定义视图
     * @param layoutParams 布局参数
     */
    fun showContent(
        @LayoutRes layoutId: Int = mContentViewResId,
        view: View? = mContentView,
        layoutParams: ViewGroup.LayoutParams = DEFAULT_LAYOUT_PARAMS
    ) {
        // ?: View.inflate(context, layoutId, null)

        changeViewStatus(STATUS_CONTENT)

        if (null == mContentView) {
            if (NULL_RESOURCE_ID != layoutId) {
                mContentView = View.inflate(context, layoutId, null)
                addView(mContentView, 0, layoutParams)
            } else {
                showContentView()
                return
            }
        }


//        if (NULL_RESOURCE_ID == layoutId && null == mContentView) {
////            mContentView = View.inflate(context, layoutId, null)
////            addView(mContentView, 0, layoutParams)
//        }


//        if (NULL_RESOURCE_ID == layoutId && mContentView == null) {
//            showContentView()
//        } else {
        clear(mContentView)
        mContentView = view
        addView(mContentView, 0, layoutParams)
        showViewById(mContentView!!.id)
//        }
    }

    private fun showViewById(viewId: Int) {
        for (i in 0 until childCount) {
            val view = getChildAt(i)
            view.visibility = if (view.id == viewId) View.VISIBLE else View.GONE
        }
    }

    private fun showContentView() {
        for (i in 0 until childCount) {
            val view = getChildAt(i)
            view.visibility = if (mOtherIds.contains(view.id)) View.GONE else View.VISIBLE
        }
    }

    private fun checkNull(obj: Any?, hint: String) {
        if (null == obj) {
            throw NullPointerException(hint)
        }
    }

    private fun clear(vararg views: View?) {
        try {
            for (view in views) {
                view?.let { removeView(it) }
            }
        } catch (e: Exception) {
            e.printStackTrace()
        }
    }

    // 视图状态改变接口
    private var mViewStatusListener: ((oldViewStatus: Int, newViewStatus: Int) -> Unit)? = null

    /**
     * 设置视图状态改变监听事件
     */
    fun setOnViewStatusChangeListener(listener: (oldViewStatus: Int, newViewStatus: Int) -> Unit) {
        this.mViewStatusListener = listener
    }

    /**
     * 改变视图状态
     *
     * @param newViewStatus 新的视图状态
     */
    private fun changeViewStatus(newViewStatus: Int) {
        if (mViewStatus == newViewStatus) {
            return
        }
        mViewStatusListener?.invoke(mViewStatus, newViewStatus)
        mViewStatus = newViewStatus
    }

}