package net.schueller.peertube.feature_video.presentation.video

import android.util.Log
import android.widget.Toast
import androidx.compose.foundation.layout.*
import androidx.compose.foundation.lazy.LazyColumn
import androidx.compose.foundation.lazy.rememberLazyListState
import androidx.compose.material.ExperimentalMaterialApi
import androidx.compose.material.Scaffold
import androidx.compose.material.Text
import androidx.compose.runtime.*
import androidx.compose.ui.Modifier
import androidx.compose.ui.geometry.Offset
import androidx.compose.ui.input.nestedscroll.NestedScrollConnection
import androidx.compose.ui.input.nestedscroll.NestedScrollSource
import androidx.compose.ui.input.nestedscroll.nestedScroll
import androidx.compose.ui.platform.LocalContext
import androidx.compose.ui.platform.LocalDensity
import androidx.compose.ui.tooling.preview.Preview
import androidx.compose.ui.unit.IntOffset
import androidx.compose.ui.unit.dp
import androidx.hilt.navigation.compose.hiltViewModel
import androidx.navigation.NavController
import androidx.paging.LoadState
import androidx.paging.compose.LazyPagingItems
import androidx.paging.compose.collectAsLazyPagingItems
import androidx.paging.compose.itemsIndexed
import coil.annotation.ExperimentalCoilApi
import com.google.accompanist.swiperefresh.SwipeRefresh
import com.google.accompanist.swiperefresh.rememberSwipeRefreshState
import kotlinx.coroutines.flow.collectLatest
import net.schueller.peertube.feature_video.domain.model.Overview
import net.schueller.peertube.feature_video.domain.model.Video
import net.schueller.peertube.feature_video.presentation.video.components.*
import net.schueller.peertube.feature_video.presentation.video.components.appBarBottom.BottomBarComponent
import net.schueller.peertube.feature_video.presentation.video.components.appBarTop.TopAppBarComponent
import net.schueller.peertube.feature_video.presentation.video.components.videoPlay.VideoPlayScreen
import net.schueller.peertube.feature_video.presentation.video.events.VideoPlayEvent
import net.schueller.peertube.feature_video.presentation.video.player.ExoPlayerHolder
import net.schueller.peertube.presentation.ui.theme.PeertubeTheme
import kotlin.math.roundToInt

@OptIn(ExperimentalMaterialApi::class)
@ExperimentalCoilApi
@Composable
fun VideoListScreen(
    navController: NavController,
    exoPlayerHolder: ExoPlayerHolder,
    viewModel: VideoListViewModel = hiltViewModel(),
    videoPlayViewModel: VideoPlayViewModel = hiltViewModel(),
    viewExploreModel: VideoExploreViewModel = hiltViewModel()
) {

    val state = viewModel.state.value

    val lazyVideoExploreItems: LazyPagingItems<Overview> = viewExploreModel.videos.collectAsLazyPagingItems()
    val lazyVideoItems: LazyPagingItems<Video> = viewModel.videos.collectAsLazyPagingItems()

    val listState = rememberLazyListState()

    val context = LocalContext.current


    // Auto hide top appbar
    val toolBarHeight = 56.dp
    val toolBarHeightPx = with(LocalDensity.current) { toolBarHeight.roundToPx().toFloat()}
    val toolBarOffsetHeightPx = remember { mutableStateOf(0f) }
    val nestedScrollConnection = remember {
        object : NestedScrollConnection {
            override fun onPreScroll(available: Offset, source: NestedScrollSource): Offset {
                val delta = available.y
                val newOffset = toolBarOffsetHeightPx.value + delta
                toolBarOffsetHeightPx.value = newOffset.coerceIn(-toolBarHeightPx, 0f)
                return Offset.Zero
            }
        }
    }

    // Events
    LaunchedEffect(key1 = true) {
        viewModel.eventFlow.collectLatest { event ->
            when(event) {
                is VideoListViewModel.UiEvent.ScrollToTop -> {
                    listState.scrollToItem(index = 0)
                    // reset toolbar to visible
                    toolBarOffsetHeightPx.value = 0f
                }
                is VideoListViewModel.UiEvent.ShowToast -> {
                    Toast.makeText(
                        context,
                        event.message,
                        event.length
                    ).show()
                }
            }
        }
    }


    Box(
        Modifier
            .fillMaxSize()
            .nestedScroll(nestedScrollConnection)
    )
    {
        // List
        Scaffold(
            bottomBar = {
                BottomBarComponent(navController)
            }
        ) { contentPadding ->
        // Pull to refresh
            // TODO: fix appbar blank issue
            SwipeRefresh(
                modifier = Modifier.padding(contentPadding),
                state = rememberSwipeRefreshState(
                    isRefreshing = (lazyVideoItems.loadState.refresh is LoadState.Loading) || (lazyVideoExploreItems.loadState.refresh is LoadState.Loading)
                ),
                onRefresh = {
                    // Which model do we want to refresh
                    if (state.explore) {
                        lazyVideoExploreItems.refresh()
                    } else {
                        lazyVideoItems.refresh()
                    }
                }
            ) {
                LazyColumn(
                    contentPadding = PaddingValues(top = toolBarHeight),
                    state = listState,
                    modifier = Modifier.fillMaxSize()
                ) {
                    if (state.explore) {
                        itemsIndexed(lazyVideoExploreItems) { _, overview ->
                            if (overview != null) {
                                // Categories
                                if (overview.categories?.isNotEmpty() == true) {
                                    overview.categories.forEach { categoryVideo ->
                                        VideoCategory(categoryVideo.category)
                                        if (categoryVideo.videos.isNotEmpty()) {
                                            categoryVideo.videos.forEach { video ->
                                                VideoListItem(
                                                    video = video,
                                                    onItemClick = {
                                                        videoPlayViewModel.onEvent(VideoPlayEvent.PlayVideo(video))
                                                    }
                                                )
                                            }
                                        }
                                    }
                                }
                                // Channels
                                if (overview.channels?.isNotEmpty() == true) {
                                    overview.channels.forEach { channelVideo ->
                                        VideoChannel(channelVideo.channel)
                                        if (channelVideo.videos.isNotEmpty()) {
                                            channelVideo.videos.forEach { video ->
                                                VideoListItem(
                                                    video = video,
                                                    onItemClick = {
                                                        videoPlayViewModel.onEvent(VideoPlayEvent.PlayVideo(video))
                                                    }
                                                )
                                            }
                                        }
                                    }
                                }
                                // Tags
                                if (overview.tags?.isNotEmpty() == true) {
                                    overview.tags.forEach { tagVideo ->
                                        VideoTag(tagVideo.tag)
                                        if (tagVideo.videos.isNotEmpty()) {
                                            tagVideo.videos.forEach { video ->
                                                VideoListItem(
                                                    video = video,
                                                    onItemClick = {
                                                        videoPlayViewModel.onEvent(VideoPlayEvent.PlayVideo(video))
                                                    }
                                                )
                                            }
                                        }
                                    }
                                }
                            }
                        }
                    } else {
                        itemsIndexed(lazyVideoItems) { item, video ->
                            if (video != null) {
                                Log.v("VLV", video.id.toString() + "-" + item.toString())
                                VideoListItem(
                                    video = video,
                                    onItemClick = {
                                        videoPlayViewModel.onEvent(VideoPlayEvent.PlayVideo(video))
                                    }
                                )
                            }
                        }
                        lazyVideoItems.apply {
                            when {
                                loadState.refresh is LoadState.Loading -> {
                                    item {
    //                                    LoadingView(modifier = Modifier.fillParentMaxSize())
                                    }
                                }
                                loadState.append is LoadState.Loading -> {
                                    item {
    //                                    LoadingItem()
                                    }
                                }
                                loadState.refresh is LoadState.Error -> {
                                    val e = lazyVideoItems.loadState.refresh as LoadState.Error
                                    item {
    //                                    ErrorItem(
    //                                        message = e.error.localizedMessage!!,
    //                                        modifier = Modifier.fillParentMaxSize(),
    //                                        onClickRetry = { retry() }
    //                                    )
                                    }
                                }
                                loadState.append is LoadState.Error -> {
                                    val e = lazyVideoItems.loadState.append as LoadState.Error
                                    item {
    //                                    ErrorItem(
    //                                        message = e.error.localizedMessage!!,
    //                                        onClickRetry = { retry() }
    //                                    )
                                    }
                                }
                            }
                        }
                    }

                    // TODO: deal with errors, https://proandroiddev.com/infinite-lists-with-paging-3-in-jetpack-compose-b095533aefe6

                }

            }

            // Place after list, so it floats above the list in z-height
            TopAppBarComponent(
                navController,
                modifier = Modifier
                    .height(toolBarHeight)
                    .offset {
                        IntOffset(x = 0, y = toolBarOffsetHeightPx.value.roundToInt())
                    }
            )
    //        if(error) {
    //            Text(
    //                text = "Error Text",
    //                color = MaterialTheme.colors.error,
    //                textAlign = TextAlign.Center,
    //                modifier = Modifier
    //                    .fillMaxWidth()
    //                    .padding(horizontal = 20.dp)
    //                    .align(Alignment.Center)
    //            )
    //        }

        }

        if (videoPlayViewModel.playerVisible.value) {
            Log.v("VLS", "Show Video Player")
            VideoPlayScreen(exoPlayerHolder)
        } else {
            Log.v("VLS", "Close Video Player")
        }

    }
}