package com.airbnb.lottie.samples

import android.animation.ValueAnimator
import android.app.Application
import android.net.Uri
import com.airbnb.lottie.LottieComposition
import com.airbnb.lottie.LottieCompositionFactory
import com.airbnb.lottie.LottieTask
import com.airbnb.lottie.samples.model.CompositionArgs
import com.airbnb.lottie.samples.utils.MvRxViewModel
import com.airbnb.mvrx.Async
import com.airbnb.mvrx.Fail
import com.airbnb.mvrx.MvRxState
import com.airbnb.mvrx.MvRxViewModelFactory
import com.airbnb.mvrx.Success
import com.airbnb.mvrx.Uninitialized
import com.airbnb.mvrx.ViewModelContext
import java.io.FileInputStream
import kotlin.math.max
import kotlin.math.min

data class PlayerState(
    val composition: Async<LottieComposition> = Uninitialized,
    val controlsVisible: Boolean = true,
    val controlBarVisible: Boolean = true,
    val renderGraphVisible: Boolean = false,
    val outlineMasksAndMattes: Boolean = false,
    val borderVisible: Boolean = false,
    val backgroundColorVisible: Boolean = false,
    val speedVisible: Boolean = false,
    val trimVisible: Boolean = false,
    val useMergePaths: Boolean = false,
    val minFrame: Int = 0,
    val maxFrame: Int = 0,
    val speed: Float = 1f,
    val repeatCount: Int = ValueAnimator.INFINITE
) : MvRxState

class PlayerViewModel(
    initialState: PlayerState,
    private val application: Application
) : MvRxViewModel<PlayerState>(initialState) {

    fun fetchAnimation(args: CompositionArgs) {
        val url = args.url ?: args.animationDataV2?.file ?: args.animationData?.lottieLink

        when {
            url != null -> LottieCompositionFactory.fromUrl(application, url, null)
            args.fileUri != null -> taskForUri(args.fileUri)
            args.asset != null -> LottieCompositionFactory.fromAsset(application, args.asset, null)
            else -> error("Don't know how to fetch animation for $args")
        }
            .addListener {
                setState {
                    copy(composition = Success(it), minFrame = it.startFrame.toInt(), maxFrame = it.endFrame.toInt())
                }
            }
            .addFailureListener { setState { copy(composition = Fail(it)) } }
    }

    private fun taskForUri(uri: Uri): LottieTask<LottieComposition> {
        val fis = when (uri.scheme) {
            "file" -> FileInputStream(uri.path ?: error("File has no path!"))
            "content" -> application.contentResolver.openInputStream(uri)
            else -> error("Unknown scheme ${uri.scheme}")
        }

        return LottieCompositionFactory.fromJsonInputStream(fis, null)
    }

    fun toggleRenderGraphVisible() = setState { copy(renderGraphVisible = !renderGraphVisible) }

    fun toggleOutlineMasksAndMattes() = setState { copy(outlineMasksAndMattes = !outlineMasksAndMattes) }

    fun toggleBorderVisible() = setState { copy(borderVisible = !borderVisible) }

    fun toggleBackgroundColorVisible() = setState { copy(backgroundColorVisible = !backgroundColorVisible) }

    fun setBackgroundColorVisible(visible: Boolean) = setState { copy(backgroundColorVisible = visible) }

    fun toggleSpeedVisible() = setState { copy(speedVisible = !speedVisible) }

    fun setSpeedVisible(visible: Boolean) = setState { copy(speedVisible = visible) }

    fun toggleTrimVisible() = setState { copy(trimVisible = !trimVisible) }

    fun setTrimVisible(visible: Boolean) = setState { copy(trimVisible = visible) }

    fun toggleMergePaths() = setState { copy(useMergePaths = !useMergePaths) }

    fun setMinFrame(minFrame: Int) = setState {
        copy(minFrame = max(minFrame, composition()?.startFrame?.toInt() ?: 0))
    }

    fun setMaxFrame(maxFrame: Int) = setState {
        copy(maxFrame = min(maxFrame, composition()?.endFrame?.toInt() ?: 0))
    }

    fun setSpeed(speed: Float) = setState { copy(speed = speed) }

    fun toggleLoop() = setState { copy(repeatCount = if (repeatCount == ValueAnimator.INFINITE) 0 else ValueAnimator.INFINITE) }

    fun setDistractionFree(distractionFree: Boolean) = setState {
        copy(
            controlsVisible = !distractionFree,
            controlBarVisible = !distractionFree,
            renderGraphVisible = false,
            borderVisible = false,
            backgroundColorVisible = false,
            speedVisible = false,
            trimVisible = false
        )
    }

    companion object : MvRxViewModelFactory<PlayerViewModel, PlayerState> {
        override fun create(viewModelContext: ViewModelContext, state: PlayerState): PlayerViewModel {
            return PlayerViewModel(state, viewModelContext.app())
        }
    }
}