package com.gh.gamecenter.simulatorgame

import android.app.Application
import android.database.sqlite.SQLiteException
import androidx.lifecycle.ViewModel
import androidx.lifecycle.ViewModelProvider
import com.gh.common.simulator.SimulatorGameManager
import com.gh.common.simulator.SimulatorGameManager.findDownloadEntityByUrl
import com.gh.gamecenter.common.utils.NetworkUtils
import com.gh.gamecenter.core.utils.UrlFilterUtils
import com.gh.gamecenter.common.utils.safelyGetInRelease
import com.gh.download.DownloadManager
import com.gh.gamecenter.common.baselist.ListViewModel
import com.gh.gamecenter.feature.entity.GameEntity
import com.gh.gamecenter.feature.entity.SimulatorGameRecordEntity
import com.gh.gamecenter.retrofit.RetrofitManager
import com.gh.gamecenter.room.AppDatabase
import com.halo.assistant.HaloApp
import io.reactivex.Observable
import io.reactivex.Single
import java.io.File

class SimulatorGameListViewModel(application: Application, var type: String) :
    ListViewModel<GameEntity, GameEntity>(application) {

    private val mApi = RetrofitManager.getInstance().api

    var positionAndPackageMap = HashMap<String, Int>() // key: packageName + position, value: position

    private val mSimulatorGameDao = AppDatabase.getInstance().simulatorGameDao()

    override fun mergeResultLiveData() {
        mResultLiveData.addSource<List<GameEntity>>(mListLiveData) {
            positionAndPackageMap.clear()
            val newList = ArrayList<GameEntity>()
            val simulatorGameRecordList = ArrayList<SimulatorGameRecordEntity>()
            it.forEachIndexed { index, gameEntity ->
                addGamePositionAndPackage(gameEntity, index + 1)
                val apk = gameEntity.getApk().safelyGetInRelease(0)
                val downloadEntity = findDownloadEntityByUrl(apk?.url ?: "")
                // 下载记录被删除或者后台设置为隐藏且本次文件被删除，则不显示该游戏且删除该记录
                if (downloadEntity == null || (!gameEntity.active && !File(downloadEntity.path).exists())) {
                    SimulatorGameManager.deleteSimulatorGame(gameEntity.id) {}
                    mSimulatorGameDao.deleteSimulatorGameByName(gameEntity.name ?: "")
                } else {
                    newList.add(gameEntity)
                    simulatorGameRecordList.add(gameEntity.convertSimulatorGameRecordEntity())
                }
            }
            try {
                mSimulatorGameDao.addSimulatorGameList(simulatorGameRecordList)
                mResultLiveData.postValue(newList)
            } catch (e: SQLiteException) {
                e.printStackTrace()
            }
        }
    }

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

    override fun provideDataSingle(page: Int): Single<MutableList<GameEntity>> {
        val isNetworkConnected = NetworkUtils.isNetworkConnected(HaloApp.getInstance())
        return if (isNetworkConnected) {
            mApi.getSimulatorGames(HaloApp.getInstance().gid, page, getFilter())
        } else {
            mSimulatorGameDao.getSimulatorGameWithOffset(type, 40, (page - 1) * 40)
                .map { simulatorGameList ->
                    val gameEntities = ArrayList<GameEntity>()
                    simulatorGameList.forEach {
                        gameEntities.add(it.convertSimulatorGameRecordEntityToGameEntity())
                    }
                    gameEntities
                }
        }
    }

    private fun getFilter(): String {
        return UrlFilterUtils.getFilterQuery("type", type)
    }

    private fun addGamePositionAndPackage(game: GameEntity, position: Int) {
        var packages = ""
        for (apkEntity in game.getApk()) {
            packages += apkEntity.packageName
        }
        packages += game.simulator?.apk?.packageName
        positionAndPackageMap[packages + position] = position
        game.gameLocation = GameEntity.GameLocation.INDEX
        game.setEntryMap(DownloadManager.getInstance().getEntryMap(game.name))
    }


    class Factory(
        private val mApplication: Application,
        private val mType: String
    ) : ViewModelProvider.NewInstanceFactory() {
        override fun <T : ViewModel> create(modelClass: Class<T>): T {
            return SimulatorGameListViewModel(mApplication, mType) as T
        }
    }
}