package com.rc.core.util

import android.content.ComponentName
import android.content.Context
import android.content.Intent
import android.net.Uri
import android.os.Build
import android.os.Process
import androidx.core.content.FileProvider
import com.rc.core.ui.ActivityCollector
import java.io.*
import java.nio.charset.Charset
import kotlin.system.exitProcess

/**
 * info
 *
 * @author ReiChin_
 */
object ApkController {

    fun installAPK(
        apkFile: File,
        appContext: Context,
        applicationId: String
    ) {
        if (isRootPermission()) {
            install(apkFile.path)
//            startApp("com.dlc.eboard", "com.dlc.eboard.ui.SplashActivity")
            startApp(appContext, "com.dlc.eboard", "com.dlc.eboard.ui.SplashActivity")
            // silentInstall(appContext, apkFile.path)
        } else {
            installOnTask(apkFile, appContext, applicationId)
        }
    }

    /**
     * 判定app是否获取root权限
     */
    fun isRootPermission(): Boolean {
        try {
            val process = Runtime.getRuntime().exec("su")
            val os = DataOutputStream(process.outputStream)
            os.writeBytes("ls /data/data/\n")
            os.writeBytes("exit\n")
            os.flush()
            val reader = BufferedReader(InputStreamReader(process.inputStream))
            val builder = StringBuilder()
            var line: String? = null
            while (reader.readLine().also { line = it } != null) {
                builder.append(line)
                builder.append(System.getProperty("line.separator"))
            }
            val result = builder.toString()
            if (result.contains("com.android.phone")) {
                return true
            }
        } catch (e: IOException) {
            return false
        }
        return false
    }

    /**
     * 安装apk
     */
    fun install(apkPath: String): Boolean {
        var result = false
        var dataOutputStream: DataOutputStream? = null
        var errorStream: BufferedReader? = null
        try {
            val process = Runtime.getRuntime().exec("su")
            dataOutputStream = DataOutputStream(process.outputStream)
            val command = "pm install -r $apkPath\n"
            dataOutputStream.write(command.toByteArray(Charset.forName("utf-8")))
            dataOutputStream.flush()
            dataOutputStream.writeBytes("exit\n")
            dataOutputStream.flush()
            process.waitFor()
            errorStream = BufferedReader(InputStreamReader(process.errorStream))
            var msg = ""
            var line: String
            while (errorStream.readLine().also { line = it } != null) {
                msg += line
            }
            if (!msg.contains("Failure")) {
                result = true
            }
        } catch (e: Exception) {
            e.printStackTrace()
        } finally {
            try {
                dataOutputStream?.close()
                errorStream?.close()
            } catch (e: IOException) {
            }
        }
        return result
    }

    fun startApp(appContext: Context, pkg: String, cls: String) {
        val intent = Intent.makeRestartActivityTask(ComponentName(pkg, cls))
        appContext.startActivity(intent)
        exitProcess(0)
    }

    /**
     * 启动app
     */
    fun startApp(packageName: String, activityName: String): Boolean {
        var result = false
        var dataOutputStream: DataOutputStream? = null
        var errorStream: BufferedReader? = null
        try {
            val process = Runtime.getRuntime().exec("su")
            dataOutputStream = DataOutputStream(process.outputStream)
            val command = "sleep 120; am start -n $packageName/$activityName\n"
            dataOutputStream.write(command.toByteArray(Charset.forName("utf-8")))
            dataOutputStream.flush()
            dataOutputStream.writeBytes("exit\n")
            dataOutputStream.flush()
            process.waitFor()
            errorStream = BufferedReader(InputStreamReader(process.errorStream))
            var msg = ""
            var line: String
            while (errorStream.readLine().also { line = it } != null) {
                msg += line
            }
            if (!msg.contains("Failure")) {
                result = true
            }
        } catch (e: Exception) {
            e.printStackTrace()
        } finally {
            try {
                dataOutputStream?.close()
                errorStream?.close()
            } catch (e: IOException) {
            }
        }
        return result
    }

    /**
     * 静默安装
     *
     * @param context
     * @param apkPath
     * @param autoStart 安装后是否自动启动
     */
    fun silentInstall(context: Context, apkPath: String, autoStart: Boolean = true) {
        val intent = Intent().apply {
            action = "android.intent.action.installslient"
            putExtra("uri", apkPath)
            putExtra("component", "com.dlc.eboard/com.dlc.eboard.ui.SplashActivity")
            putExtra("enable", autoStart)
        }
        context.sendBroadcast(intent)
    }

    fun installOnTask(
        apkFile: File,
        appContext: Context,
        applicationId: String
    ) {
        val intent = Intent()
        intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK)
        intent.action = Intent.ACTION_VIEW

        if (apkFile.exists()) {
            // 提升目录读写权限,否则可能出现解析异常
            DeviceUtils.promotePermission(apkFile.parentFile!!.path)
            if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) {
                // 7.0以上的版本，特殊处理
                intent.addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION)
                // 参数1 上下文, 参数2 Provider主机地址 和配置文件中保持一致   参数3  共享的文件
                val uri = FileProvider.getUriForFile(
                    appContext,
                    "${applicationId}.fileprovider",
                    apkFile
                )
                intent.setDataAndType(uri, "application/vnd.android.package-archive")
            } else {
                intent.setDataAndType(
                    Uri.fromFile(apkFile),
                    "application/vnd.android.package-archive"
                )
            }
            appContext.startActivity(intent)
            ActivityCollector.finishAll()
            Process.killProcess(Process.myPid())
        }
    }

}