package com.ama.core.common.widget

import android.content.Context
import android.util.AttributeSet
import android.view.MotionEvent
import android.view.View
import android.view.ViewGroup
import com.ama.core.common.util.dp
import kotlin.math.abs

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

    private var mSubviewTop: Int = 10.dp
    private var mSubviewLeft: Int = 20.dp
    private var edgeThreshold = 0.dp


    private var isDragging = false
    private var draggedView: View? = null
    private var lastTouchX = 0f
    private var lastTouchY = 0f


    var onDragStart: ((View) -> Unit)? = null
    var onDragEnd: ((View) -> Unit)? = null
    var onDragging: ((View, Float, Float) -> Unit)? = null


    init {
        isClickable = true
        isLongClickable = true
    }


    override fun onInterceptTouchEvent(ev: MotionEvent): Boolean {
        when (ev.action and MotionEvent.ACTION_MASK) {
            MotionEvent.ACTION_DOWN -> {
                lastTouchX = ev.x
                lastTouchY = ev.y

                val child = findChildUnder(ev.x.toInt(), ev.y.toInt())
                if (child != null) {
                    draggedView = child
                    return true
                }
                return false
            }

            MotionEvent.ACTION_MOVE -> {
                if (draggedView != null && !isDragging) {
                    val dx = abs(ev.x - lastTouchX)
                    val dy = abs(ev.y - lastTouchY)
                    if (dx > 5f || dy > 5f) { // 降低阈值
                        startDrag()
                        return true
                    }
                }
                return isDragging
            }
        }
        return false
    }

    override fun onTouchEvent(event: MotionEvent): Boolean {
        if (draggedView == null) return false

        when (event.action and MotionEvent.ACTION_MASK) {
            MotionEvent.ACTION_DOWN -> {
                return true
            }

            MotionEvent.ACTION_MOVE -> {
                if (!isDragging) {
                    startDrag()
                }

                val dx = event.x - lastTouchX
                val dy = event.y - lastTouchY

                updateViewPosition(dx, dy)
                lastTouchX = event.x
                lastTouchY = event.y
                return true
            }

            MotionEvent.ACTION_UP, MotionEvent.ACTION_CANCEL -> {
                endDrag()
                return true
            }
        }
        return false
    }

    private fun startDrag() {
        isDragging = true
        draggedView?.let { view ->
            bringChildToFront(view)
            onDragStart?.invoke(view)
        }
    }

    private fun updateViewPosition(dx: Float, dy: Float) {
        draggedView?.let { view ->
            val currentPos = Pair(view.left, view.top)
            var newLeft = currentPos.first + dx.toInt()
            var newTop = currentPos.second + dy.toInt()
            newLeft = newLeft.coerceIn(0, width - view.width)
            newTop = newTop.coerceIn(0, height - view.height)
            mSubviewLeft = newLeft
            mSubviewTop = newTop
            view.requestLayout()
            onDragging?.invoke(view, newLeft.toFloat(), newTop.toFloat())
        }
    }

    private fun endDrag() {
        draggedView?.let { view ->
            applyEdgeAnimation(view)
            onDragEnd?.invoke(view)
        }
        isDragging = false
        draggedView = null
    }


    private fun applyEdgeAnimation(view: View) {
        val currentPos = Pair(view.left, view.top)
        val centerX = currentPos.first + view.width / 2

        val distToLeft = centerX
        val distToRight = width - centerX

        val finalLeft = if (distToLeft < distToRight) {
            0 // 贴左边
        } else {
            width - view.width // 贴右边
        }

        val finalTop = currentPos.second.coerceIn(0, height - view.height)

        view.animate()
            .x(finalLeft.toFloat())
            .y(finalTop.toFloat())
            .setDuration(300)
            .withEndAction {
                view.translationX = 0F
                mSubviewLeft = finalLeft.toInt()
                mSubviewTop = finalTop.toInt()
                view.requestLayout()
            }
            .start()
    }


    override fun onMeasure(widthMeasureSpec: Int, heightMeasureSpec: Int) {
        val child = getChildAt(0)
        measureChild(child, widthMeasureSpec, heightMeasureSpec)

        val widthSize = MeasureSpec.getSize(widthMeasureSpec)
        val heightSize = MeasureSpec.getSize(heightMeasureSpec)
        setMeasuredDimension(widthSize, heightSize)
    }

    override fun onLayout(changed: Boolean, l: Int, t: Int, r: Int, b: Int) {
        if (childCount == 0) return

        val child = getChildAt(0)
        val childWidth = child.measuredWidth
        val childHeight = child.measuredHeight

        child.layout(mSubviewLeft, mSubviewTop, mSubviewLeft + childWidth, mSubviewTop + childHeight)
    }



    private fun findChildUnder(x: Int, y: Int): View? {
        val child = getChildAt(0)
        if (x >= child.left  && x < child.right  &&
            y >= child.top && y < child.bottom) {
            return child
        }
        return null
    }



    /**
     * 贴边阈值
     */
    fun setEdgeThreshold(dp: Float) {
        edgeThreshold = dp.dp
    }


    fun isDragging(): Boolean = isDragging

}




