package com.adealink.weparty.cache

import android.util.Log
import com.adealink.frame.base.IError
import com.adealink.frame.base.Rlt
import kotlinx.coroutines.async
import kotlinx.coroutines.flow.channelFlow
import kotlinx.coroutines.supervisorScope

/**
 * 数据仓库，本地+网络，谁快就先用谁来显示。
 * ChannelFlow:生产者消费者两端能够实现异步非阻塞模型
 * 生产和消费两端实现了并行执行
 */
abstract class CacheRepository<T> {

    companion object {
        private const val TAG = "CacheRepository"
    }


    fun getData() = channelFlow<Rlt<T>> {
        supervisorScope {
            val dataFromLocalDeffer = async {
                fetchDataFromLocal().also {
                    Log.d(
                        TAG,
                        "fetchDataFromLocal result:$it , thread:${Thread.currentThread().name}"
                    )

                    if (it is Rlt.Success) {
                        send(it)
                    }
                }
            }

            val dataFromNetDeffer = async {
                fetchDataFromNetWork().also {
                    Log.d(
                        TAG,
                        "fetchDataFromNetWork result:$it , thread:${Thread.currentThread().name}"
                    )
                    if (it is Rlt.Success) {
                        send(it)
                        //如果网络数据已加载，可以直接取消任务,就不需要处理本地数据了
                        dataFromLocalDeffer.cancel()
                    }
                }
            }

            //本地数据和网络数据，都加载失败的情况
            val localData = dataFromLocalDeffer.await()
            val networkData = dataFromNetDeffer.await()
            if (localData is Rlt.Failed && networkData is Rlt.Failed) {
                send(Rlt.Failed(IError("load data error")))
            }
        }
    }

    protected abstract suspend fun fetchDataFromLocal(): Rlt<T>

    protected abstract suspend fun fetchDataFromNetWork(): Rlt<T>

}
