package com.remax.visualnovel.widget.imageviewer.adapter

import androidx.lifecycle.MutableLiveData
import androidx.paging.Pager
import androidx.paging.PagingConfig
import androidx.paging.PagingSource
import androidx.paging.PagingState
import androidx.paging.liveData
import com.remax.visualnovel.extension.resumeWithActive
import com.remax.visualnovel.widget.imageviewer.core.Components
import com.remax.visualnovel.widget.imageviewer.core.Photo
import kotlinx.coroutines.suspendCancellableCoroutine

class Repository {
    private val dataProvider by lazy { Components.requireDataProvider() }
    private val dataList = MutableLiveData<List<Photo>>()
    internal val snapshot: List<Photo> get() = dataList.value ?: listOf()
    internal val pagingData = Pager(PagingConfig(1), null) { dataSource() }.liveData

    private fun dataSource() = object : PagingSource<Long, Photo>() {
        override fun getRefreshKey(state: PagingState<Long, Photo>): Long? = null
        override suspend fun load(params: LoadParams<Long>): LoadResult<Long, Photo> {
            when (params) {
                is LoadParams.Refresh -> {
                    val list: List<Photo> = snapshot.ifEmpty { dataProvider.loadInitial() }
                    dataList.value = list
                    return LoadResult.Page(list, list.firstOrNull()?.id(), list.lastOrNull()?.id())
                }
                is LoadParams.Append -> {
                    val list: List<Photo> = suspendCancellableCoroutine { continuation ->
                        dataProvider.loadAfter(params.key) {
                            continuation.resumeWithActive(it)
                        }
                        continuation.invokeOnCancellation {
                            continuation.resumeWithActive(emptyList())
                        }
                    }
                    dataList.value = snapshot.toMutableList().also { it.addAll(list) }
                    return LoadResult.Page(list, list.firstOrNull()?.id(), list.lastOrNull()?.id())
                }
                is LoadParams.Prepend -> {
                    val list: List<Photo> = suspendCancellableCoroutine { continuation ->
                        dataProvider.loadBefore(params.key) {
                            continuation.resumeWithActive(it)
                        }
                        continuation.invokeOnCancellation {
                            continuation.resumeWithActive(emptyList())
                        }
                    }
                    dataList.value = snapshot.toMutableList().also { it.addAll(0, list) }
                    return LoadResult.Page(list, list.firstOrNull()?.id(), list.lastOrNull()?.id())
                }
            }
        }
    }

    fun redirect(adapter: ImageViewerAdapter, exclude: List<Photo>, emptyCallback: () -> Unit) {
        synchronized(this) {
            val list = snapshot.asSequence()
            val _dataList = list.filter {
                !exclude.contains(it)
            }.toList()
            if (_dataList.isEmpty()) {
                return Unit.also { emptyCallback() }
            }
            dataList.value = _dataList

            //找到应该定位到的targetItem
            val last = exclude.lastOrNull()
            val lastIndex = snapshot.indexOf(last)
            val first = exclude.firstOrNull()
            val firstIndex = exclude.indexOf(first)
            val targetIndex = if (lastIndex != snapshot.size - 1) {
                lastIndex + 1
            } else {
                firstIndex - 1
            }
            val target = snapshot[targetIndex]
            dataProvider.exclude(exclude, target)
            adapter.refresh()
        }
    }
}
