/*
 * Copyright (C) 2020 The Android Open Source Project
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
package com.android.systemui.util.magnetictarget

import android.annotation.SuppressLint
import android.content.Context
import android.database.ContentObserver
import android.graphics.PointF
import android.os.Handler
import android.os.UserHandle
import android.os.VibrationEffect
import android.os.Vibrator
import android.provider.Settings
import android.view.MotionEvent
import android.view.VelocityTracker
import android.view.View
import android.view.ViewConfiguration
import androidx.dynamicanimation.animation.DynamicAnimation
import androidx.dynamicanimation.animation.FloatPropertyCompat
import androidx.dynamicanimation.animation.SpringForce
import com.android.systemui.util.animation.PhysicsAnimator
import kotlin.math.hypot

/**
 * Utility class for creating 'magnetized' objects that are attracted to one or more magnetic
 * targets. Magnetic targets attract objects that are dragged near them, and hold them there unless
 * they're moved away or released. Releasing objects inside a magnetic target typically performs an
 * action on the object.
 *
 * MagnetizedObject also supports flinging to targets, which will result in the object being pulled
 * into the target and released as if it was dragged into it.
 *
 * To use this class, either construct an instance with an object of arbitrary type, or use the
 * [MagnetizedObject.magnetizeView] shortcut method if you're magnetizing a view. Then, set
 * [magnetListener] to receive event callbacks. In your touch handler, pass all MotionEvents
 * that move this object to [maybeConsumeMotionEvent]. If that method returns true, consider the
 * event consumed by the MagnetizedObject and don't move the object unless it begins returning false
 * again.
 *
 * @param context Context, used to retrieve a Vibrator instance for vibration effects.
 * @param underlyingObject The actual object that we're magnetizing.
 * @param xProperty Property that sets the x value of the object's position.
 * @param yProperty Property that sets the y value of the object's position.
 */
abstract class MagnetizedObject<T : Any>(
    val context: Context,

    /** The actual object that is animated. */
    val underlyingObject: T,

    /** Property that gets/sets the object's X value. */
    val xProperty: FloatPropertyCompat<in T>,

    /** Property that gets/sets the object's Y value. */
    val yProperty: FloatPropertyCompat<in T>
) {

    /** Return the width of the object. */
    abstract fun getWidth(underlyingObject: T): Float

    /** Return the height of the object. */
    abstract fun getHeight(underlyingObject: T): Float

    /**
     * Fill the provided array with the location of the top-left of the object, relative to the
     * entire screen. Compare to [View.getLocationOnScreen].
     */
    abstract fun getLocationOnScreen(underlyingObject: T, loc: IntArray)

    /** Methods for listening to events involving a magnetized object.  */
    interface MagnetListener {

        /**
         * Called when touch events move within the magnetic field of a target, causing the
         * object to animate to the target and become 'stuck' there. The animation happens
         * automatically here - you should not move the object. You can, however, change its state
         * to indicate to the user that it's inside the target and releasing it will have an effect.
         *
         * [maybeConsumeMotionEvent] is now returning true and will continue to do so until a call
         * to [onUnstuckFromTarget] or [onReleasedInTarget].
         *
         * @param target The target that the object is now stuck to.
         */
        fun onStuckToTarget(target: MagneticTarget)

        /**
         * Called when the object is no longer stuck to a target. This means that either touch
         * events moved outside of the magnetic field radius, or that a forceful fling out of the
         * target was detected.
         *
         * The object won't be automatically animated out of the target, since you're responsible
         * for moving the object again. You should move it (or animate it) using your own
         * movement/animation logic.
         *
         * Reverse any effects applied in [onStuckToTarget] here.
         *
         * If [wasFlungOut] is true, [maybeConsumeMotionEvent] returned true for the ACTION_UP event
         * that concluded the fling. If [wasFlungOut] is false, that means a drag gesture is ongoing
         * and [maybeConsumeMotionEvent] is now returning false.
         *
         * @param target The target that this object was just unstuck from.
         * @param velX The X velocity of the touch gesture when it exited the magnetic field.
         * @param velY The Y velocity of the touch gesture when it exited the magnetic field.
         * @param wasFlungOut Whether the object was unstuck via a fling gesture. This means that
         * an ACTION_UP event was received, and that the gesture velocity was sufficient to conclude
         * that the user wants to un-stick the object despite no touch events occurring outside of
         * the magnetic field radius.
         */
        fun onUnstuckFromTarget(
            target: MagneticTarget,
            velX: Float,
            velY: Float,
            wasFlungOut: Boolean
        )

        /**
         * Called when the object is released inside a target, or flung towards it with enough
         * velocity to reach it.
         *
         * @param target The target that the object was released in.
         */
        fun onReleasedInTarget(target: MagneticTarget)
    }

    private val animator: PhysicsAnimator<T> = PhysicsAnimator.getInstance(underlyingObject)
    private val objectLocationOnScreen = IntArray(2)

    /**
     * Targets that have been added to this object. These will all be considered when determining
     * magnetic fields and fling trajectories.
     */
    private val associatedTargets = ArrayList<MagneticTarget>()

    private val velocityTracker: VelocityTracker = VelocityTracker.obtain()
    private val vibrator: Vibrator = context.getSystemService(Context.VIBRATOR_SERVICE) as Vibrator

    private var touchDown = PointF()
    private var touchSlop = 0
    private var movedBeyondSlop = false

    /** Whether touch events are presently occurring within the magnetic field area of a target. */
    val objectStuckToTarget: Boolean
        get() = targetObjectIsStuckTo != null

    /** The target the object is stuck to, or null if the object is not stuck to any target. */
    private var targetObjectIsStuckTo: MagneticTarget? = null

    /**
     * Sets the listener to receive events. This must be set, or [maybeConsumeMotionEvent]
     * will always return false and no magnetic effects will occur.
     */
    lateinit var magnetListener: MagnetizedObject.MagnetListener

    /**
     * Optional update listener to provide to the PhysicsAnimator that is used to spring the object
     * into the target.
     */
    var physicsAnimatorUpdateListener: PhysicsAnimator.UpdateListener<T>? = null

    /**
     * Optional end listener to provide to the PhysicsAnimator that is used to spring the object
     * into the target.
     */
    var physicsAnimatorEndListener: PhysicsAnimator.EndListener<T>? = null

    /**
     * Sets whether forcefully flinging the object vertically towards a target causes it to be
     * attracted to the target and then released immediately, despite never being dragged within the
     * magnetic field.
     */
    var flingToTargetEnabled = true

    /**
     * If fling to target is enabled, forcefully flinging the object towards a target will cause
     * it to be attracted to the target and then released immediately, despite never being dragged
     * within the magnetic field.
     *
     * This sets the width of the area considered 'near' enough a target to be considered a fling,
     * in terms of percent of the target view's width. For example, setting this to 3f means that
     * flings towards a 100px-wide target will be considered 'near' enough if they're towards the
     * 300px-wide area around the target.
     *
     * Flings whose trajectory intersects the area will be attracted and released - even if the
     * target view itself isn't intersected:
     *
     * |             |
     * |           0 |
     * |          /  |
     * |         /   |
     * |      X /    |
     * |.....###.....|
     *
     *
     * Flings towards the target whose trajectories do not intersect the area will be treated as
     * normal flings and the magnet will leave the object alone:
     *
     * |             |
     * |             |
     * |   0         |
     * |  /          |
     * | /    X      |
     * |.....###.....|
     *
     */
    var flingToTargetWidthPercent = 3f

    /**
     * Sets the minimum velocity (in pixels per second) required to fling an object to the target
     * without dragging it into the magnetic field.
     */
    var flingToTargetMinVelocity = 4000f

    /**
     * Sets the minimum velocity (in pixels per second) required to fling un-stuck an object stuck
     * to the target. If this velocity is reached, the object will be freed even if it wasn't moved
     * outside the magnetic field radius.
     */
    var flingUnstuckFromTargetMinVelocity = 1000f

    /**
     * Sets the maximum velocity above which the object will not stick to the target. Even if the
     * object is dragged through the magnetic field, it will not stick to the target until the
     * velocity is below this value.
     */
    var stickToTargetMaxVelocity = 2000f

    /**
     * Enable or disable haptic vibration effects when the object interacts with the magnetic field.
     *
     * If you're experiencing crashes when the object enters targets, ensure that you have the
     * android.permission.VIBRATE permission!
     */
    var hapticsEnabled = true

    /** Whether the HAPTIC_FEEDBACK_ENABLED setting is true. */
    private var systemHapticsEnabled = false

    /** Default spring configuration to use for animating the object into a target. */
    var springConfig = PhysicsAnimator.SpringConfig(
            SpringForce.STIFFNESS_MEDIUM, SpringForce.DAMPING_RATIO_NO_BOUNCY)

    /**
     * Spring configuration to use to spring the object into a target specifically when it's flung
     * towards (rather than dragged near) it.
     */
    var flungIntoTargetSpringConfig = springConfig

    init {
        val hapticSettingObserver =
                object : ContentObserver(Handler.getMain()) {
            override fun onChange(selfChange: Boolean) {
                systemHapticsEnabled =
                        Settings.System.getIntForUser(
                                context.contentResolver,
                                Settings.System.HAPTIC_FEEDBACK_ENABLED,
                                0,
                                UserHandle.USER_CURRENT) != 0
            }
        }

        context.contentResolver.registerContentObserver(
                Settings.System.getUriFor(Settings.System.HAPTIC_FEEDBACK_ENABLED),
                true /* notifyForDescendants */, hapticSettingObserver)

        // Trigger the observer once to initialize systemHapticsEnabled.
        hapticSettingObserver.onChange(false /* selfChange */)
    }

    /**
     * Adds the provided MagneticTarget to this object. The object will now be attracted to the
     * target if it strays within its magnetic field or is flung towards it.
     *
     * If this target (or its magnetic field) overlaps another target added to this object, the
     * prior target will take priority.
     */
    fun addTarget(target: MagneticTarget) {
        associatedTargets.add(target)
        target.updateLocationOnScreen()
    }

    /**
     * Shortcut that accepts a View and a magnetic field radius and adds it as a magnetic target.
     *
     * @return The MagneticTarget instance for the given View. This can be used to change the
     * target's magnetic field radius after it's been added. It can also be added to other
     * magnetized objects.
     */
    fun addTarget(target: View, magneticFieldRadiusPx: Int): MagneticTarget {
        return MagneticTarget(target, magneticFieldRadiusPx).also { addTarget(it) }
    }

    /**
     * Removes the given target from this object. The target will no longer attract the object.
     */
    fun removeTarget(target: MagneticTarget) {
        associatedTargets.remove(target)
    }

    /**
     * Provide this method with all motion events that move the magnetized object. If the
     * location of the motion events moves within the magnetic field of a target, or indicate a
     * fling-to-target gesture, this method will return true and you should not move the object
     * yourself until it returns false again.
     *
     * Note that even when this method returns true, you should continue to pass along new motion
     * events so that we know when the events move back outside the magnetic field area.
     *
     * This method will always return false if you haven't set a [magnetListener].
     */
    fun maybeConsumeMotionEvent(ev: MotionEvent): Boolean {
        // Short-circuit if we don't have a listener or any targets, since those are required.
        if (associatedTargets.size == 0) {
            return false
        }

        // When a gesture begins, recalculate target views' positions on the screen in case they
        // have changed. Also, clear state.
        if (ev.action == MotionEvent.ACTION_DOWN) {
            updateTargetViews()

            // Clear the velocity tracker and stuck target.
            velocityTracker.clear()
            targetObjectIsStuckTo = null

            // Set the touch down coordinates and reset movedBeyondSlop.
            touchDown.set(ev.rawX, ev.rawY)
            movedBeyondSlop = false
        }

        // Always pass events to the VelocityTracker.
        addMovement(ev)

        // If we haven't yet moved beyond the slop distance, check if we have.
        if (!movedBeyondSlop) {
            val dragDistance = hypot(ev.rawX - touchDown.x, ev.rawY - touchDown.y)
            if (dragDistance > touchSlop) {
                // If we're beyond the slop distance, save that and continue.
                movedBeyondSlop = true
            } else {
                // Otherwise, don't do anything yet.
                return false
            }
        }

        val targetObjectIsInMagneticFieldOf = associatedTargets.firstOrNull { target ->
            val distanceFromTargetCenter = hypot(
                    ev.rawX - target.centerOnScreen.x,
                    ev.rawY - target.centerOnScreen.y)
            distanceFromTargetCenter < target.magneticFieldRadiusPx
        }

        // If we aren't currently stuck to a target, and we're in the magnetic field of a target,
        // we're newly stuck.
        val objectNewlyStuckToTarget =
                !objectStuckToTarget && targetObjectIsInMagneticFieldOf != null

        // If we are currently stuck to a target, we're in the magnetic field of a target, and that
        // target isn't the one we're currently stuck to, then touch events have moved into a
        // adjacent target's magnetic field.
        val objectMovedIntoDifferentTarget =
                objectStuckToTarget &&
                        targetObjectIsInMagneticFieldOf != null &&
                        targetObjectIsStuckTo != targetObjectIsInMagneticFieldOf

        if (objectNewlyStuckToTarget || objectMovedIntoDifferentTarget) {
            velocityTracker.computeCurrentVelocity(1000)
            val velX = velocityTracker.xVelocity
            val velY = velocityTracker.yVelocity

            // If the object is moving too quickly within the magnetic field, do not stick it. This
            // only applies to objects newly stuck to a target. If the object is moved into a new
            // target, it wasn't moving at all (since it was stuck to the previous one).
            if (objectNewlyStuckToTarget && hypot(velX, velY) > stickToTargetMaxVelocity) {
                return false
            }

            // This touch event is newly within the magnetic field - let the listener know, and
            // animate sticking to the magnet.
            targetObjectIsStuckTo = targetObjectIsInMagneticFieldOf
            cancelAnimations()
            magnetListener.onStuckToTarget(targetObjectIsInMagneticFieldOf!!)
            animateStuckToTarget(targetObjectIsInMagneticFieldOf, velX, velY, false)

            vibrateIfEnabled(VibrationEffect.EFFECT_HEAVY_CLICK)
        } else if (targetObjectIsInMagneticFieldOf == null && objectStuckToTarget) {
            velocityTracker.computeCurrentVelocity(1000)

            // This touch event is newly outside the magnetic field - let the listener know. It will
            // move the object out of the target using its own movement logic.
            cancelAnimations()
            magnetListener.onUnstuckFromTarget(
                    targetObjectIsStuckTo!!, velocityTracker.xVelocity, velocityTracker.yVelocity,
                    wasFlungOut = false)
            targetObjectIsStuckTo = null

            vibrateIfEnabled(VibrationEffect.EFFECT_TICK)
        }

        // First, check for relevant gestures concluding with an ACTION_UP.
        if (ev.action == MotionEvent.ACTION_UP) {

            velocityTracker.computeCurrentVelocity(1000 /* units */)
            val velX = velocityTracker.xVelocity
            val velY = velocityTracker.yVelocity

            // Cancel the magnetic animation since we might still be springing into the magnetic
            // target, but we're about to fling away or release.
            cancelAnimations()

            if (objectStuckToTarget) {
                if (hypot(velX, velY) > flingUnstuckFromTargetMinVelocity) {
                    // If the object is stuck, but it was forcefully flung away from the target,
                    // tell the listener so the object can be animated out of the target.
                    magnetListener.onUnstuckFromTarget(
                            targetObjectIsStuckTo!!, velX, velY, wasFlungOut = true)
                } else {
                    // If the object is stuck and not flung away, it was released inside the target.
                    magnetListener.onReleasedInTarget(targetObjectIsStuckTo!!)
                    vibrateIfEnabled(VibrationEffect.EFFECT_HEAVY_CLICK)
                }

                // Either way, we're no longer stuck.
                targetObjectIsStuckTo = null
                return true
            }

            // The target we're flinging towards, or null if we're not flinging towards any target.
            val flungToTarget = associatedTargets.firstOrNull { target ->
                isForcefulFlingTowardsTarget(target, ev.rawX, ev.rawY, velX, velY)
            }

            if (flungToTarget != null) {
                // If this is a fling-to-target, animate the object to the magnet and then release
                // it.
                magnetListener.onStuckToTarget(flungToTarget)
                targetObjectIsStuckTo = flungToTarget

                animateStuckToTarget(flungToTarget, velX, velY, true) {
                    targetObjectIsStuckTo = null
                    magnetListener.onReleasedInTarget(flungToTarget)
                    vibrateIfEnabled(VibrationEffect.EFFECT_HEAVY_CLICK)
                }

                return true
            }

            // If it's not either of those things, we are not interested.
            return false
        }

        return objectStuckToTarget // Always consume touch events if the object is stuck.
    }

    /** Plays the given vibration effect if haptics are enabled. */
    @SuppressLint("MissingPermission")
    private fun vibrateIfEnabled(effect: Int) {
        if (hapticsEnabled && systemHapticsEnabled) {
            vibrator.vibrate(effect.toLong())
        }
    }

    /** Adds the movement to the velocity tracker using raw coordinates. */
    private fun addMovement(event: MotionEvent) {
        // Add movement to velocity tracker using raw screen X and Y coordinates instead
        // of window coordinates because the window frame may be moving at the same time.
        val deltaX = event.rawX - event.x
        val deltaY = event.rawY - event.y
        event.offsetLocation(deltaX, deltaY)
        velocityTracker.addMovement(event)
        event.offsetLocation(-deltaX, -deltaY)
    }

    /** Animates sticking the object to the provided target with the given start velocities.  */
    private fun animateStuckToTarget(
        target: MagneticTarget,
        velX: Float,
        velY: Float,
        flung: Boolean,
        after: (() -> Unit)? = null
    ) {
        target.updateLocationOnScreen()
        getLocationOnScreen(underlyingObject, objectLocationOnScreen)

        // Calculate the difference between the target's center coordinates and the object's.
        // Animating the object's x/y properties by these values will center the object on top
        // of the magnetic target.
        val xDiff = target.centerOnScreen.x -
                getWidth(underlyingObject) / 2f - objectLocationOnScreen[0]
        val yDiff = target.centerOnScreen.y -
                getHeight(underlyingObject) / 2f - objectLocationOnScreen[1]

        val springConfig = if (flung) flungIntoTargetSpringConfig else springConfig

        cancelAnimations()

        // Animate to the center of the target.
        animator
                .spring(xProperty, xProperty.getValue(underlyingObject) + xDiff, velX,
                        springConfig)
                .spring(yProperty, yProperty.getValue(underlyingObject) + yDiff, velY,
                        springConfig)

        if (physicsAnimatorUpdateListener != null) {
            animator.addUpdateListener(physicsAnimatorUpdateListener!!)
        }

        if (physicsAnimatorEndListener != null) {
            animator.addEndListener(physicsAnimatorEndListener!!)
        }

        if (after != null) {
            animator.withEndActions(after)
        }

        animator.start()
    }

    /**
     * Whether or not the provided values match a 'fast fling' towards the provided target. If it
     * does, we consider it a fling-to-target gesture.
     */
    private fun isForcefulFlingTowardsTarget(
        target: MagneticTarget,
        rawX: Float,
        rawY: Float,
        velX: Float,
        velY: Float
    ): Boolean {
        if (!flingToTargetEnabled) {
            return false
        }

        // Whether velocity is sufficient, depending on whether we're flinging into a target at the
        // top or the bottom of the screen.
        val velocitySufficient =
                if (rawY < target.centerOnScreen.y) velY > flingToTargetMinVelocity
                else velY < flingToTargetMinVelocity

        if (!velocitySufficient) {
            return false
        }

        // Whether the trajectory of the fling intersects the target area.
        var targetCenterXIntercept = rawX

        // Only do math if the X velocity is non-zero, otherwise X won't change.
        if (velX != 0f) {
            // Rise over run...
            val slope = velY / velX
            // ...y = mx + b, b = y / mx...
            val yIntercept = rawY - slope * rawX

            // ...calculate the x value when y = the target's y-coordinate.
            targetCenterXIntercept = (target.centerOnScreen.y - yIntercept) / slope
        }

        // The width of the area we're looking for a fling towards.
        val targetAreaWidth = target.targetView.width * flingToTargetWidthPercent

        // Velocity was sufficient, so return true if the intercept is within the target area.
        return targetCenterXIntercept > target.centerOnScreen.x - targetAreaWidth / 2 &&
                targetCenterXIntercept < target.centerOnScreen.x + targetAreaWidth / 2
    }

    /** Cancel animations on this object's x/y properties. */
    internal fun cancelAnimations() {
        animator.cancel(xProperty, yProperty)
    }

    /** Updates the locations on screen of all of the [associatedTargets]. */
    internal fun updateTargetViews() {
        associatedTargets.forEach { it.updateLocationOnScreen() }

        // Update the touch slop, since the configuration may have changed.
        if (associatedTargets.size > 0) {
            touchSlop =
                    ViewConfiguration.get(associatedTargets[0].targetView.context).scaledTouchSlop
        }
    }

    /**
     * Represents a target view with a magnetic field radius and cached center-on-screen
     * coordinates.
     *
     * Instances of MagneticTarget are passed to a MagnetizedObject's [addTarget], and can then
     * attract the object if it's dragged near or flung towards it. MagneticTargets can be added to
     * multiple objects.
     */
    class MagneticTarget(
        internal val targetView: View,
        var magneticFieldRadiusPx: Int
    ) {
        internal val centerOnScreen = PointF()

        private val tempLoc = IntArray(2)

        fun updateLocationOnScreen() {
            targetView.post {
                targetView.getLocationOnScreen(tempLoc)

                // Add half of the target size to get the center, and subtract translation since the
                // target could be animating in while we're doing this calculation.
                centerOnScreen.set(
                        tempLoc[0] + targetView.width / 2f - targetView.translationX,
                        tempLoc[1] + targetView.height / 2f - targetView.translationY)
            }
        }
    }

    companion object {

        /**
         * Magnetizes the given view. Magnetized views are attracted to one or more magnetic
         * targets. Magnetic targets attract objects that are dragged near them, and hold them there
         * unless they're moved away or released. Releasing objects inside a magnetic target
         * typically performs an action on the object.
         *
         * Magnetized views can also be flung to targets, which will result in the view being pulled
         * into the target and released as if it was dragged into it.
         *
         * To use the returned MagnetizedObject<View> instance, first set [magnetListener] to
         * receive event callbacks. In your touch handler, pass all MotionEvents that move this view
         * to [maybeConsumeMotionEvent]. If that method returns true, consider the event consumed by
         * MagnetizedObject and don't move the view unless it begins returning false again.
         *
         * The view will be moved via translationX/Y properties, and its
         * width/height will be determined via getWidth()/getHeight(). If you are animating
         * something other than a view, or want to position your view using properties other than
         * translationX/Y, implement an instance of [MagnetizedObject].
         *
         * Note that the magnetic library can't re-order your view automatically. If the view
         * renders on top of the target views, it will obscure the target when it sticks to it.
         * You'll want to bring the view to the front in [MagnetListener.onStuckToTarget].
         */
        @JvmStatic
        fun <T : View> magnetizeView(view: T): MagnetizedObject<T> {
            return object : MagnetizedObject<T>(
                    view.context,
                    view,
                    DynamicAnimation.TRANSLATION_X,
                    DynamicAnimation.TRANSLATION_Y) {
                override fun getWidth(underlyingObject: T): Float {
                    return underlyingObject.width.toFloat()
                }

                override fun getHeight(underlyingObject: T): Float {
                    return underlyingObject.height.toFloat() }

                override fun getLocationOnScreen(underlyingObject: T, loc: IntArray) {
                    underlyingObject.getLocationOnScreen(loc)
                }
            }
        }
    }
}