package com.soulstream.transfernotice

import android.Manifest
import android.app.Activity
import android.content.pm.PackageManager
import android.os.Build
import androidx.core.app.ActivityCompat
import androidx.core.content.ContextCompat
import app.tauri.annotation.Command
import app.tauri.annotation.InvokeArg
import app.tauri.annotation.TauriPlugin
import app.tauri.plugin.Invoke
import app.tauri.plugin.JSObject
import app.tauri.plugin.Plugin

/** What the notice says — the Rust `TransferNotice`, camelCase. */
@InvokeArg
class NoticeArgs {
    /** how many files are still in flight; zero means take the notice down */
    var count: Int = 0
    var title: String? = null
    var line: String? = null
    var percent: Int = 0
    /** nobody has stated a size yet, so the bar has no end to walk towards */
    var indeterminate: Boolean = false
}

/**
 * The bridge between the WebView and the service that owns the notice.
 * `update` mirrors what Save is fetching (and starts the service the first
 * time); `clear` takes the notice down. Its buttons come back as the plugin
 * event `action` with `{ action }` — "cancel" or "open".
 */
@TauriPlugin
class TransferNoticePlugin(private val activity: Activity) : Plugin(activity) {
    private var askedForNotifications = false

    init {
        TransferHub.onAction = { action ->
            val payload = JSObject()
            payload.put("action", action)
            trigger("action", payload)
        }
        /* the channel exists from app start, so a user can silence the
           downloads on their own before the first one ever runs */
        TransferHub.ensureChannel(activity.applicationContext)
    }

    @Command
    fun update(invoke: Invoke) {
        val args = invoke.parseArgs(NoticeArgs::class.java)
        ensureNotificationPermission()
        TransferHub.update(activity.applicationContext, args)
        invoke.resolve()
    }

    @Command
    fun clear(invoke: Invoke) {
        TransferHub.clear(activity.applicationContext)
        invoke.resolve()
    }

    /** Android 13+: the notice is a notification and needs the permission;
     *  asked once, the first time something is fetched. Its own request code
     *  — 4711 is the media card's, and two requests that share one would
     *  answer each other. The service runs either way; without the
     *  permission it simply has nothing to show. */
    private fun ensureNotificationPermission() {
        if (Build.VERSION.SDK_INT < 33 || askedForNotifications) return
        askedForNotifications = true
        if (ContextCompat.checkSelfPermission(activity, Manifest.permission.POST_NOTIFICATIONS)
            == PackageManager.PERMISSION_GRANTED
        ) return
        ActivityCompat.requestPermissions(activity, arrayOf(Manifest.permission.POST_NOTIFICATIONS), 4712)
    }
}
