package tk.zwander.common.compose.util

import android.annotation.SuppressLint
import android.appwidget.AppWidgetHostView
import android.appwidget.AppWidgetProviderInfo
import android.content.Context
import android.content.Context.CONTEXT_INCLUDE_CODE
import dev.zwander.lswinterconnect.safeApplicationContext
import tk.zwander.common.host.widgetHostCompat
import tk.zwander.common.util.RemoteViewsLayoutInflaterContext
import tk.zwander.common.util.andRemoveFromParent
import tk.zwander.common.util.logUtils
import tk.zwander.common.util.themedContext

val Context.widgetViewCacheRegistry: WidgetViewCacheRegistry
    get() = WidgetViewCacheRegistry.getInstance(this)

class WidgetViewCacheRegistry private constructor(@Suppress("unused") private val context: Context) {
    companion object {
        @SuppressLint("StaticFieldLeak")
        private var instance: WidgetViewCacheRegistry? = null

        @Synchronized
        fun getInstance(context: Context): WidgetViewCacheRegistry {
            return instance ?: WidgetViewCacheRegistry(context.safeApplicationContext).also {
                instance = it
            }
        }
    }

    private val cachedViews = HashMap<Int, AppWidgetHostView>()

    fun getOrCreateView(context: Context, appWidgetId: Int, appWidget: AppWidgetProviderInfo): AppWidgetHostView {
        return cachedViews.getOrPut(appWidgetId) {
            val widgetContext = try {
                RemoteViewsLayoutInflaterContext(
                    context.safeApplicationContext.createContextAsUser(
                        appWidget.profile,
                        CONTEXT_INCLUDE_CODE or Context.CONTEXT_IGNORE_SECURITY,
                    ).themedContext.createApplicationContext(
                        appWidget.providerInfo.applicationInfo,
                        CONTEXT_INCLUDE_CODE or Context.CONTEXT_IGNORE_SECURITY,
                    ),
                    appWidgetId,
                )
            } catch (e: Throwable) {
                context.logUtils.debugLog("Unable to create application context for " +
                        "${appWidget.providerInfo.applicationInfo.packageName}", e)
                null
            }

            context.widgetHostCompat.createView(
                widgetContext ?: context, appWidgetId, appWidget,
            )
        }.andRemoveFromParent()
    }

    fun removeView(appWidgetId: Int) {
        cachedViews.remove(appWidgetId)
    }
}
