package com.qimai.android.widgetlib.bottombar

import android.content.Context
import android.graphics.Bitmap
import android.graphics.BitmapFactory
import android.graphics.Canvas
import android.graphics.Paint
import android.os.Parcel
import android.os.Parcelable
import android.util.AttributeSet
import android.view.View
import android.view.View.OnClickListener
import android.view.ViewGroup
import android.view.ViewTreeObserver
import android.view.animation.AccelerateDecelerateInterpolator
import android.widget.LinearLayout
import androidx.core.content.ContextCompat
import com.qimai.android.tools.dpTopx
import com.qimai.android.tools.resize
import com.qimai.android.widgetlib.R
import java.util.*

@Suppress("unused")
class BottomBar @JvmOverloads constructor(
    context: Context,
    attrs: AttributeSet? = null,
    defStyleAttr: Int = 0
) :
    LinearLayout(context, attrs, defStyleAttr) {
    private val TRANSLATE_DURATION_MILLIS = 200

    private val mInterpolator = AccelerateDecelerateInterpolator()
    private var mVisible = true

    private var mTabs: MutableList<BottomBarTab> = ArrayList()
    private var mTabLayout: LinearLayout? = null

    private var mTabParams: LayoutParams? = null
    private var mCurrentPosition = -1
    private var mListener: OnTabSelectedListener? = null

    private var mShadowBitmap: Bitmap? = null
    private val mPaint = Paint(Paint.ANTI_ALIAS_FLAG)


    init {
        initBottom(context)
    }


    private fun initBottom(context: Context) {

        clipChildren = false
        setWillNotDraw(false)
        orientation = VERTICAL
        mPaint.color = ContextCompat.getColor(context, R.color.segment_divider_dark)
        mPaint.strokeWidth = context.dpTopx(0.7F).toFloat()
        mTabLayout = LinearLayout(context)
        mTabLayout!!.orientation = HORIZONTAL
        this.addView(
            mTabLayout,
            LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.MATCH_PARENT)
        )
        mTabLayout!!.clipChildren = false
        mTabParams = LayoutParams(0, ViewGroup.LayoutParams.MATCH_PARENT)
        mTabParams!!.weight = 1f

        mShadowBitmap = BitmapFactory.decodeResource(resources, R.drawable.segment_bottom_shadow)
        mShadowBitmap =
            mShadowBitmap!!.resize(
                resources.displayMetrics.widthPixels,
                mShadowBitmap!!.height / 2
            )
    }

    override fun onDraw(canvas: Canvas?) {
        canvas!!.drawBitmap(mShadowBitmap!!, 0f, (-mShadowBitmap!!.height).toFloat(), mPaint)

        super.onDraw(canvas)
    }


    override fun onAttachedToWindow() {
        super.onAttachedToWindow()
        val view = parent as View
        if (view is ViewGroup) {
            view.clipChildren = false
        }
    }

    fun addItem(tab: BottomBarTab): BottomBar {
        tab.setOnClickListener(OnClickListener { v ->
            if (mListener == null) return@OnClickListener
            val pos = mTabs.indexOf(v)
            if (pos == -1) return@OnClickListener
            if (mCurrentPosition == -1) {
                mListener!!.onTabSelected(pos, 0)
                tab.isSelected = true
                mCurrentPosition = pos
            } else {
                if (mCurrentPosition == pos) {
                    mListener!!.onTabReselected(pos)
                } else {
                    //修复可能存在的数组越界情况
                    if (mCurrentPosition > mTabs.size - 1) mCurrentPosition = mTabs.size - 1
                    mListener!!.onTabSelected(pos, mCurrentPosition)
                    tab.isSelected = true
                    mListener!!.onTabUnselected(mCurrentPosition)
                    mTabs[mCurrentPosition].isSelected = false
                    mCurrentPosition = pos
                }
            }
        })
        tab.layoutParams = mTabParams
        mTabLayout!!.addView(tab)
        mTabs.add(tab)
        return this
    }

    //获取BottomBarTab 的容器
    fun getTabLayout(): LinearLayout? {
        return mTabLayout
    }

    //重置tabs 数量
    fun resetTabs() {
        mTabs = ArrayList()
    }

    fun resetCurrentPosition() {
        mCurrentPosition = -1
    }

    /**
     * 设置选择监听
     */
    fun setOnTabSelectedListener(onTabSelectedListener: OnTabSelectedListener) {
        mListener = onTabSelectedListener
    }

    /**
     * 设置当前 item
     */
    fun setCurrentItem(position: Int) {
        mTabLayout!!.post {
            mTabLayout!!.getChildAt(position).performClick()
        }
    }

    /**
     * 获取当前 选中index
     */
    fun getCurrentItemPosition(): Int {
        return mCurrentPosition
    }

    /**
     * 获取 Tab
     */
    fun getItem(index: Int): BottomBarTab? {
        return if (mTabs.size < index) null else mTabs[index]
    }

    interface OnTabSelectedListener {
        fun onTabSelected(position: Int, prePosition: Int)

        fun onTabUnselected(position: Int)

        fun onTabReselected(position: Int)
    }

    override fun onSaveInstanceState(): Parcelable? {
        val superState = super.onSaveInstanceState()
        return SavedState(superState!!, mCurrentPosition)
    }

    override fun onRestoreInstanceState(state: Parcelable) {
        val ss = state as SavedState
        super.onRestoreInstanceState(ss.superState)

        if (mCurrentPosition != ss.position) {
            if (mCurrentPosition == -1) {
                val childAt = mTabLayout!!.getChildAt(ss.position)
                if (childAt != null) {
                    childAt.isSelected = true
                }
                mCurrentPosition = ss.position
                return
            }
            val currentView = mTabLayout!!.getChildAt(mCurrentPosition)
            if (currentView != null) {
                currentView.isSelected = false
            }
            val selectView = mTabLayout!!.getChildAt(ss.position)
            if (selectView != null) {
                selectView.isSelected = true
            }
        }
        mCurrentPosition = ss.position
    }


    internal class SavedState : BaseSavedState {


        var position: Int = 0

        constructor(source: Parcel) : super(source) {
            position = source.readInt()
        }

        constructor(superState: Parcelable, position: Int) : super(superState) {
            this.position = position
        }

        override fun writeToParcel(parcel: Parcel, flags: Int) {
            parcel.writeInt(position)
        }

        override fun describeContents(): Int {
            return 0
        }

        companion object CREATOR : Parcelable.Creator<SavedState> {
            override fun createFromParcel(parcel: Parcel): SavedState {
                return SavedState(parcel)
            }

            override fun newArray(size: Int): Array<SavedState?> {
                return arrayOfNulls(size)
            }
        }


    }


    fun hide() {
        hide(true)
    }

    fun show() {
        show(true)
    }

    fun hide(anim: Boolean) {
        toggle(false, anim, false)
    }

    fun show(anim: Boolean) {
        toggle(true, anim, false)
    }

    fun isVisible(): Boolean {
        return mVisible
    }

    private fun toggle(visible: Boolean, animate: Boolean, force: Boolean) {
        if (mVisible != visible || force) {
            mVisible = visible
            val height = height
            if (height == 0 && !force) {
                val vto = viewTreeObserver
                if (vto.isAlive) {
                    // view树完成测量并且分配空间而绘制过程还没有开始的时候播放动画。
                    vto.addOnPreDrawListener(object : ViewTreeObserver.OnPreDrawListener {
                        override fun onPreDraw(): Boolean {
                            val currentVto = viewTreeObserver
                            if (currentVto.isAlive) {
                                currentVto.removeOnPreDrawListener(this)
                            }
                            toggle(visible, animate, true)
                            return true
                        }
                    })
                    return
                }
            }
            val translationY = if (visible) 0 else height
            if (animate) {
                animate().setInterpolator(mInterpolator)
                    .setDuration(TRANSLATE_DURATION_MILLIS.toLong())
                    .translationY(translationY.toFloat())
            } else {
                this.translationY = translationY.toFloat()
            }
        }
    }

}