package com.gh.vspace

import android.app.Application
import androidx.annotation.WorkerThread
import com.gh.download.DownloadManager
import com.gh.download.PackageObserver
import com.gh.gamecenter.common.baselist.ListViewModel
import com.gh.gamecenter.common.baselist.LoadType
import com.gh.gamecenter.common.utils.toProperReadableSize
import com.gh.gamecenter.core.runOnIoThread
import com.gh.gamecenter.core.runOnUiThread
import com.gh.gamecenter.core.utils.NumberUtils
import com.gh.gamecenter.core.utils.ToastUtils
import com.gh.gamecenter.feature.entity.GameEntity
import com.gh.gamecenter.eventbus.EBPackage
import com.gh.gamecenter.feature.entity.ApkEntity
import com.lightgame.download.DownloadStatus
import io.reactivex.Observable
import io.reactivex.Single
import io.reactivex.android.schedulers.AndroidSchedulers
import io.reactivex.disposables.Disposable
import io.reactivex.subjects.PublishSubject
import org.greenrobot.eventbus.EventBus
import java.util.concurrent.TimeUnit

class VDownloadManagerViewModel(application: Application) :
    ListViewModel<GameEntity, GameEntity>(application) {

    var type = ""
    var isFromHomeRecent = false

    private var loadPublishSubject: PublishSubject<List<String>> = PublishSubject.create()

    val disposable: Disposable = loadPublishSubject.debounce(300, TimeUnit.MILLISECONDS)
        .distinctUntilChanged { p1, p2 -> p1.sorted() == p2.sorted() }
        .observeOn(AndroidSchedulers.mainThread())
        .subscribe {
            load(LoadType.REFRESH)
        }

    val vGames = VHelper.vGameDao.getAllGames()

    fun refresh(apks: List<String>) {
        loadPublishSubject.onNext(apks)
    }

    override fun mergeResultLiveData() {
        mResultLiveData.addSource(mListLiveData) {
            mResultLiveData.postValue(it)
        }
    }

    override fun provideDataObservable(page: Int): Observable<MutableList<GameEntity>>? = null

    override fun provideDataSingle(page: Int): Single<MutableList<GameEntity>> {
        return if (type == TYPE_DOWNLOADED) {
            provideDownloadedSingle()
        } else {
            provideDownloadingSingle()
        }
    }

    private fun provideDownloadedSingle(): Single<MutableList<GameEntity>> {
        return Single.create { emitter ->
            val vGameList = VHelper.getAllVGame().sortedByDescending { it.downloadEntity.start }
            val gameList = arrayListOf<GameEntity>()

            // 为空直接返回
            if (vGameList.isEmpty()) {
                emitter.onSuccess(gameList)
                return@create
            }

            for (vGame in vGameList) {
                // 过滤部分不需要的
                if (DownloadManager.getInstance().allVDownloadTaskSnapshots.any {
                        it.gameId == vGame.downloadEntity.gameId && it.status != DownloadStatus.done
                    }) {
                    continue
                }

                val gameEntity = VHelper.toGameEntity(vGame.downloadEntity)
                if (gameEntity.playedTime != 0L) {
                    gameEntity.des =
                        "已畅玩${NumberUtils.transSimpleUsageTime(gameEntity.playedTime / 1000)}"
                } else {
                    var occupiedSpace =
                        VHelper.getAppOccupiedSpace(vGame.downloadEntity.packageName)
                    if (occupiedSpace == 0L) {
                        occupiedSpace = vGame.downloadEntity.size
                    }

                    gameEntity.des = "已占用 ${occupiedSpace.toProperReadableSize()}"
                }

                gameList.add(gameEntity)
            }

            emitter.onSuccess(gameList)
        }
    }

    private fun provideDownloadingSingle(): Single<MutableList<GameEntity>> {
        return Single.create { emitter ->
            val downloadList = DownloadManager.getInstance().allVDownloadTaskSnapshots

            val gameList = arrayListOf<GameEntity>()

            for (downloadEntity in downloadList) {
                // 过滤下载完成的部分
                if (downloadEntity.status == DownloadStatus.done
                    && VHelper.getAllVGameSnapshots().any { it.packageName == downloadEntity.packageName }
                ) {
                    continue
                }
                gameList.add(VHelper.toGameEntity(downloadEntity))
            }

            emitter.onSuccess(gameList)
        }
    }

    fun cleanGameData(packageName: String?) {
        runOnIoThread {
            VHelper.cleanGameData(packageName)
        }
    }

    @WorkerThread
    fun removeItem(url: String?, packageName: String?) {
        DownloadManager.getInstance().pause(url)
        DownloadManager.getInstance().cancel(url)

        VHelper.uninstall(packageName ?: "")

        runOnUiThread {
            val event = EBPackage("卸载", packageName ?: "", "unknown").also {
                it.isVGame = true
            }
            EventBus.getDefault().post(event)
            PackageObserver.onPackageChanged(event)

            ToastUtils.toast("已删除 1 款游戏")
        }
    }

    @WorkerThread
    fun removeItems(idList: ArrayList<String>) {
        val packageList = arrayListOf<String>()
        val apkList = arrayListOf<ApkEntity>()

        for (id in idList) {
            val apkEntity =
                mResultLiveData.value?.firstOrNull { id == it.id }?.getApk()?.firstOrNull() ?: continue

            apkList.add(apkEntity)
        }

        for (apkEntity in apkList) {
            DownloadManager.getInstance().pause(apkEntity.url)
            DownloadManager.getInstance().cancel(apkEntity.url)

            packageList.add(apkEntity.packageName)

            VHelper.uninstall(apkEntity.packageName)
        }

        runOnUiThread {
            for (packageName in packageList) {
                val event = EBPackage("卸载", packageName, "unknown").also {
                    it.isVGame = true
                }
                EventBus.getDefault().post(event)
                PackageObserver.onPackageChanged(event)
            }

            ToastUtils.toast("已删除 ${packageList.size} 款游戏")
        }
    }

    fun pauseItems(idList: ArrayList<String>) {
        for (id in idList) {
            mResultLiveData.value?.firstOrNull { id == it.id }?.getApk()?.firstOrNull()?.url?.let { url ->
                DownloadManager.getInstance().getDownloadEntitySnapshot(url)
                    ?.takeIf { it.status != DownloadStatus.done }
                    ?.let {
                        DownloadManager.getInstance().pause(url)
                    }
            }
        }
    }

    fun isTypeDownloaded(): Boolean {
        return type == TYPE_DOWNLOADED
    }

    override fun onCleared() {
        super.onCleared()

        disposable.dispose()
    }

    companion object {
        const val TYPE = "type"
        const val TYPE_DOWNLOADED = "type_downloaded"
        const val TYPE_DOWNLOADING = "type_downloading"
    }

}