<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools">

    <uses-permission android:name="android.permission.READ_CALENDAR" />
    <uses-permission android:name="android.permission.WRITE_CALENDAR" />
    <uses-permission android:name="android.permission.POST_NOTIFICATIONS" />
    <!--
      Optional and feature-gated: only the "Contact special dates" feature reads
      contacts, and only after the user enables it and grants this at runtime
      (never requested at startup). Everything stays offline — birthdays and
      other contact dates are mirrored one-way into local calendars; contacts
      are never written and nothing leaves the device (the app has no INTERNET
      permission). See docs/design/contact-special-dates.md.
    -->
    <uses-permission android:name="android.permission.READ_CONTACTS" />
    <!--
      Lets the "Reliable delivery" setting open the direct system dialog to
      exempt Calendula from battery optimisation (so reminder broadcasts aren't
      delayed by Doze). Used only to launch that dialog; falls back to the
      battery-optimisation list if the OS declines the direct intent.
    -->
    <uses-permission android:name="android.permission.REQUEST_IGNORE_BATTERY_OPTIMIZATIONS" />

    <!--
      Re-fire a snoozed reminder at an exact time (the calendar provider won't —
      its alert is already fired). USE_EXACT_ALARM is auto-granted to calendar
      apps on API 33+; SCHEDULE_EXACT_ALARM covers API 31–32 (user-revocable,
      with an inexact fallback if withheld). F-Droid-clean: no Play allowlisting.
    -->
    <uses-permission
        android:name="android.permission.SCHEDULE_EXACT_ALARM"
        android:maxSdkVersion="32" />
    <uses-permission android:name="android.permission.USE_EXACT_ALARM" />

    <!-- Package visibility (Android 11+): without this, getLaunchIntentForPackage
         returns null and the calendar manager's per-account "manage" button can't
         open the source sync app (DAVx5, ICSx5, Google Calendar, …). The LAUNCHER
         intent makes launchable apps visible so we can launch whichever app owns a
         calendar account's authenticator. -->
    <queries>
        <intent>
            <action android:name="android.intent.action.MAIN" />
            <category android:name="android.intent.category.LAUNCHER" />
        </intent>
    </queries>

    <application
        android:name=".CalendulaApp"
        android:allowBackup="true"
        android:enableOnBackInvokedCallback="true"
        android:dataExtractionRules="@xml/data_extraction_rules"
        android:fullBackupContent="@xml/backup_rules"
        android:icon="@mipmap/ic_launcher"
        android:label="@string/app_name"
        android:localeConfig="@xml/locales_config"
        android:roundIcon="@mipmap/ic_launcher_round"
        android:supportsRtl="true"
        android:theme="@style/Theme.Calendula"
        tools:targetApi="35">
        <activity
            android:name=".MainActivity"
            android:exported="true"
            android:launchMode="singleTop"
            android:windowSoftInputMode="adjustResize">
            <intent-filter>
                <action android:name="android.intent.action.MAIN" />
                <category android:name="android.intent.category.LAUNCHER" />
            </intent-filter>

            <!-- Be selectable as the system calendar app. Android has no API for
                 an app to make itself the default, so registering the filters
                 launchers and the OS use is what lets the user pick Calendula
                 from the system chooser when a date action fires (issue #9).
                 APP_CALENDAR is the "open the calendar app" action; the VIEW
                 filters below catch a tapped date. -->
            <intent-filter>
                <action android:name="android.intent.action.MAIN" />
                <category android:name="android.intent.category.DEFAULT" />
                <category android:name="android.intent.category.APP_CALENDAR" />
            </intent-filter>
            <!-- A launcher/clock date tap fires ACTION_VIEW on the provider's
                 time Uri (content://com.android.calendar/time/<epochMillis>);
                 some surfaces use the time/epoch mime type. We open the day view
                 on that date (MainActivity.calendarTimeDateOrNull). -->
            <intent-filter>
                <action android:name="android.intent.action.VIEW" />
                <category android:name="android.intent.category.DEFAULT" />
                <data
                    android:scheme="content"
                    android:host="com.android.calendar"
                    android:pathPrefix="/time" />
            </intent-filter>
            <intent-filter>
                <action android:name="android.intent.action.VIEW" />
                <category android:name="android.intent.category.DEFAULT" />
                <data android:mimeType="time/epoch" />
            </intent-filter>

            <!-- Open a .ics file (file manager / email attachment / browser). -->
            <intent-filter>
                <action android:name="android.intent.action.VIEW" />
                <category android:name="android.intent.category.DEFAULT" />
                <category android:name="android.intent.category.BROWSABLE" />
                <data android:scheme="content" android:mimeType="text/calendar" />
                <data android:scheme="file" android:mimeType="text/calendar" />
            </intent-filter>
            <!-- Receive a .ics shared from another app. -->
            <intent-filter>
                <action android:name="android.intent.action.SEND" />
                <category android:name="android.intent.category.DEFAULT" />
                <data android:mimeType="text/calendar" />
            </intent-filter>

            <!-- Let another app or widget (e.g. the Todo Agenda widget) launch us
                 to create a new event, the way the AOSP calendar accepts it:
                 ACTION_INSERT on the events dir mime type, carrying the new
                 event's fields as CalendarContract extras
                 (MainActivity.insertFormOrNull, issue #30). -->
            <intent-filter>
                <action android:name="android.intent.action.INSERT" />
                <category android:name="android.intent.category.DEFAULT" />
                <data android:mimeType="vnd.android.cursor.dir/event" />
            </intent-filter>

            <!-- Launcher long-press shortcuts (e.g. "New event"). -->
            <meta-data
                android:name="android.app.shortcuts"
                android:resource="@xml/shortcuts" />
        </activity>

        <!-- Standalone surface for a captured crash report. MainActivity routes
             here on a startup crash-loop, so it stays clear of the app's Hilt
             graph and Compose content. Not exported: launched only by us. -->
        <activity
            android:name=".ui.crash.CrashReportActivity"
            android:exported="false"
            android:excludeFromRecents="true"
            android:launchMode="singleTask" />

        <!-- Quick Settings tile: a one-tap "New event" shortcut in the QS panel.
             Exported with BIND_QUICK_SETTINGS_TILE so only the system QS host can
             bind it; the action mirrors the launcher "New event" shortcut. -->
        <service
            android:name=".qs.NewEventTileService"
            android:exported="true"
            android:icon="@drawable/ic_qs_new_event"
            android:label="@string/qs_tile_new_event_label"
            android:permission="android.permission.BIND_QUICK_SETTINGS_TILE">
            <intent-filter>
                <action android:name="android.service.quicksettings.action.QS_TILE" />
            </intent-filter>
        </service>

        <!-- The provider broadcasts EVENT_REMINDER at reminder time but posts
             no notification itself — a calendar app must (v1.4, Etar model).
             Exported: the broadcast arrives from the provider's process. -->
        <receiver
            android:name=".data.reminders.EventReminderReceiver"
            android:exported="true">
            <intent-filter>
                <action android:name="android.intent.action.EVENT_REMINDER" />
                <data
                    android:host="com.android.calendar"
                    android:scheme="content" />
            </intent-filter>
        </receiver>

        <!-- Snooze / dismiss actions on a reminder notification, plus the snooze
             re-show alarm. Not exported: only our own notification buttons and
             AlarmManager PendingIntents target it. -->
        <receiver
            android:name=".data.reminders.ReminderActionReceiver"
            android:exported="false" />

        <!-- Home-screen widgets (Glance). Exported: the launcher/host binds them. -->
        <receiver
            android:name=".widget.agenda.AgendaWidgetReceiver"
            android:label="@string/widget_agenda_label"
            android:exported="true">
            <intent-filter>
                <action android:name="android.appwidget.action.APPWIDGET_UPDATE" />
            </intent-filter>
            <meta-data
                android:name="android.appwidget.provider"
                android:resource="@xml/appwidget_info_agenda" />
        </receiver>

        <receiver
            android:name=".widget.month.MonthWidgetReceiver"
            android:label="@string/widget_month_label"
            android:exported="true">
            <intent-filter>
                <action android:name="android.appwidget.action.APPWIDGET_UPDATE" />
            </intent-filter>
            <meta-data
                android:name="android.appwidget.provider"
                android:resource="@xml/appwidget_info_month" />
        </receiver>

        <!-- Keeps both widgets fresh: the calendar provider broadcasts
             PROVIDER_CHANGED on any data change (our writes and external sync),
             and the system broadcasts the date/time ones at midnight / clock
             changes so "today" highlighting rolls over. -->
        <receiver
            android:name=".widget.WidgetUpdateReceiver"
            android:exported="true">
            <intent-filter>
                <action android:name="android.intent.action.PROVIDER_CHANGED" />
                <data
                    android:host="com.android.calendar"
                    android:scheme="content" />
            </intent-filter>
            <intent-filter>
                <action android:name="android.intent.action.DATE_CHANGED" />
                <action android:name="android.intent.action.TIME_SET" />
                <action android:name="android.intent.action.TIMEZONE_CHANGED" />
            </intent-filter>
        </receiver>

        <!-- Hands .ics files we stage in the cache to other apps via a content
             Uri (single-event share). Authority tracks applicationId so the
             debug suffix doesn't break getUriForFile. -->
        <provider
            android:name="androidx.core.content.FileProvider"
            android:authorities="${applicationId}.fileprovider"
            android:exported="false"
            android:grantUriPermissions="true">
            <meta-data
                android:name="android.support.FILE_PROVIDER_PATHS"
                android:resource="@xml/file_paths" />
        </provider>

        <!-- Persists the per-app language (M4) on API < 33, where the platform
             per-app-languages API is unavailable. On 33+ this is a no-op. -->
        <service
            android:name="androidx.appcompat.app.AppLocalesMetadataHolderService"
            android:enabled="false"
            android:exported="false">
            <meta-data
                android:name="autoStoreLocales"
                android:value="true" />
        </service>
    </application>

</manifest>
