package com.xyzshell.andinfo.libs

import android.content.Context
import android.os.Environment
import android.os.StatFs
import com.xyzshell.andinfo.libs.storage.models.EncryptionType
import com.xyzshell.andinfo.utils.SystemProperties

class StorageInfo(private val context: Context) {

    val internalStorageTotalSpace: Long
        get() = StatFs(Environment.getDataDirectory().absolutePath).let { statFs ->
            statFs.blockCountLong * statFs.blockSizeLong
        }

    val internalStorageAvailableSpace: Long
        get() = StatFs(Environment.getDataDirectory().absolutePath).let { statFs ->
            statFs.availableBlocksLong * statFs.blockSizeLong
        }

    val internalStorageUsedSpace: Long
        get() = internalStorageTotalSpace - internalStorageAvailableSpace

    val isInternalStorageEncrypted: Boolean?
        get() = when (SystemProperties.getString("ro.crypto.state", "unknown")) {
            "encrypted" -> true
            "unencrypted" -> false
            else -> null
        }

    val internalStorageEncryptionType: EncryptionType?
        get() = when (SystemProperties.getString("ro.crypto.type", "unknown")) {
            "none" -> EncryptionType.NONE
            "block" -> EncryptionType.FDE
            "file" -> EncryptionType.FBE
            else -> null
        }

    val externalStorageTotalSpace: Long?
        get() = runCatching {
            StatFs(Environment.getExternalStorageDirectory().absolutePath).let { statFs ->
                statFs.blockCountLong * statFs.blockSizeLong
            }
        }.getOrNull()

    val externalStorageAvailableSpace: Long?
        get() = runCatching {
            StatFs(Environment.getExternalStorageDirectory().absolutePath).let { statFs ->
                statFs.availableBlocksLong * statFs.blockSizeLong
            }
        }.getOrNull()

    val externalStorageUsedSpace: Long?
        get() = externalStorageTotalSpace?.let { total ->
            externalStorageAvailableSpace?.let { available ->
                total - available
            }
        }

    val isExternalStorageEmulated: Boolean
        get() = Environment.isExternalStorageEmulated()

    val isExternalStorageRemovable: Boolean
        get() = Environment.isExternalStorageRemovable()

    val hasUpdatableApex: Boolean?
        get() = SystemProperties.getBoolean("ro.apex.updatable")

    val usesSystemAsRoot: Boolean?
        get() = SystemProperties.getBoolean("ro.build.system_root_image")

    val usesAb: Boolean?
        get() = SystemProperties.getBoolean("ro.build.ab_update")

    val abOtaPartitions: Array<String>?
        get() = SystemProperties.getString("ro.product.ab_ota_partitions")?.split(",")?.toTypedArray()

    val usesDynamicPartitions: Boolean?
        get() = SystemProperties.getBoolean("ro.boot.dynamic_partitions")

    val usesRetrofittedDynamicPartitions: Boolean?
        get() = SystemProperties.getBoolean("ro.boot.dynamic_partitions_retrofit")

    val usesVirtualAb: Boolean?
        get() = SystemProperties.getBoolean("ro.virtual_ab.enabled")

    val usesRetrofittedVirtualAb: Boolean?
        get() = SystemProperties.getBoolean("ro.virtual_ab.retrofit")

    val usesCompressedVirtualAb: Boolean?
        get() = SystemProperties.getBoolean("ro.virtual_ab.compression.enabled")
}
