package com.dphms.optimizer.lite

import android.os.Environment
import android.os.StatFs
import java.io.BufferedReader
import java.io.InputStreamReader

class SystemOptimizer(private val service: IOptimizerService) {

    data class RamInfo(val totalMb: Long, val freeMb: Long, val usedMb: Long)
    data class StorageInfo(val totalGb: Double, val freeGb: Double, val usedGb: Double)

    private val excludedPackages = setOf(
        "com.dphms.optimizer.lite", "moe.shizuku.privileged.api",
        "android", "com.android.systemui", "com.android.phone",
        "com.android.settings", "com.android.launcher3",
        "com.google.android.inputmethod", "com.motorola.launcher3",
        "com.motorola.systemui"
    )

    fun getRamInfo(): RamInfo {
        return try {
            val reader = BufferedReader(InputStreamReader(
                Runtime.getRuntime().exec(arrayOf("sh", "-c", "cat /proc/meminfo")).inputStream))
            var total = 0L
            var avail = 0L
            var line: String?
            while (reader.readLine().also { line = it } != null) {
                val l = line ?: continue
                if (l.startsWith("MemTotal:")) {
                    total = l.split(Regex("\\s+"))[1].toLong()
                } else if (l.startsWith("MemAvailable:")) {
                    avail = l.split(Regex("\\s+"))[1].toLong()
                }
            }
            reader.close()
            val totalMb = total / 1024
            val freeMb = avail / 1024
            RamInfo(totalMb, freeMb, totalMb - freeMb)
        } catch (e: Exception) {
            RamInfo(0, 0, 0)
        }
    }

    fun getStorageInfo(): StorageInfo {
        return try {
            val stat = StatFs(Environment.getDataDirectory().path)
            val total = stat.totalBytes
            val free = stat.availableBytes
            StorageInfo(
                total / (1024.0 * 1024 * 1024),
                free / (1024.0 * 1024 * 1024),
                (total - free) / (1024.0 * 1024 * 1024)
            )
        } catch (e: Exception) {
            StorageInfo(0.0, 0.0, 0.0)
        }
    }

    suspend fun stopAllApps(onProgress: (current: Int, total: Int, packageName: String) -> Unit): Int {
        val packages = service.listPackages().filter { it !in excludedPackages }
        var stopped = 0
        for (pkg in packages) {
            service.forceStopPackage(pkg)
            stopped++
            onProgress(stopped, packages.size, pkg)
        }
        return stopped
    }

    suspend fun clearAllCaches(): Boolean {
        return service.trimCaches()
    }
}
