/*
 * Copyright 2021 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.
 */

// Ignore lint warnings in documentation snippets
@file:Suppress("unused", "UNUSED_PARAMETER", "UNUSED_VARIABLE")

package androidx.compose.integration.docs.lifecycle

import androidx.activity.OnBackPressedCallback
import androidx.activity.OnBackPressedDispatcher
import androidx.compose.foundation.layout.Box
import androidx.compose.foundation.layout.Column
import androidx.compose.foundation.layout.fillMaxSize
import androidx.compose.foundation.lazy.LazyColumn
import androidx.compose.foundation.lazy.items
import androidx.compose.material.Button
import androidx.compose.material.ExperimentalMaterialApi
import androidx.compose.material.Scaffold
import androidx.compose.material.ScaffoldState
import androidx.compose.material.Text
import androidx.compose.material.rememberScaffoldState
import androidx.compose.runtime.Composable
import androidx.compose.runtime.DisposableEffect
import androidx.compose.runtime.getValue
import androidx.compose.runtime.LaunchedEffect
import androidx.compose.runtime.SideEffect
import androidx.compose.runtime.Stable
import androidx.compose.runtime.State
import androidx.compose.runtime.derivedStateOf
import androidx.compose.runtime.key
import androidx.compose.runtime.mutableStateListOf
import androidx.compose.runtime.produceState
import androidx.compose.runtime.remember
import androidx.compose.runtime.rememberCoroutineScope
import androidx.compose.runtime.rememberUpdatedState
import androidx.compose.ui.Modifier
import kotlinx.coroutines.delay
import kotlinx.coroutines.launch
import kotlin.random.Random

/**
 * This file lets DevRel track changes to snippets present in
 * https://developer.android.com/jetpack/compose/xxxxxxxxxxxxxxx
 *
 * No action required if it's modified.
 */

private object LifecycleSnippet1 {
    @Composable
    fun MyComposable() {
        Column {
            Text("Hello")
            Text("World")
        }
    }
}
private object LifecycleSnippet2 {
    @Composable
    fun LoginScreen(showError: Boolean) {
        if (showError) {
            LoginError()
        }
        LoginInput() // This call site is used to generate the key
    }

    @Composable
    fun LoginInput() { /* ... */ }
}

private object LifecycleSnippet3 {
    @Composable
    fun MoviesScreen(movies: List<Movie>) {
        LazyColumn {
            items(movies) { movie ->
                // All MovieOverview composables in Composition will have the same key!
                // Thus, all calls will always recompose and restart all side effects.
                MovieOverview(movie)
            }
        }
    }
}

private object LifecycleSnippet4 {
    @Composable
    fun MoviesScreen(movies: List<Movie>) {
        LazyColumn {
            items(movies) { movie ->
                key(movie.id) { // Unique ID for this movie
                    MovieOverview(movie)
                }
            }
        }
    }
}

private object LifecycleSnippet5 {
    // Marking the type as stable to favor skipping and smart recompositions.
    @Stable
    interface UiState<T : Result<T>> {
        val value: T?
        val exception: Throwable?

        val hasError: Boolean
            get() = exception != null
    }
}

@ExperimentalMaterialApi
private object LifecycleSnippet6 {
    @Composable
    fun MyScreen(
        state: UiState<List<Movie>>,
        scaffoldState: ScaffoldState = rememberScaffoldState()
    ) {

        // If the UI state contains an error, show snackbar
        if (state.hasError) {

            // `LaunchedEffect` will cancel and re-launch if `scaffoldState` changes
            LaunchedEffect(scaffoldState) {
                // Show snackbar using a coroutine, when the coroutine is cancelled the
                // snackbar will automatically dismiss. This coroutine will cancel whenever
                // `state.hasError` is false, and only start when `state.hasError`
                // is true (due to the above if-check), or if `scaffoldState` changes.
                scaffoldState.snackbarHostState.showSnackbar(
                    message = "Error message",
                    actionLabel = "Retry message"
                )
            }
        }

        Scaffold(scaffoldState = scaffoldState) {
            /* ... */
        }
    }
}

@ExperimentalMaterialApi
private object LifecycleSnippet7 {
    @Composable
    fun MoviesScreen(scaffoldState: ScaffoldState = rememberScaffoldState()) {

        // Creates a CoroutineScope bound to the MoviesScreen's lifecycle
        val scope = rememberCoroutineScope()

        Scaffold(scaffoldState = scaffoldState) {
            Column {
                /* ... */
                Button(
                    onClick = {
                        // Create a new coroutine in the event handler to show a snackbar
                        scope.launch {
                            scaffoldState.snackbarHostState.showSnackbar("Something happened!")
                        }
                    }
                ) {
                    Text("Press me")
                }
            }
        }
    }
}

private object LifecycleSnippet8 {
    @Composable
    fun LandingScreen(onTimeout: () -> Unit) {

        // This will always refer to the latest onTimeout function that
        // LandingScreen was recomposed with
        val currentOnTimeout by rememberUpdatedState(onTimeout)

        // Create an effect that matches the lifecycle of LandingScreen.
        // If LandingScreen recomposes, the delay shouldn't start again.
        LaunchedEffect(Unit) {
            delay(SplashWaitTimeMillis)
            currentOnTimeout()
        }

        /* Landing screen content */
    }
}

private object LifecycleSnippet9 {
    @Composable
    fun BackHandler(backDispatcher: OnBackPressedDispatcher, onBack: () -> Unit) {

        // Safely update the current `onBack` lambda when a new one is provided
        val currentOnBack by rememberUpdatedState(onBack)

        // Remember in Composition a back callback that calls the `onBack` lambda
        val backCallback = remember {
            // Always intercept back events. See the SideEffect for a more complete version
            object : OnBackPressedCallback(true) {
                override fun handleOnBackPressed() {
                    currentOnBack()
                }
            }
        }

        // If `backDispatcher` changes, dispose and reset the effect
        DisposableEffect(backDispatcher) {
            // Add callback to the backDispatcher
            backDispatcher.addCallback(backCallback)

            // When the effect leaves the Composition, remove the callback
            onDispose {
                backCallback.remove()
            }
        }
    }
}

private object LifecycleSnippet10 {
    @Composable
    fun BackHandler(
        backDispatcher: OnBackPressedDispatcher,
        enabled: Boolean = true, // Whether back events should be intercepted or not
        onBack: () -> Unit
    ) {
        // START - DO NOT COPY IN CODE SNIPPET
        val currentOnBack by rememberUpdatedState(onBack)

        val backCallback = remember {
            // Always intercept back events. See the SideEffect for a more complete version
            object : OnBackPressedCallback(true) {
                override fun handleOnBackPressed() {
                    currentOnBack()
                }
            }
        }
        // END - DO NOT COPY IN CODE SNIPPET, just use /* ... */

        // On every successful composition, update the callback with the `enabled` value
        // to tell `backCallback` whether back events should be intercepted or not
        SideEffect {
            backCallback.isEnabled = enabled
        }

        /* Rest of the code */
    }
}

private object LifecycleSnippet11 {
    @Composable
    fun loadNetworkImage(
        url: String,
        imageRepository: ImageRepository
    ): State<Result<Image>> {

        // Creates a State<T> with Result.Loading as initial value
        // If either `url` or `imageRepository` changes, the running producer
        // will cancel and will be re-launched with the new inputs.
        return produceState(initialValue = Result.Loading, url, imageRepository) {

            // In a coroutine, can make suspend calls
            val image = imageRepository.load(url)

            // Update State with either an Error or Success result.
            // This will trigger a recomposition where this State is read
            value = if (image == null) {
                Result.Error
            } else {
                Result.Success(image)
            }
        }
    }
}

private object LifecycleSnippet12 {
    @Composable
    fun TodoList(highPriorityKeywords: List<String> = listOf("Review", "Unblock", "Compose")) {

        val todoTasks = remember { mutableStateListOf<String>() }

        // Calculate high priority tasks only when the todoTasks or highPriorityKeywords
        // change, not on every recomposition
        val highPriorityTasks by remember(todoTasks, highPriorityKeywords) {
            derivedStateOf { todoTasks.filter { it.containsWord(highPriorityKeywords) } }
        }

        Box(Modifier.fillMaxSize()) {
            LazyColumn {
                items(highPriorityTasks) { /* ... */ }
                items(todoTasks) { /* ... */ }
            }
            /* Rest of the UI where users can add elements to the list */
        }
    }
}

private object LifecycleSnippet13 {
    @Composable
    fun BackHandler(backDispatcher: OnBackPressedDispatcher, onBack: () -> Unit) {
        // START - DO NOT COPY IN CODE SNIPPET
        val currentOnBack by rememberUpdatedState(onBack)

        val backCallback = remember {
            // Always intercept back events. See the SideEffect for a more complete version
            object : OnBackPressedCallback(true) {
                override fun handleOnBackPressed() {
                    currentOnBack()
                }
            }
        }
        // END - DO NOT COPY IN CODE SNIPPET, just use /* ... */

        DisposableEffect(backDispatcher) {
            backDispatcher.addCallback(backCallback)
            onDispose {
                backCallback.remove()
            }
        }
    }
}

/*
Fakes needed for snippets to build:
 */
private const val SplashWaitTimeMillis = 1000L

@Composable
private fun LoginError() { }

@Composable
private fun MovieOverview(movie: Movie) { }
private data class Movie(val id: Long)

private data class UiState<T>(
    val loading: Boolean = false,
    val exception: Exception? = null,
    val data: T? = null
) {
    val hasError: Boolean
        get() = exception != null
}

private class Image
private class ImageRepository {
    fun load(url: String): Image? = if (Random.nextInt() == 0) Image() else null // Avoid warnings
}

private sealed class Result<out R> {
    data class Success<out T>(val data: T) : Result<T>()
    object Loading : Result<Nothing>()
    object Error : Result<Nothing>()
}

private class User
private class Weather
private class Greeting(val name: String)
private fun prepareGreeting(user: User, weather: Weather) = Greeting("haha")

private fun String.containsWord(input: List<String>): Boolean = false
