/*
 * 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.media

import android.graphics.Outline
import android.util.MathUtils
import android.view.GestureDetector
import android.view.MotionEvent
import android.view.View
import android.view.ViewGroup
import android.view.ViewOutlineProvider
import androidx.core.view.GestureDetectorCompat
import androidx.dynamicanimation.animation.FloatPropertyCompat
import androidx.dynamicanimation.animation.SpringForce
import com.android.settingslib.Utils
import com.android.systemui.Gefingerpoken
import com.android.systemui.qs.PageIndicator
import com.android.systemui.R
import com.android.systemui.plugins.FalsingManager
import com.android.systemui.util.animation.PhysicsAnimator
import com.android.systemui.util.concurrency.DelayableExecutor

private const val FLING_SLOP = 1000000
private const val DISMISS_DELAY = 100L
private const val RUBBERBAND_FACTOR = 0.2f
private const val SETTINGS_BUTTON_TRANSLATION_FRACTION = 0.3f

/**
 * Default spring configuration to use for animations where stiffness and/or damping ratio
 * were not provided, and a default spring was not set via [PhysicsAnimator.setDefaultSpringConfig].
 */
private val translationConfig = PhysicsAnimator.SpringConfig(
        SpringForce.STIFFNESS_MEDIUM,
        SpringForce.DAMPING_RATIO_LOW_BOUNCY)

/**
 * A controller class for the media scrollview, responsible for touch handling
 */
class MediaCarouselScrollHandler(
    private val scrollView: MediaScrollView,
    private val pageIndicator: PageIndicator,
    private val mainExecutor: DelayableExecutor,
    private val dismissCallback: () -> Unit,
    private var translationChangedListener: () -> Unit,
    private val closeGuts: () -> Unit,
    private val falsingManager: FalsingManager
) {
    /**
     * Is the view in RTL
     */
    val isRtl: Boolean get() = scrollView.isLayoutRtl
    /**
     * Do we need falsing protection?
     */
    var falsingProtectionNeeded: Boolean = false
    /**
     * The width of the carousel
     */
    private var carouselWidth: Int = 0

    /**
     * The height of the carousel
     */
    private var carouselHeight: Int = 0

    /**
     * How much are we scrolled into the current media?
     */
    private var cornerRadius: Int = 0

    /**
     * The content where the players are added
     */
    private var mediaContent: ViewGroup
    /**
     * The gesture detector to detect touch gestures
     */
    private val gestureDetector: GestureDetectorCompat

    /**
     * The settings button view
     */
    private lateinit var settingsButton: View

    /**
     * What's the currently active player index?
     */
    var activeMediaIndex: Int = 0
        private set
    /**
     * How much are we scrolled into the current media?
     */
    private var scrollIntoCurrentMedia: Int = 0

    /**
     * how much is the content translated in X
     */
    var contentTranslation = 0.0f
        private set(value) {
            field = value
            mediaContent.translationX = value
            updateSettingsPresentation()
            translationChangedListener.invoke()
            updateClipToOutline()
        }

    /**
     * The width of a player including padding
     */
    var playerWidthPlusPadding: Int = 0
        set(value) {
            field = value
            // The player width has changed, let's update the scroll position to make sure
            // it's still at the same place
            var newRelativeScroll = activeMediaIndex * playerWidthPlusPadding
            if (scrollIntoCurrentMedia > playerWidthPlusPadding) {
                newRelativeScroll += playerWidthPlusPadding -
                        (scrollIntoCurrentMedia - playerWidthPlusPadding)
            } else {
                newRelativeScroll += scrollIntoCurrentMedia
            }
            scrollView.relativeScrollX = newRelativeScroll
        }

    /**
     * Does the dismiss currently show the setting cog?
     */
    var showsSettingsButton: Boolean = false

    /**
     * A utility to detect gestures, used in the touch listener
     */
    private val gestureListener = object : GestureDetector.SimpleOnGestureListener() {
        override fun onFling(
            eStart: MotionEvent?,
            eCurrent: MotionEvent?,
            vX: Float,
            vY: Float
        ) = onFling(vX, vY)

        override fun onScroll(
            down: MotionEvent?,
            lastMotion: MotionEvent?,
            distanceX: Float,
            distanceY: Float
        ) = onScroll(down!!, lastMotion!!, distanceX)

        override fun onDown(e: MotionEvent?): Boolean {
            if (falsingProtectionNeeded) {
                falsingManager.onNotificationStartDismissing()
            }
            return false
        }
    }

    /**
     * The touch listener for the scroll view
     */
    private val touchListener = object : Gefingerpoken {
        override fun onTouchEvent(motionEvent: MotionEvent?) = onTouch(motionEvent!!)
        override fun onInterceptTouchEvent(ev: MotionEvent?) = onInterceptTouch(ev!!)
    }

    /**
     * A listener that is invoked when the scrolling changes to update player visibilities
     */
    private val scrollChangedListener = object : View.OnScrollChangeListener {
        override fun onScrollChange(
            v: View?,
            scrollX: Int,
            scrollY: Int,
            oldScrollX: Int,
            oldScrollY: Int
        ) {
            if (playerWidthPlusPadding == 0) {
                return
            }
            val relativeScrollX = scrollView.relativeScrollX
            onMediaScrollingChanged(relativeScrollX / playerWidthPlusPadding,
                    relativeScrollX % playerWidthPlusPadding)
        }
    }

    init {
        gestureDetector = GestureDetectorCompat(scrollView.context, gestureListener)
        scrollView.touchListener = touchListener
        scrollView.setOverScrollMode(View.OVER_SCROLL_NEVER)
        mediaContent = scrollView.contentContainer
        scrollView.setOnScrollChangeListener(scrollChangedListener)
        scrollView.outlineProvider = object : ViewOutlineProvider() {
            override fun getOutline(view: View?, outline: Outline?) {
                outline?.setRoundRect(0, 0, carouselWidth, carouselHeight, cornerRadius.toFloat())
            }
        }
    }

    fun onSettingsButtonUpdated(button: View) {
        settingsButton = button
        // We don't have a context to resolve, lets use the settingsbuttons one since that is
        // reinflated appropriately
        cornerRadius = settingsButton.resources.getDimensionPixelSize(
                Utils.getThemeAttr(settingsButton.context, android.R.attr.dialogCornerRadius))
        updateSettingsPresentation()
        scrollView.invalidateOutline()
    }

    private fun updateSettingsPresentation() {
        if (showsSettingsButton) {
            val settingsOffset = MathUtils.map(
                    0.0f,
                    getMaxTranslation().toFloat(),
                    0.0f,
                    1.0f,
                    Math.abs(contentTranslation))
            val settingsTranslation = (1.0f - settingsOffset) * -settingsButton.width *
                    SETTINGS_BUTTON_TRANSLATION_FRACTION
            val newTranslationX = if (isRtl) {
                // In RTL, the 0-placement is on the right side of the view, not the left...
                if (contentTranslation > 0) {
                    -(scrollView.width - settingsTranslation - settingsButton.width)
                } else {
                    -settingsTranslation
                }
            } else {
                if (contentTranslation > 0) {
                    settingsTranslation
                } else {
                    scrollView.width - settingsTranslation - settingsButton.width
                }
            }
            val rotation = (1.0f - settingsOffset) * 50
            settingsButton.rotation = rotation * -Math.signum(contentTranslation)
            val alpha = MathUtils.saturate(MathUtils.map(0.5f, 1.0f, 0.0f, 1.0f, settingsOffset))
            settingsButton.alpha = alpha
            settingsButton.visibility = if (alpha != 0.0f) View.VISIBLE else View.INVISIBLE
            settingsButton.translationX = newTranslationX
            settingsButton.translationY = (scrollView.height - settingsButton.height) / 2.0f
        } else {
            settingsButton.visibility = View.INVISIBLE
        }
    }

    private fun onTouch(motionEvent: MotionEvent): Boolean {
        val isUp = motionEvent.action == MotionEvent.ACTION_UP
        if (isUp && falsingProtectionNeeded) {
            falsingManager.onNotificationStopDismissing()
        }
        if (gestureDetector.onTouchEvent(motionEvent)) {
            if (isUp) {
                // If this is an up and we're flinging, we don't want to have this touch reach
                // the view, otherwise that would scroll, while we are trying to snap to the
                // new page. Let's dispatch a cancel instead.
                scrollView.cancelCurrentScroll()
                return true
            } else {
                // Pass touches to the scrollView
                return false
            }
        }
        if (isUp || motionEvent.action == MotionEvent.ACTION_CANCEL) {
            // It's an up and the fling didn't take it above
            val relativePos = scrollView.relativeScrollX % playerWidthPlusPadding
            val scrollXAmount: Int
            if (relativePos > playerWidthPlusPadding / 2) {
                scrollXAmount = playerWidthPlusPadding - relativePos
            } else {
                scrollXAmount = -1 * relativePos
            }
            if (scrollXAmount != 0) {
                // Delay the scrolling since scrollView calls springback which cancels
                // the animation again..
                mainExecutor.execute {
                    scrollView.smoothScrollBy(if (isRtl) -scrollXAmount else scrollXAmount, 0)
                }
            }
            val currentTranslation = scrollView.getContentTranslation()
            if (currentTranslation != 0.0f) {
                // We started a Swipe but didn't end up with a fling. Let's either go to the
                // dismissed position or go back.
                val springBack = Math.abs(currentTranslation) < getMaxTranslation() / 2 ||
                        isFalseTouch()
                val newTranslation: Float
                if (springBack) {
                    newTranslation = 0.0f
                } else {
                    newTranslation = getMaxTranslation() * Math.signum(currentTranslation)
                    if (!showsSettingsButton) {
                        // Delay the dismiss a bit to avoid too much overlap. Waiting until the
                        // animation has finished also feels a bit too slow here.
                        mainExecutor.executeDelayed({
                            dismissCallback.invoke()
                        }, DISMISS_DELAY)
                    }
                }
                PhysicsAnimator.getInstance(this).spring(CONTENT_TRANSLATION,
                        newTranslation, startVelocity = 0.0f, config = translationConfig).start()
                scrollView.animationTargetX = newTranslation
            }
        }
        // Always pass touches to the scrollView
        return false
    }

    private fun isFalseTouch() = falsingProtectionNeeded && falsingManager.isFalseTouch

    private fun getMaxTranslation() = if (showsSettingsButton) {
            settingsButton.width
        } else {
            playerWidthPlusPadding
        }

    private fun onInterceptTouch(motionEvent: MotionEvent): Boolean {
        return gestureDetector.onTouchEvent(motionEvent)
    }

    fun onScroll(
        down: MotionEvent,
        lastMotion: MotionEvent,
        distanceX: Float
    ): Boolean {
        val totalX = lastMotion.x - down.x
        val currentTranslation = scrollView.getContentTranslation()
        if (currentTranslation != 0.0f ||
                !scrollView.canScrollHorizontally((-totalX).toInt())) {
            var newTranslation = currentTranslation - distanceX
            val absTranslation = Math.abs(newTranslation)
            if (absTranslation > getMaxTranslation()) {
                // Rubberband all translation above the maximum
                if (Math.signum(distanceX) != Math.signum(currentTranslation)) {
                    // The movement is in the same direction as our translation,
                    // Let's rubberband it.
                    if (Math.abs(currentTranslation) > getMaxTranslation()) {
                        // we were already overshooting before. Let's add the distance
                        // fully rubberbanded.
                        newTranslation = currentTranslation - distanceX * RUBBERBAND_FACTOR
                    } else {
                        // We just crossed the boundary, let's rubberband it all
                        newTranslation = Math.signum(newTranslation) * (getMaxTranslation() +
                                (absTranslation - getMaxTranslation()) * RUBBERBAND_FACTOR)
                    }
                } // Otherwise we don't have do do anything, and will remove the unrubberbanded
                // translation
            }
            if (Math.signum(newTranslation) != Math.signum(currentTranslation) &&
                    currentTranslation != 0.0f) {
                // We crossed the 0.0 threshold of the translation. Let's see if we're allowed
                // to scroll into the new direction
                if (scrollView.canScrollHorizontally(-newTranslation.toInt())) {
                    // We can actually scroll in the direction where we want to translate,
                    // Let's make sure to stop at 0
                    newTranslation = 0.0f
                }
            }
            val physicsAnimator = PhysicsAnimator.getInstance(this)
            if (physicsAnimator.isRunning()) {
                physicsAnimator.spring(CONTENT_TRANSLATION,
                        newTranslation, startVelocity = 0.0f, config = translationConfig).start()
            } else {
                contentTranslation = newTranslation
            }
            scrollView.animationTargetX = newTranslation
            return true
        }
        return false
    }

    private fun onFling(
        vX: Float,
        vY: Float
    ): Boolean {
        if (vX * vX < 0.5 * vY * vY) {
            return false
        }
        if (vX * vX < FLING_SLOP) {
            return false
        }
        val currentTranslation = scrollView.getContentTranslation()
        if (currentTranslation != 0.0f) {
            // We're translated and flung. Let's see if the fling is in the same direction
            val newTranslation: Float
            if (Math.signum(vX) != Math.signum(currentTranslation) || isFalseTouch()) {
                // The direction of the fling isn't the same as the translation, let's go to 0
                newTranslation = 0.0f
            } else {
                newTranslation = getMaxTranslation() * Math.signum(currentTranslation)
                // Delay the dismiss a bit to avoid too much overlap. Waiting until the animation
                // has finished also feels a bit too slow here.
                if (!showsSettingsButton) {
                    mainExecutor.executeDelayed({
                        dismissCallback.invoke()
                    }, DISMISS_DELAY)
                }
            }
            PhysicsAnimator.getInstance(this).spring(CONTENT_TRANSLATION,
                    newTranslation, startVelocity = vX, config = translationConfig).start()
            scrollView.animationTargetX = newTranslation
        } else {
            // We're flinging the player! Let's go either to the previous or to the next player
            val pos = scrollView.relativeScrollX
            val currentIndex = if (playerWidthPlusPadding > 0) pos / playerWidthPlusPadding else 0
            val flungTowardEnd = if (isRtl) vX > 0 else vX < 0
            var destIndex = if (flungTowardEnd) currentIndex + 1 else currentIndex
            destIndex = Math.max(0, destIndex)
            destIndex = Math.min(mediaContent.getChildCount() - 1, destIndex)
            val view = mediaContent.getChildAt(destIndex)
            // We need to post this since we're dispatching a touch to the underlying view to cancel
            // but canceling will actually abort the animation.
            mainExecutor.execute {
                scrollView.smoothScrollTo(view.left, scrollView.scrollY)
            }
        }
        return true
    }

    /**
     * Reset the translation of the players when swiped
     */
    fun resetTranslation(animate: Boolean = false) {
        if (scrollView.getContentTranslation() != 0.0f) {
            if (animate) {
                PhysicsAnimator.getInstance(this).spring(CONTENT_TRANSLATION,
                        0.0f, config = translationConfig).start()
                scrollView.animationTargetX = 0.0f
            } else {
                PhysicsAnimator.getInstance(this).cancel()
                contentTranslation = 0.0f
            }
        }
    }

    private fun updateClipToOutline() {
        val clip = contentTranslation != 0.0f || scrollIntoCurrentMedia != 0
        scrollView.clipToOutline = clip
    }

    private fun onMediaScrollingChanged(newIndex: Int, scrollInAmount: Int) {
        val wasScrolledIn = scrollIntoCurrentMedia != 0
        scrollIntoCurrentMedia = scrollInAmount
        val nowScrolledIn = scrollIntoCurrentMedia != 0
        if (newIndex != activeMediaIndex || wasScrolledIn != nowScrolledIn) {
            activeMediaIndex = newIndex
            closeGuts()
            updatePlayerVisibilities()
        }
        val relativeLocation = activeMediaIndex.toFloat() + if (playerWidthPlusPadding > 0)
            scrollInAmount.toFloat() / playerWidthPlusPadding else 0f
        // Fix the location, because PageIndicator does not handle RTL internally
        val location = if (isRtl) {
            mediaContent.childCount - relativeLocation - 1
        } else {
            relativeLocation
        }
        pageIndicator.setLocation(location)
        updateClipToOutline()
    }

    /**
     * Notified whenever the players or their order has changed
     */
    fun onPlayersChanged() {
        updatePlayerVisibilities()
        updateMediaPaddings()
    }

    private fun updateMediaPaddings() {
        val padding = scrollView.context.resources.getDimensionPixelSize(R.dimen.qs_media_padding)
        val childCount = mediaContent.childCount
        for (i in 0 until childCount) {
            val mediaView = mediaContent.getChildAt(i)
            val desiredPaddingEnd = if (i == childCount - 1) 0 else padding
            val layoutParams = mediaView.layoutParams as ViewGroup.MarginLayoutParams
            if (layoutParams.marginEnd != desiredPaddingEnd) {
                layoutParams.marginEnd = desiredPaddingEnd
                mediaView.layoutParams = layoutParams
            }
        }
    }

    private fun updatePlayerVisibilities() {
        val scrolledIn = scrollIntoCurrentMedia != 0
        for (i in 0 until mediaContent.childCount) {
            val view = mediaContent.getChildAt(i)
            val visible = (i == activeMediaIndex) || ((i == (activeMediaIndex + 1)) && scrolledIn)
            view.visibility = if (visible) View.VISIBLE else View.INVISIBLE
        }
    }

    /**
     * Notify that a player will be removed right away. This gives us the opporunity to look
     * where it was and update our scroll position.
     */
    fun onPrePlayerRemoved(removed: MediaControlPanel) {
        val removedIndex = mediaContent.indexOfChild(removed.view?.player)
        // If the removed index is less than the activeMediaIndex, then we need to decrement it.
        // RTL has no effect on this, because indices are always relative (start-to-end).
        // Update the index 'manually' since we won't always get a call to onMediaScrollingChanged
        val beforeActive = removedIndex <= activeMediaIndex
        if (beforeActive) {
            activeMediaIndex = Math.max(0, activeMediaIndex - 1)
        }
        // If the removed media item is "left of" the active one (in an absolute sense), we need to
        // scroll the view to keep that player in view.  This is because scroll position is always
        // calculated from left to right.
        val leftOfActive = if (isRtl) !beforeActive else beforeActive
        if (leftOfActive) {
            scrollView.scrollX = Math.max(scrollView.scrollX - playerWidthPlusPadding, 0)
        }
    }

    /**
     * Update the bounds of the carousel
     */
    fun setCarouselBounds(currentCarouselWidth: Int, currentCarouselHeight: Int) {
        if (currentCarouselHeight != carouselHeight || currentCarouselWidth != carouselHeight) {
            carouselWidth = currentCarouselWidth
            carouselHeight = currentCarouselHeight
            scrollView.invalidateOutline()
        }
    }

    /**
     * Reset the MediaScrollView to the start.
     */
    fun scrollToStart() {
        scrollView.relativeScrollX = 0
    }

    companion object {
        private val CONTENT_TRANSLATION = object : FloatPropertyCompat<MediaCarouselScrollHandler>(
                "contentTranslation") {
            override fun getValue(handler: MediaCarouselScrollHandler): Float {
                return handler.contentTranslation
            }

            override fun setValue(handler: MediaCarouselScrollHandler, value: Float) {
                handler.contentTranslation = value
            }
        }
    }
}