package com.dphms.optimizer.lite

import java.util.Locale
import android.app.PendingIntent
import android.appwidget.AppWidgetManager
import android.appwidget.AppWidgetProvider
import android.content.ComponentName
import android.content.Context
import android.content.Intent
import android.os.Build
import android.widget.RemoteViews
import androidx.core.content.ContextCompat
import java.io.BufferedReader
import java.io.InputStreamReader

class DPHMSWidgetProvider : AppWidgetProvider() {

    companion object {
        const val ACTION_WIDGET_STOP = "com.dphms.optimizer.lite.WIDGET_STOP"
        const val ACTION_WIDGET_CLEAR = "com.dphms.optimizer.lite.WIDGET_CLEAR"
        const val ACTION_UPDATE_WIDGET = "com.dphms.optimizer.lite.UPDATE_WIDGET"

        fun updateWidget(context: Context, appWidgetManager: AppWidgetManager, appWidgetId: Int,
                         ramText: String, storageText: String, resultText: String = "") {
            val views = RemoteViews(context.packageName, R.layout.widget_dphms)
            views.setTextViewText(R.id.widget_ram_text, ramText)
            views.setTextViewText(R.id.widget_storage_text, storageText)
            if (resultText.isNotEmpty()) {
                views.setTextViewText(R.id.widget_result_text, resultText)
            } else {
                views.setTextViewText(R.id.widget_result_text, "")
            }

            val stopIntent = Intent(context, DPHMSWidgetProvider::class.java).apply {
                action = ACTION_WIDGET_STOP
                data = android.net.Uri.parse("widget://$appWidgetId/stop")
            }
            val stopPI = PendingIntent.getBroadcast(context, appWidgetId, stopIntent,
                PendingIntent.FLAG_UPDATE_CURRENT or PendingIntent.FLAG_IMMUTABLE)
            views.setOnClickPendingIntent(R.id.widget_btn_stop, stopPI)

            val clearIntent = Intent(context, DPHMSWidgetProvider::class.java).apply {
                action = ACTION_WIDGET_CLEAR
                data = android.net.Uri.parse("widget://$appWidgetId/clear")
            }
            val clearPI = PendingIntent.getBroadcast(context, appWidgetId + 1, clearIntent,
                PendingIntent.FLAG_UPDATE_CURRENT or PendingIntent.FLAG_IMMUTABLE)
            views.setOnClickPendingIntent(R.id.widget_btn_clear, clearPI)

            appWidgetManager.updateAppWidget(appWidgetId, views)
        }

        fun updateAllWidgets(context: Context) {
            val mgr = AppWidgetManager.getInstance(context)
            val ids = mgr.getAppWidgetIds(ComponentName(context, DPHMSWidgetProvider::class.java))
            for (id in ids) {
                updateWidget(context, mgr, id, getRamString(context), getStorageString(context))
            }
        }

        private fun getRamString(context: Context): String {
            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 used = (total - avail) / 1024
                "${used}/${total / 1024} MB"
            } catch (e: Exception) { "RAM: N/A" }
        }

        private fun getStorageString(context: Context): String {
            return try {
                val stat = android.os.StatFs(android.os.Environment.getDataDirectory().path)
                val free = stat.availableBytes / (1024.0 * 1024 * 1024)
                val total = stat.totalBytes / (1024.0 * 1024 * 1024)
                String.format(Locale.US, "%.1f / %.1f GB", free, total)
            } catch (e: Exception) { "Storage: N/A" }
        }
    }

    override fun onUpdate(context: Context, mgr: AppWidgetManager, ids: IntArray) {
        for (id in ids) updateWidget(context, mgr, id, getRamString(context), getStorageString(context))
    }

    override fun onReceive(context: Context, intent: Intent) {
        super.onReceive(context, intent)
        when (intent.action) {
            ACTION_WIDGET_STOP -> {
                val svc = Intent(context, OptimizerService::class.java).apply {
                    action = OptimizerService.ACTION_WIDGET_STOP
                    if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O)
                        ContextCompat.startForegroundService(context, this)
                    else context.startService(this)
                }
            }
            ACTION_WIDGET_CLEAR -> {
                val svc = Intent(context, OptimizerService::class.java).apply {
                    action = OptimizerService.ACTION_WIDGET_CLEAR
                    if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O)
                        ContextCompat.startForegroundService(context, this)
                    else context.startService(this)
                }
            }
            ACTION_UPDATE_WIDGET -> updateAllWidgets(context)
        }
    }
}
