package com.gh.ndownload.suspendwindow.view

import android.annotation.SuppressLint
import android.content.Context
import android.util.AttributeSet
import android.util.TypedValue
import android.view.MotionEvent
import android.view.View
import android.view.ViewConfiguration
import android.widget.FrameLayout
import kotlin.math.abs

class NDownloadSuspendIconLayout @JvmOverloads constructor(
    context: Context,
    attrs: AttributeSet? = null,
    defStyle: Int = 0
) : FrameLayout(context, attrs, defStyle) {

    private var touchX: Float = 0F

    private var touchY: Float = 0F

    private var isDragging = false

    private val touchSlop: Int by lazy {
        ViewConfiguration.get(context).scaledTouchSlop
    }

    private var onDragCallback: OnDragCallback? = null

    val icon = NDownloadSuspendIconView(context).also {
        it.clipChildren = false
        it.clipToPadding = false
        val size = TypedValue.applyDimension(
            TypedValue.COMPLEX_UNIT_DIP,
            40F,
            context.resources.displayMetrics
        ).toInt()
        addView(it, LayoutParams(size, size))
    }

    fun setOnDragCallback(onDragCallback: OnDragCallback?) {
        this.onDragCallback = onDragCallback
    }

    override fun onInterceptTouchEvent(ev: MotionEvent): Boolean {
        val onDragCallback = this.onDragCallback
            ?: return super.onInterceptTouchEvent(ev)

        if (ev.action == MotionEvent.ACTION_DOWN) {
            isDragging = false
            touchX = ev.rawX
            touchY = ev.rawY
            return super.onInterceptTouchEvent(ev)
        }

        if (isDragging && ev.action == MotionEvent.ACTION_MOVE) {
            return true
        }

        if (ev.action == MotionEvent.ACTION_MOVE) {
            val rawX = ev.rawX
            val rawY = ev.rawY
            val xDiff = abs(rawX - touchX)
            val yDiff = abs(rawY - touchY)
            val dragging = xDiff > touchSlop || yDiff > touchSlop
            if (dragging) {
                isDragging = true
                onDragCallback.onDragStart(this)
                return true
            }
            return super.onInterceptTouchEvent(ev)
        }

        if (isDragging && ev.action == MotionEvent.ACTION_UP) {
            return true
        }

        return super.onInterceptTouchEvent(ev)
    }

    @SuppressLint("ClickableViewAccessibility")
    override fun onTouchEvent(ev: MotionEvent): Boolean {
        val onDragListener = this.onDragCallback
            ?: return super.onInterceptTouchEvent(ev)

        when(ev.action) {
            MotionEvent.ACTION_DOWN -> onDragListener.onDragStart(this)
            MotionEvent.ACTION_MOVE -> onDragListener.onDragMove(this, ev.rawX, ev.rawY)
            MotionEvent.ACTION_UP -> onDragListener.onDragEnd(this, ev.rawX, ev.rawY)
        }

        return super.onTouchEvent(ev)
    }

    interface OnDragCallback {

        fun onDragStart(v: View)

        fun onDragMove(v: View, x: Float, y: Float)

        fun onDragEnd(v: View,  x: Float, y: Float)
    }
}