package com.ama.core.common.widget


import android.content.Context
import android.util.AttributeSet
import android.view.MotionEvent
import android.view.GestureDetector
import android.widget.LinearLayout
import androidx.core.view.GestureDetectorCompat

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

    private var isDragging = false
    private var lastX = 0f
    private var lastY = 0f
    private var originalX = 0f
    private var originalY = 0f

    private val gestureDetector: GestureDetectorCompat

    // feature enable flags
    private var enableBoundaryLimit = true
    private var enableMagneticEffect = true
    private var magneticSensitivity = 100f


    var onDragListener: OnDragListener? = null
    interface OnDragListener {
        fun onDragStart(view: DragIconView)
        fun onDragging(view: DragIconView, x: Float, y: Float)
        fun onDragEnd(view: DragIconView)
    }


    init {

        isClickable = true
        isLongClickable = true
        gestureDetector = GestureDetectorCompat(context, object : GestureDetector.SimpleOnGestureListener() {
            override fun onLongPress(e: MotionEvent) {
                startDrag(e)
            }
        })

        post {
            originalX = x
            originalY = y
        }
    }

    override fun onInterceptTouchEvent(event: MotionEvent): Boolean {
        gestureDetector.onTouchEvent(event)
        return isDragging || super.onInterceptTouchEvent(event)
    }

    override fun onTouchEvent(event: MotionEvent): Boolean {
        gestureDetector.onTouchEvent(event)

        when (event.action and MotionEvent.ACTION_MASK) {
            MotionEvent.ACTION_DOWN -> {
                lastX = event.rawX
                lastY = event.rawY
                return true
            }

            MotionEvent.ACTION_MOVE -> {
                if (isDragging) {
                    val deltaX = event.rawX - lastX
                    val deltaY = event.rawY - lastY

                    x += deltaX
                    y += deltaY
                    lastX = event.rawX
                    lastY = event.rawY

                    onDragListener?.onDragging(this, x, y)
                    return true
                }
            }

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

        return super.onTouchEvent(event)
    }

    private fun startDrag(event: MotionEvent) {
        isDragging = true
        parent?.requestDisallowInterceptTouchEvent(true)
        alpha = 0.8f

        onDragListener?.onDragStart(this)
    }

    private fun endDrag() {
        isDragging = false
        parent?.requestDisallowInterceptTouchEvent(false)
        alpha = 1.0f

        if (enableBoundaryLimit) {
            ensureWithinBoundary()
        }

        if (enableMagneticEffect) {
            applyMagneticEffect()
        }

        onDragListener?.onDragEnd(this)
    }






    // ============ public methods ============

    /**
     * 开启或关闭边界限制功能
     */
    fun setBoundaryLimitEnabled(enabled: Boolean) {
        enableBoundaryLimit = enabled
    }

    /**
     * 开启或关闭贴边吸附功能
     */
    fun setMagneticEffectEnabled(enabled: Boolean) {
        enableMagneticEffect = enabled
    }

    /**
     * 设置贴边吸附敏感度
     */
    fun setMagneticSensitivity(sensitivity: Float) {
        magneticSensitivity = sensitivity
    }


    data class DragFeatures(
        val boundaryLimit: Boolean,
        val magneticEffect: Boolean,
        val sensitivity: Float
    )

    fun resetPosition() {
        x = originalX
        y = originalY
    }

    fun setPosition(newX: Float, newY: Float) {
        x = newX
        y = newY
    }


    fun getCurrentPosition(): Pair<Float, Float> = Pair(x, y)

    fun isDragging(): Boolean = isDragging


    fun getOriginalPosition(): Pair<Float, Float> = Pair(originalX, originalY)







    // ============ 私有功能方法 ============
    /**
     * 边界限制：确保 View 不会超出屏幕边界
     */
    private fun ensureWithinBoundary() {
        val screenWidth = resources.displayMetrics.widthPixels
        val screenHeight = resources.displayMetrics.heightPixels

        var newX = x
        var newY = y

        if (x < 0) newX = 0f
        if (y < 0) newY = 0f
        if (x + width > screenWidth) newX = (screenWidth - width).toFloat()
        if (y + height > screenHeight) newY = (screenHeight - height).toFloat()

        if (newX != x || newY != y) {
            animate().x(newX).y(newY).setDuration(150).start()
        }
    }

    /**
     * 贴边吸附效果：拖动结束后自动吸附到最近的屏幕边缘
     */
    private fun applyMagneticEffect() {
        val screenWidth = resources.displayMetrics.widthPixels.toFloat()
        val screenHeight = resources.displayMetrics.heightPixels.toFloat()

        val centerX = x + width / 2
        val centerY = y + height / 2

        var targetX = x
        var targetY = y


        val distanceToLeft = centerX
        val distanceToRight = screenWidth - centerX

        when {
            distanceToLeft <= magneticSensitivity -> {
                targetX = 0f
            }
            distanceToRight <= magneticSensitivity -> {
                targetX = screenWidth - width
            }
        }

        if (targetX != x || targetY != y) {
            animate().x(targetX).y(targetY).setDuration(200).start()
        }
    }
}










