package com.gh.gamecenter.va

import android.app.Activity
import android.content.ContentValues
import android.content.Context
import android.net.Uri
import android.os.Build
import android.util.Log
import com.blankj.utilcode.util.FileUtils
import com.gh.gamecenter.common.exposure.meta.MetaUtil
import com.gh.gamecenter.va.impl.BuildConfig
import com.gh.gamecenter.va.provider.IVa
import com.gh.gamecenter.va.remote.InstalledAppInfo
import com.gh.gamecenter.va.remote.VaInstallResult
import com.lg.common.utils.SPUtils
import com.lg.core.common.log.LogConstants
import com.lg.core.common.log.NewFlatLogUtils
import com.lg.vspace.archive.ArchiveExtHelper
import com.lg.vspace.archive.common.ui.interfaces.ArchiveProgressPageListener
import com.lg.vspace.archive.ui.ArchiveManager
import com.lg.vspace.archive.ui.utils.ArchiveUtils
import com.lg.vspace.common.Constants
import com.lg.vspace.common.db.GameConfigDB
import com.lg.vspace.meta.ProcessUtils
import com.lg.vspace.plugin.host.PluginFileUtils
import com.lg.vspace.plugin.host.PluginHelper
import com.lg.vspace.ui.launcher.LaunchActivity
import com.lg.vspace.utils.FilterInstallPackage
import com.lody.virtual.client.core.VirtualCore
import com.lody.virtual.client.ipc.VActivityManager
import com.lody.virtual.os.VEnvironment
import com.lody.virtual.remote.VAppInstallerParams
import com.lody.virtual.remote.VAppInstallerResult
import com.va.host.HostUtils
import com.walkud.rom.checker.RomIdentifier
import java.io.File

/**
 * 调用方负责异常
 */
@com.therouter.inject.ServiceProvider
class Va : IVa {
    override fun isFakeVa(): Boolean = false

    override fun installPackage(path: String?): VaInstallResult {
        if (path.isNullOrEmpty()) {
            return VaInstallResult(
                status = VAppInstallerResult.STATUS_FAILURE_INVALID_PATH,
                errorMessage = "安装函数输入参数path为空"
            )
        }
        val result = try {
            VirtualCore.get().installPackage(
                Uri.fromFile(File(path)),
                VAppInstallerParams(VAppInstallerParams.FLAG_INSTALL_OVERRIDE_NO_CHECK)
            ) ?: VAppInstallerResult.create(VAppInstallerResult.STATUS_FAILURE_RETURN_NULL_OBJECT, "安装返回空对象")
        } catch (e: Exception) {
            VAppInstallerResult.create(
                VAppInstallerResult.STATUS_FAILURE_RUNTIME_EXCEPTION,
                "安装异常，堆栈信息：" + Log.getStackTraceString(e)
            )
        }
        return VaInstallResult(status = result.status, errorMessage = result.errorMessage)
    }

    override fun getInstalledApps(source: List<InstalledAppInfo>): List<InstalledAppInfo> = try {
        VirtualCore.get().getInstalledApps(0)?.filter { !FilterInstallPackage.Companion.check(it.packageName) }
            ?.map {
                InstalledAppInfo(packageName = it.packageName, is64bit = it.is64bit)
            } ?: source
    } catch (ignore: Exception) {
        source
    }

    override fun unInstallPackage(packageName: String): Boolean {
        VirtualCore.get().uninstallPackage(packageName)
        // 卸载不管是否成功都删掉
        SPUtils.remove(packageName + Constants.KEY_APP_TOTAL_TIME)
        GameConfigDB.Companion.getDatabase(VirtualCore.get().context).gameConfigDao().deleteGameConfig(packageName)
        // FIXME: 32在安装之前先判断是更新还是安装，安装则删除/更新不删除 appTotalTime
        return true
    }

    override fun getGameAppTotalTime(packageName: String): Long =
        SPUtils.getLong(packageName + Constants.KEY_APP_TOTAL_TIME, 0L)

    override fun getAppOccupiedSpace(packageName: String): Long {
        var fsAvailableSize: Long = 0
        val userId = 0

        val dataAppPath = VEnvironment.getDataAppPackageDirectory(packageName).path
        val dataUserPath = VEnvironment.buildPath(VEnvironment.getDataUserDirectory(userId), packageName).absolutePath
        val sdcardAndroidData = VEnvironment.getExternalVirtualAndroidDataPackage(packageName, userId).path
        val sdcardAndroidObb = VEnvironment.getExternalVirtualAndroidObbPackage(packageName, userId).path

        fsAvailableSize += FileUtils.getLength(dataAppPath)
        fsAvailableSize += FileUtils.getLength(dataUserPath)
        fsAvailableSize += FileUtils.getLength(sdcardAndroidData)
        fsAvailableSize += FileUtils.getLength(sdcardAndroidObb)
        return fsAvailableSize
    }

    override fun isAppInstalled(packageName: String): Boolean = try {
        VirtualCore.get().isAppInstalled(packageName)
    } catch (_: Exception) {
        false
    }

    override fun launchApp(packageName: String): Boolean = try {
        VActivityManager.get().launchApp(0, packageName)
    } catch (_: Exception) {
        false
    }


    override fun cleanPackageData(packageName: String): Boolean = try {
        VirtualCore.get().cleanPackageData(packageName, 0)
    } catch (ignore: Exception) {
        false
    }

    override fun isExtPackageInstalled(): Boolean = VirtualCore.get().isExtPackageInstalled

    override fun isLaunchActivity(activity: Activity): Boolean = activity is LaunchActivity

    override fun <T> useArchive(
        context: Context,
        packageName: String,
        archiveFile: T,
        archiveConfig: String?,
        listener: ArchiveProgressPageListener
    ) = ArchiveManager.useArchive(context, packageName, archiveFile, archiveConfig, listener)

    override fun <T> generatePackage(
        context: Context,
        packageName: String,
        archiveConfig: String,
        archiveFile: T,
        listener: ArchiveProgressPageListener
    ) = ArchiveManager.generatePackage(context, packageName, archiveConfig, archiveFile, listener)

    override fun checkGameArchiveExists(
        packageName: String,
        archiveConfigJsonStr: String,
        isRunInExt: Boolean
    ): Boolean = if (isRunInExt) {
        ArchiveExtHelper.checkGameArchiveExists(packageName, archiveConfigJsonStr)
    } else {
        ArchiveUtils.checkGameArchiveExists(packageName, archiveConfigJsonStr)
    }

    override fun getPluginVersion(): String = HostUtils.getPluginVersion() ?: ""

    override fun getCwBaseLogParams(
        gid: String,
        oaid: String,
        hostVersion: String,
        hostChannel: String,
    ): Map<String, String> = mapOf(
        LogConstants.KEY_ANDROID_VERSION to Build.VERSION.RELEASE,
        LogConstants.KEY_APP_64_VERSION to com.lg.vspace.BuildConfig.VERSION_NAME,
        LogConstants.KEY_APP_32_VERSION to "",
        LogConstants.KEY_VA_VERSION to HostUtils.getPluginVersion(),
        LogConstants.KEY_ARCHITECTURE to if (ProcessUtils.is64Bit()) "64" else "32",
        LogConstants.KEY_DIA to MetaUtil.getBase64EncodedAndroidId(),
        LogConstants.KEY_GID to gid,
        LogConstants.KEY_JNFJ to "",
        LogConstants.KEY_MAC to "",
        LogConstants.KEY_MANUFACTURER to Build.MANUFACTURER,
        LogConstants.KEY_MODEL to Build.MODEL,
        LogConstants.KEY_NETWORK to (MetaUtil.getMeta().network ?: ""),
        LogConstants.KEY_ROM to RomIdentifier.getRom().name + " " + RomIdentifier.getRom().versionName,
        LogConstants.KEY_HOST_VERSION to hostVersion,
        LogConstants.KEY_HOST_CHANNEL to hostChannel,
        LogConstants.KEY_OAID to oaid,
    )

    override fun getUriAuthorizationString(): String = com.va.host.Constants.getUriAuthorizationString()

    override fun getAuthContentValue(token: String, userName: String?, userAvatar: String?): ContentValues =
        ContentValues().apply {
            put(com.va.host.Constants.KEY_TOKEN, token)
            put(com.va.host.Constants.KEY_USER_NAME, userName)
            put(com.va.host.Constants.KEY_USER_AVATAR, userAvatar)
        }

    override fun logBeforeGameLaunch(kv: Map<String, String>) = NewFlatLogUtils.logBeforeGameLaunch(kv)

    override fun getPluginUpdateFileName(id: String): String = PluginHelper.getInstance().getPluginUpdateFileName(id)

    override fun isZipFile(file: File): Boolean = PluginFileUtils.isZipFile(file)
    override fun getDefaultPluginUrl(): String = BuildConfig.DEFAULT_PLUGIN_URL

}