package cash.z.android.wallet.ui.util

import android.animation.Animator
import cash.z.android.wallet.extention.Toaster
import com.airbnb.lottie.LottieAnimationView
import com.airbnb.lottie.LottieDrawable

/**
 * Utility to help with looping a lottie animation over a particular range. It will start the animation and play it up
 * to the end of the range and then set it to loop over the range and, once stopped, it will proceed from the current
 * frame to the end of the animation. Visually: BEGIN...LOOP...LOOP...LOOP...END
 */
class LottieLooper(private val lottie: LottieAnimationView, private val loopRange: IntRange, private val lastFrame: Int = Int.MAX_VALUE) :
    Animator.AnimatorListener {

    var isPlaying = false

    fun start() {
        if (isPlaying) return
        with(lottie) {
            setMinAndMaxFrame(1, loopRange.last)
            repeatCount = 0
            addAnimatorListener(this@LottieLooper)
            playAnimation()
        }
        isPlaying = true
    }

    fun stop() {
        with(lottie) {
            setMinAndMaxFrame(lottie.frame, lastFrame)
            repeatCount = 0
            // we don't want to just cancel the animation. We want it to finish it's final frames but the moment it is
            // done, we need it to freeze on that final frame and then die
            addAnimatorListener(LottieAssassin())
        }
        isPlaying = false
    }

    override fun onAnimationRepeat(animation: Animator?) {
    }

    override fun onAnimationEnd(animation: Animator?) {
        with(lottie) {
            removeAllAnimatorListeners()
            setMinAndMaxFrame(loopRange.first, loopRange.last)
            repeatCount = LottieDrawable.INFINITE
            playAnimation()
        }
    }

    override fun onAnimationCancel(animation: Animator?) {
    }

    override fun onAnimationStart(animation: Animator?) {
    }

    /** I have one job: kill lottie */
    inner class LottieAssassin : Animator.AnimatorListener {
        override fun onAnimationRepeat(animation: Animator?) {
            finishingMove()
        }

        override fun onAnimationEnd(animation: Animator?) {
            finishingMove()
        }

        override fun onAnimationCancel(animation: Animator?) {
            finishingMove()
        }

        override fun onAnimationStart(animation: Animator?) {
            finishingMove()
        }

        /** Agressively force it to freeze on the lastframe */
        private fun finishingMove() {
            lottie.pauseAnimation()
            lottie.setMinAndMaxFrame(lastFrame, lastFrame)
            lottie.progress = 1.0f
            // wait around a bit to see if there's any movement, then quietly make my getaway
            lottie.postDelayed({
                lottie.removeAnimatorListener(this)
                lottie.setMinAndMaxFrame(1, lastFrame)
            }, 500L)
        }
    }
}