package app

import (
	

	
)

// Notification represents a user notification.
type Notification struct {
	// The title displayed prominently at the top of the notification.
	Title string `json:"title"`

	// Path is the URL to navigate to upon clicking the notification.
	Path string `json:"path"`

	// Lang specifies the notification's language, using ISO 2-letter codes.
	// See: https://www.sitepoint.com/iso-2-letter-language-codes
	Lang string `json:"lang,omitempty"`

	// Badge is the URL of an image to represent the notification when space
	// is limited.
	Badge string `json:"badge,omitempty"`

	// Body is the main content, displayed below the title.
	Body string `json:"body,omitempty"`

	// Tag provides a unique identifier for the notification.
	Tag string `json:"tag,omitempty"`

	// Icon is the URL of an icon shown in the notification.
	Icon string `json:"icon,omitempty"`

	// Image is the URL of an image displayed in the notification.
	Image string `json:"image,omitempty"`

	// Data contains arbitrary data associated with the notification.
	// Note: "goapp" key is reserved for go-app data.
	Data map[string]any `json:"data"`

	// Renotify determines if the user should be notified when a new
	// notification replaces an existing one.
	Renotify bool `json:"renotify,omitempty"`

	// RequireInteraction ensures the notification remains active until
	// the user acts on it, not closing automatically.
	RequireInteraction bool `json:"requireInteraction,omitempty"`

	// Silent specifies if the notification should be silent, suppressing
	// all sounds and vibrations, regardless of device settings.
	Silent bool `json:"silent,omitempty"`

	// Vibrate defines a vibration pattern for the device upon notification.
	// See: https://developer.mozilla.org/en-US/docs/Web/API/Vibration_API
	Vibrate []int `json:"vibrate,omitempty"`

	// Actions lists the available actions displayed within the notification.
	Actions []NotificationAction `json:"actions,omitempty"`
}

// NotificationAction represents an actionable item within a notification.
type NotificationAction struct {
	// Action is the unique ID associated with the user's action on
	// the notification.
	Action string `json:"action"`

	// Title is the descriptive text shown alongside the action.
	Title string `json:"title"`

	// Icon is the URL of an image to represent the action.
	Icon string `json:"icon,omitempty"`

	// Path is the URL to navigate to upon clicking the action.
	Path string `json:"path"`
}

// NotificationSubscription encapsulates a PushSubscription from the Push API.
type NotificationSubscription struct {
	// Endpoint is the push service endpoint URL.
	Endpoint string `json:"endpoint"`

	// Keys contains cryptographic keys used for the subscription.
	Keys struct {
		// Auth is the authentication secret.
		Auth string `json:"auth"`

		// P256dh is the user's public key, associated with the push
		// subscription.
		P256dh string `json:"p256dh"`
	} `json:"keys"`
}

// NotificationPermission represents permission levels for displaying
// notifications to users.
type NotificationPermission string

const (
	// NotificationDefault indicates the user's choice for notifications is
	// unknown, prompting the browser to treat it as "denied".
	NotificationDefault NotificationPermission = "default"

	// NotificationGranted means the user has allowed notifications.
	NotificationGranted NotificationPermission = "granted"

	// NotificationDenied means the user has declined notifications.
	NotificationDenied NotificationPermission = "denied"

	// NotificationNotSupported indicates that the browser doesn't support
	// notifications.
	NotificationNotSupported NotificationPermission = "unsupported"
)

// NotificationService provides functionalities related to user notifications.
type NotificationService struct{}

// Permission retrieves the current notification permission status.
func ( NotificationService) () NotificationPermission {
	 := Window().Get("Notification")
	if !.Truthy() {
		return NotificationNotSupported
	}

	return NotificationPermission(.Get("permission").String())
}

// RequestPermission prompts the user for permission to display notifications.
func ( NotificationService) () NotificationPermission {
	 := Window().Get("Notification")
	if !.Truthy() {
		return NotificationNotSupported
	}

	 := make(chan string, 1)
	defer close()

	.Call("requestPermission").Then(func( Value) {
		 <- .String()
	})

	return NotificationPermission(<-)
}

// New creates and displays a notification to the user.
func ( NotificationService) ( Notification) {
	,  := json.Marshal()
	Window().Call("goappNewNotification", string())
}

// Subscribe retrieves a notification subscription using the provided VAPID
// public key. If the key is empty or push notifications aren't supported, an
// error is returned.
func ( NotificationService) ( string) (NotificationSubscription, error) {
	if  == "" {
		return NotificationSubscription{}, errors.New("vapid public key is empty")
	}

	 := make(chan string, 1)
	defer close()

	Window().Call("goappSubscribePushNotifications", ).Then(func( Value) {
		 <- .String()
	})

	 := <-
	if  == "" {
		return NotificationSubscription{}, errors.
			New("push notifications are not supported by the browser")
	}

	var  NotificationSubscription
	 := json.Unmarshal([]byte(), &)
	if  != nil {
		return NotificationSubscription{}, errors.
			New("failed to decode push notification subscription").Wrap()
	}
	return , nil
}