package de.jeanlucmakiola.calendula.domain

import kotlin.time.Instant

data class CalendarSource(
    val id: Long,
    val displayName: String,
    val accountName: String,
    val accountType: String,
    val color: Int,
    val isVisibleInSystem: Boolean,
    /**
     * Whether events in this calendar can be created/edited/deleted
     * (`Calendars.CALENDAR_ACCESS_LEVEL` >= contributor). False for WebCal
     * subscriptions, birthday calendars and other read-only sources.
     */
    val canModifyContents: Boolean = false,
    /**
     * A device-only calendar the app itself owns (`ACCOUNT_TYPE_LOCAL`): it has
     * no sync backend, so the app can rename / recolor / delete it. Synced
     * calendars (Google, DAVx5, …) are managed in their own source app instead.
     */
    val isLocal: Boolean = false,
    /**
     * Free-text note for a local calendar (stored in `CAL_SYNC1`, which the app
     * owns for its own calendars). Always null for synced calendars.
     */
    val description: String? = null,
)

data class EventInstance(
    val instanceId: Long,
    val eventId: Long,
    val calendarId: Long,
    val title: String,
    val start: Instant,
    val end: Instant,
    val isAllDay: Boolean,
    val color: Int,
    val location: String?,
)

data class EventDetail(
    val instance: EventInstance,
    val description: String?,
    val organizer: String?,
    val attendees: List<Attendee>,
    val rrule: String?,
    /** Reminders (VALARM) configured on the event, ascending lead time. */
    val reminders: List<Reminder> = emptyList(),
    /** Confirmed / Tentative / Cancelled (`Events.STATUS`). */
    val status: EventStatus = EventStatus.Confirmed,
    /** Busy / Free (`Events.AVAILABILITY`, the iCal TRANSP field). */
    val availability: Availability = Availability.Busy,
    /** Default / Private / Confidential / Public (`Events.ACCESS_LEVEL`). */
    val accessLevel: AccessLevel = AccessLevel.Default,
    /** Raw zone id (`Events.EVENT_TIMEZONE`), e.g. "Europe/Berlin"; null if unset. */
    val eventTimezone: String? = null,
    /** This device user's own response (`Events.SELF_ATTENDEE_STATUS`). */
    val selfStatus: AttendeeStatus = AttendeeStatus.Unknown,
    /**
     * The event's own raw colour (`Events.EVENT_COLOR`), null when the event
     * inherits its calendar's colour. Unlike [EventInstance.color] (which
     * already folds in the calendar fallback for display) this stays null so
     * the edit form can tell "has own colour" from "inherits".
     */
    val eventColor: Int? = null,
    /** The event's `Events.EVENT_COLOR_KEY` (a calendar-palette key), or null. */
    val eventColorKey: String? = null,
)

/**
 * One selectable event colour published by a calendar's account
 * (`CalendarContract.Colors`, `TYPE_EVENT`): [key] is the account-scoped
 * `COLOR_KEY` written as `EVENT_COLOR_KEY` (so the colour survives sync),
 * [argb] is the swatch it renders as.
 */
data class EventColorOption(val key: String, val argb: Int)

data class Attendee(
    val name: String,
    val email: String?,
    val status: AttendeeStatus,
    /** Organizer / performer / speaker / plain attendee (`ATTENDEE_RELATIONSHIP`). */
    val relationship: AttendeeRelationship = AttendeeRelationship.None,
    /** Required / optional / resource (`ATTENDEE_TYPE`). */
    val type: AttendeeType = AttendeeType.None,
)

data class Reminder(
    /** Lead time before the event start, in minutes. `-1` means the provider default. */
    val minutes: Int,
    val method: ReminderMethod,
)

enum class AttendeeStatus {
    Accepted,
    Declined,
    Tentative,
    NeedsAction,
    Unknown,
}

enum class AttendeeRelationship {
    Organizer,
    Attendee,
    Performer,
    Speaker,
    None,
}

enum class AttendeeType {
    Required,
    Optional,
    Resource,
    None,
}

enum class ReminderMethod {
    Alert,
    Email,
    Sms,
    Alarm,
    Default,
}

enum class EventStatus {
    Confirmed,
    Tentative,
    Cancelled,
}

enum class Availability {
    Busy,
    Free,
    Tentative,
}

enum class AccessLevel {
    Default,
    Public,
    Private,
    Confidential,
}

/**
 * How far a write to a recurring event reaches. Non-recurring events always
 * use [AllEvents] (there is only one).
 */
enum class RecurringWriteScope {
    ThisEvent,
    ThisAndFollowing,
    AllEvents,
}

enum class FailureReason {
    PermissionRevoked,
    NoCalendarsConfigured,
    ProviderUnavailable,
    EventNotFound,
    Unknown,
}
