package com.airbnb.lottie.compose

import com.airbnb.lottie.LottieComposition

/**
 * Use subclasses of [LottieClipSpec] to set min/max bounds on the animation playback.
 *
 * @see LottieAnimation
 * @see animateLottieComposition
 */
sealed class LottieClipSpec {

    internal abstract fun getMinProgress(composition: LottieComposition): Float

    internal abstract fun getMaxProgress(composition: LottieComposition): Float

    /**
     * Play the animation starting from this frame.
     */
    data class MinFrame(val minFrame: Int) : LottieClipSpec() {
        override fun getMinProgress(composition: LottieComposition): Float {
            return (minFrame / composition.endFrame).coerceIn(0f, 1f)
        }

        override fun getMaxProgress(composition: LottieComposition): Float {
            return 1f
        }
    }

    /**
     * Play the animation until this frame.
     */
    data class MaxFrame(val maxFrame: Int, val inclusive: Boolean = true) : LottieClipSpec() {

        private val actualMaxFrame = if (inclusive) maxFrame else maxFrame - 1

        override fun getMinProgress(composition: LottieComposition): Float {
            return 0f
        }

        override fun getMaxProgress(composition: LottieComposition): Float {
            return (actualMaxFrame / composition.endFrame).coerceIn(0f, 1f)
        }
    }

    /**
     * Play the animation between these two frames.
     */
    data class MinAndMaxFrame(val minFrame: Int, val maxFrame: Int, val maxFrameInclusive: Boolean = true) : LottieClipSpec() {

        private val actualMaxFrame = if (maxFrameInclusive) maxFrame else maxFrame - 1

        override fun getMinProgress(composition: LottieComposition): Float {
            return (minFrame / composition.endFrame).coerceIn(0f, 1f)
        }

        override fun getMaxProgress(composition: LottieComposition): Float {
            return (actualMaxFrame / composition.endFrame).coerceIn(0f, 1f)
        }
    }

    /**
     * Play the animation from this progress.
     */
    data class MinProgress(val minProgress: Float) : LottieClipSpec() {
        override fun getMinProgress(composition: LottieComposition): Float {
            return minProgress
        }

        override fun getMaxProgress(composition: LottieComposition): Float {
            return 1f
        }
    }

    /**
     * Play the animation until this progress.
     */
    data class MaxProgress(val maxProgress: Float) : LottieClipSpec() {
        override fun getMinProgress(composition: LottieComposition): Float {
            return 0f
        }

        override fun getMaxProgress(composition: LottieComposition): Float {
            return maxProgress
        }
    }

    /**
     * Play the animation between these two progresses.
     */
    data class MinAndMaxProgress(val minProgress: Float, val maxProgress: Float) : LottieClipSpec() {
        override fun getMinProgress(composition: LottieComposition): Float {
            return minProgress
        }

        override fun getMaxProgress(composition: LottieComposition): Float {
            return maxProgress
        }
    }

    /**
     * Play the animation starting from this marker.
     */
    data class MinMarker(val minMarker: String) : LottieClipSpec() {
        override fun getMinProgress(composition: LottieComposition): Float {
            return ((composition.getMarker(minMarker)?.startFrame ?: 0f) / composition.endFrame).coerceIn(0f, 1f)
        }

        override fun getMaxProgress(composition: LottieComposition): Float {
            return 1f
        }
    }

    /**
     * Play the animation until this marker. If the marker represents the end of your animation, set
     * [playMarkerFrame] to true. If the marker represents the beginning of the next section, set
     * it to false. In that case, the animation will stop at the frame before the marker.
     */
    data class MaxMarker(val maxMarker: String, val playMarkerFrame: Boolean = true) : LottieClipSpec() {
        override fun getMinProgress(composition: LottieComposition): Float {
            return 0f
        }

        override fun getMaxProgress(composition: LottieComposition): Float {
            val offset = if (playMarkerFrame) 0 else -1
            return ((composition.getMarker(maxMarker)?.startFrame?.plus(offset) ?: 0f) / composition.endFrame).coerceIn(0f, 1f)
        }
    }

    /**
     * Play the animation from minMarker until maxMarker. If maxMarker represents the end of your animation,
     * set [playMaxMarkerStartFrame] to true. If the marker represents the beginning of the next section, set
     * it to false. In that case, the animation will stop at the frame before maxMarker.
     */
    data class MinAndMaxMarker(val minMarker: String, val maxMarker: String, val playMaxMarkerStartFrame: Boolean = true) : LottieClipSpec() {
        override fun getMinProgress(composition: LottieComposition): Float {
            return ((composition.getMarker(minMarker)?.startFrame ?: 0f) / composition.endFrame).coerceIn(0f, 1f)
        }

        override fun getMaxProgress(composition: LottieComposition): Float {
            val offset = if (playMaxMarkerStartFrame) 0 else -1
            return ((composition.getMarker(maxMarker)?.startFrame?.plus(offset) ?: 0f) / composition.endFrame).coerceIn(0f, 1f)
        }
    }

    /**
     * Play the animation from the beginning of the marker for the duration of the marker itself.
     * The duration can be set in After Effects.
     */
    data class Marker(val marker: String) : LottieClipSpec() {
        override fun getMinProgress(composition: LottieComposition): Float {
            return ((composition.getMarker(marker)?.startFrame ?: 0f) / composition.endFrame).coerceIn(0f, 1f)
        }

        override fun getMaxProgress(composition: LottieComposition): Float {
            val marker = composition.getMarker(marker) ?: return 1f
            return ((marker.startFrame + marker.durationFrames) / composition.endFrame).coerceIn(0f, 1f)
        }
    }
}