package com.adealink.weparty.commonui.widget

import android.content.Context
import android.util.AttributeSet
import android.view.Gravity
import android.view.View
import android.view.ViewGroup
import android.widget.LinearLayout.HORIZONTAL
import android.widget.LinearLayout.VERTICAL
import androidx.appcompat.widget.LinearLayoutCompat
import androidx.constraintlayout.widget.ConstraintLayout
import androidx.core.view.updateLayoutParams
import com.adealink.weparty.R


class SpreadLinearLayout @JvmOverloads constructor(
    context: Context, attrs: AttributeSet? = null, defStyleAttr: Int = 0
) : ConstraintLayout(context, attrs, defStyleAttr) {

    private var group1: LinearLayoutCompat = LinearLayoutCompat(context).apply {
        id = R.id.id_spread_linear_layout_group_1
    }
    private var group2: LinearLayoutCompat = LinearLayoutCompat(context).apply {
        id = R.id.id_spread_linear_layout_group_2
    }

    private var orientation: Int? = null
    private var gravity: Int? = null
    private var dividerSize: Int = 0

    /**
     * 哪些控件放到Group2里
     */
    private val group2Ids = HashSet<Int>()

    init {
        addView(
            group1,
            ConstraintLayout.LayoutParams(
                ConstraintLayout.LayoutParams.WRAP_CONTENT,
                ConstraintLayout.LayoutParams.WRAP_CONTENT
            ).apply {
                topToTop = ConstraintLayout.LayoutParams.PARENT_ID
                startToStart = ConstraintLayout.LayoutParams.PARENT_ID
                endToEnd = ConstraintLayout.LayoutParams.PARENT_ID
            }
        )
        addView(
            group2,
            ConstraintLayout.LayoutParams(
                ConstraintLayout.LayoutParams.WRAP_CONTENT,
                ConstraintLayout.LayoutParams.WRAP_CONTENT
            ).apply {
                topToTop = ConstraintLayout.LayoutParams.PARENT_ID
                startToStart = ConstraintLayout.LayoutParams.PARENT_ID
                endToEnd = ConstraintLayout.LayoutParams.PARENT_ID
            }
        )
        initAttrs(context, attrs)
    }

    private fun initAttrs(context: Context, attrs: AttributeSet?) {
        context.theme.obtainStyledAttributes(
            attrs,
            R.styleable.SpreadLinearLayout,
            0, 0
        ).apply {
            dividerSize = getDimensionPixelSize(R.styleable.SpreadLinearLayout_dividerSize, 0)
            val orientation = getInt(R.styleable.SpreadLinearLayout_orientation, VERTICAL)
            val gravity = getInt(R.styleable.SpreadLinearLayout_android_gravity, Gravity.START)
            setOrientationAndGravity(orientation, gravity)
        }
    }

    fun setOrientationAndGravity(orientation: Int, gravity: Int): Boolean {
        var requestLayout = false
        if (this.orientation != orientation || this.gravity != gravity) {
            this.orientation = orientation
            this.gravity = gravity
            group1.orientation = orientation
            group2.orientation = orientation
            group1.gravity = gravity
            group2.gravity = gravity

            if (orientation == HORIZONTAL) {
                group1.layoutParams = ConstraintLayout.LayoutParams(
                    ConstraintLayout.LayoutParams.WRAP_CONTENT,
                    ConstraintLayout.LayoutParams.WRAP_CONTENT
                ).apply {
                    topToTop = ConstraintLayout.LayoutParams.PARENT_ID
                    bottomToBottom = ConstraintLayout.LayoutParams.PARENT_ID
                    startToStart = ConstraintLayout.LayoutParams.PARENT_ID
                    endToStart = R.id.id_spread_linear_layout_group_2
                    horizontalBias = 0f
                    marginEnd = dividerSize

                    if (gravity == Gravity.CENTER_VERTICAL) {
                        verticalBias = 0.5f
                    } else if (gravity == Gravity.TOP) {
                        verticalBias = 0f
                    } else if (gravity == Gravity.BOTTOM) {
                        verticalBias = 1f
                    }
                }

                group2.layoutParams = ConstraintLayout.LayoutParams(
                    ConstraintLayout.LayoutParams.WRAP_CONTENT,
                    ConstraintLayout.LayoutParams.WRAP_CONTENT
                ).apply {
                    topToTop = ConstraintLayout.LayoutParams.PARENT_ID
                    bottomToBottom = ConstraintLayout.LayoutParams.PARENT_ID
                    endToEnd = ConstraintLayout.LayoutParams.PARENT_ID

                    if (gravity == Gravity.CENTER_VERTICAL) {
                        verticalBias = 0.5f
                    } else if (gravity == Gravity.TOP) {
                        verticalBias = 0f
                    } else if (gravity == Gravity.BOTTOM) {
                        verticalBias = 1f
                    }
                }
            } else {
                group1.layoutParams = ConstraintLayout.LayoutParams(
                    ConstraintLayout.LayoutParams.WRAP_CONTENT,
                    ConstraintLayout.LayoutParams.WRAP_CONTENT
                ).apply {
                    startToStart = ConstraintLayout.LayoutParams.PARENT_ID
                    endToEnd = ConstraintLayout.LayoutParams.PARENT_ID
                    topToTop = ConstraintLayout.LayoutParams.PARENT_ID
                    bottomToTop = R.id.id_spread_linear_layout_group_2
                    verticalBias = 0f
                    bottomMargin = dividerSize

                    if (gravity == Gravity.CENTER_HORIZONTAL) {
                        horizontalBias = 0.5f
                    } else if (gravity == Gravity.START) {
                        horizontalBias = 0.5f
                    } else if (gravity == Gravity.END) {
                        horizontalBias = 0.5f
                    }
                }
                group2.layoutParams = ConstraintLayout.LayoutParams(
                    ConstraintLayout.LayoutParams.WRAP_CONTENT,
                    ConstraintLayout.LayoutParams.WRAP_CONTENT
                ).apply {
                    startToStart = ConstraintLayout.LayoutParams.PARENT_ID
                    endToEnd = ConstraintLayout.LayoutParams.PARENT_ID
                    bottomToBottom = ConstraintLayout.LayoutParams.PARENT_ID

                    if (gravity == Gravity.CENTER_HORIZONTAL) {
                        horizontalBias = 0.5f
                    } else if (gravity == Gravity.START) {
                        horizontalBias = 0.5f
                    } else if (gravity == Gravity.END) {
                        horizontalBias = 0.5f
                    }
                }
            }
            if (group1.childCount > 0) {
                for (i in 0 until group1.childCount) {
                    val child = group1.getChildAt(i)
                    child.updateLayoutParams<LayoutParams> {
                        if (orientation == HORIZONTAL) {
                            marginEnd = dividerSize
                            bottomMargin = 0
                        } else {
                            marginEnd = 0
                            bottomMargin = dividerSize
                        }
                    }
                }
            }
            if (group2.childCount > 0) {
                for (i in 0 until group2.childCount) {
                    val child = group2.getChildAt(i)
                    child.updateLayoutParams<LayoutParams> {
                        if (orientation == HORIZONTAL) {
                            marginEnd = dividerSize
                            bottomMargin = 0
                        } else {
                            marginEnd = 0
                            bottomMargin = dividerSize
                        }
                    }
                }
            }
            requestLayout = true
        }
        return requestLayout
    }

    fun setGroup2Ids(vararg ids: Int) {
        group2Ids.addAll(ids.toList())
    }

    override fun indexOfChild(child: View?): Int {
        child ?: return -1
        if (child.id == R.id.id_spread_linear_layout_group_1 ||
            child.id == R.id.id_spread_linear_layout_group_2
        ) {
            return -1
        }
        var index = group1.indexOfChild(child)
        if (index != -1) {
            return index
        }
        index = group2.indexOfChild(child)
        if (index != -1) {
            return index + group1.childCount
        }
        return -1
    }

    override fun addView(child: View?, index: Int, params: ViewGroup.LayoutParams?) {
        child ?: return
        if (child.id == R.id.id_spread_linear_layout_group_1 ||
            child.id == R.id.id_spread_linear_layout_group_2
        ) {
            super.addView(child, index, params)
        } else {

            if (group2Ids.contains(child.id)) {
                group2.addView(
                    child,
                    (index - group1.childCount).coerceIn(-1, group2.childCount),
                    ((params ?: LayoutParams(
                        LinearLayoutCompat.LayoutParams.WRAP_CONTENT,
                        LinearLayoutCompat.LayoutParams.WRAP_CONTENT
                    )) as? LayoutParams)?.apply {
                        if (orientation == HORIZONTAL) {
                            marginEnd = dividerSize
                        } else {
                            bottomMargin = dividerSize
                        }
                    }
                )
            } else {
                group1.addView(
                    child,
                    index.coerceIn(-1, group1.childCount),
                    ((params ?: LayoutParams(
                        LinearLayoutCompat.LayoutParams.WRAP_CONTENT,
                        LinearLayoutCompat.LayoutParams.WRAP_CONTENT
                    )) as? LayoutParams)?.apply {
                        if (orientation == HORIZONTAL) {
                            marginEnd = dividerSize
                        } else {
                            bottomMargin = dividerSize
                        }
                    }
                )
            }
        }
    }

    override fun removeView(view: View?) {
        view ?: return
        if (group2Ids.contains(view.id)) {
            group2.removeView(view)
        } else {
            group1.removeView(view)
        }
    }

    override fun removeAllViews() {
        group1.removeAllViews()
        group2.removeAllViews()
    }

    class LayoutParams : LinearLayoutCompat.LayoutParams {
        constructor(c: Context?, attrs: AttributeSet?) : super(c, attrs)
        constructor(width: Int, height: Int) : super(width, height)
        constructor(width: Int, height: Int, weight: Float) : super(width, height, weight)
        constructor(p: ViewGroup.LayoutParams?) : super(p)

    }

}