package com.foxx.androidcast;

/*********************************************************************
 * CastTrayNotifier.java
 * Created at: Sun 17 May 2026 18:17:14 +0200
 * Updated at: Wed 20 May 2026 15:17:13 +0200 by Anton Afanasyeu <a.afanasieff@gmail.com>
 * Commit: 5d8e82d2e60a21fff3138d2a394ee4e8b4c6dcb8
 * class CastTrayNotifier
 * Contributors:
 *    - Anton Afanasyeu <a.afanasieff@gmail.com> (3 commits, 156 lines)
 *    - Cursor Agent (project assistant)
 * Digest: SHA256	292d7f278b9726120e113e803105641b313de93e2efa129dd3af428d1aa68033
**********************************************************************/
import android.app.ForegroundServiceStartNotAllowedException;
import android.app.Notification;
import android.app.NotificationChannel;
import android.app.NotificationManager;
import android.app.PendingIntent;
import android.app.Service;
import android.content.Context;
import android.content.Intent;
import android.os.Build;
import android.util.Log;

import androidx.core.app.NotificationCompat;

/**
 * Persistent status-bar icon while cast services run (when enabled in settings).
 */
public final class CastTrayNotifier {
    private static final String TAG = "CastTrayNotifier";
    public static final String CHANNEL_TRAY = "cast_tray";
    public static final int ID_TRAY = 3;

    private CastTrayNotifier() {}

    /** Sync tray with cast service lifecycle (call from foreground services). */
    public static void refresh(Context context) {
        Context app = context.getApplicationContext();
        if (!AppPreferences.isShowTrayIcon(app)) {
            hide(app);
            return;
        }
        ensureTrayService(app);
    }

    /**
     * Start idle tray when an activity is foreground (API 31+ blocks FGS from
     * {@link android.app.Application#onCreate()}).
     */
    public static void syncWhenForeground(Context context) {
        if (AppPreferences.isShowTrayIcon(context)) {
            ensureTrayService(context);
        }
    }

    /** User toggled the preference — show or hide immediately. */
    public static void onPreferenceChanged(Context context) {
        Context app = context.getApplicationContext();
        if (AppPreferences.isShowTrayIcon(app)) {
            ensureTrayService(app);
        } else {
            stopTrayService(app);
            hide(app);
        }
    }

    public static void ensureTrayService(Context context) {
        Context app = context.getApplicationContext();
        if (!AppPreferences.isShowTrayIcon(app)) {
            return;
        }
        Intent intent = new Intent(app, TrayForegroundService.class);
        try {
            if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
                app.startForegroundService(intent);
            } else {
                app.startService(intent);
            }
        } catch (ForegroundServiceStartNotAllowedException e) {
            Log.w(TAG, "tray FGS deferred (not foreground): " + e.getMessage());
        } catch (IllegalStateException e) {
            if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.S) {
                Log.w(TAG, "tray FGS deferred: " + e.getMessage());
            } else {
                throw e;
            }
        }
    }

    public static void stopTrayService(Context context) {
        context.getApplicationContext().stopService(new Intent(context, TrayForegroundService.class));
    }

    /** Foreground tray — not swipe-dismissible on stock Android. */
    public static void startForegroundTray(Service service) {
        if (!AppPreferences.isShowTrayIcon(service)) {
            service.stopSelf();
            return;
        }
        createChannel(service);
        boolean idle = !CastActiveState.isSenderCasting() && !CastActiveState.isReceiverListening();
        Notification n = buildNotification(service, idle);
        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.Q) {
            service.startForeground(ID_TRAY, n, android.content.pm.ServiceInfo.FOREGROUND_SERVICE_TYPE_SPECIAL_USE);
        } else {
            service.startForeground(ID_TRAY, n);
        }
    }

    private static void show(Context context, boolean idle) {
        if (AppPreferences.isShowTrayIcon(context)) {
            ensureTrayService(context);
            return;
        }
        hide(context);
    }

    private static Notification buildNotification(Context context, boolean idle) {
        String body = idle
                ? context.getString(R.string.tray_cast_idle)
                : context.getString(R.string.tray_cast_active);
        PendingIntent pi = PendingIntent.getActivity(
                context, 0, CastActivityTracker.resumeIntent(context),
                PendingIntent.FLAG_UPDATE_CURRENT | PendingIntent.FLAG_IMMUTABLE);
        Intent deleted = new Intent(context, TrayNotificationReceiver.class);
        deleted.setAction("com.foxx.androidcast.TRAY_DISMISSED");
        PendingIntent deletePi = PendingIntent.getBroadcast(
                context, 1, deleted,
                PendingIntent.FLAG_UPDATE_CURRENT | PendingIntent.FLAG_IMMUTABLE);
        return new NotificationCompat.Builder(context, CHANNEL_TRAY)
                .setContentTitle(context.getString(R.string.app_name))
                .setContentText(body)
                .setSmallIcon(R.drawable.ic_notification)
                .setContentIntent(pi)
                .setDeleteIntent(deletePi)
                .setOngoing(true)
                .setAutoCancel(false)
                .setOnlyAlertOnce(true)
                .setShowWhen(false)
                .setLocalOnly(true)
                .setPriority(NotificationCompat.PRIORITY_LOW)
                .setCategory(NotificationCompat.CATEGORY_SERVICE)
                .setVisibility(NotificationCompat.VISIBILITY_PUBLIC)
                .setForegroundServiceBehavior(NotificationCompat.FOREGROUND_SERVICE_IMMEDIATE)
                .build();
    }

    private static void hide(Context context) {
        NotificationManager nm = context.getSystemService(NotificationManager.class);
        if (nm != null) {
            nm.cancel(ID_TRAY);
        }
    }

    private static void createChannel(Context context) {
        if (Build.VERSION.SDK_INT < Build.VERSION_CODES.O) {
            return;
        }
        NotificationManager nm = context.getSystemService(NotificationManager.class);
        if (nm == null) {
            return;
        }
        NotificationChannel existing = nm.getNotificationChannel(CHANNEL_TRAY);
        if (existing != null && existing.getImportance() < NotificationManager.IMPORTANCE_DEFAULT) {
            nm.deleteNotificationChannel(CHANNEL_TRAY);
        }
        if (nm.getNotificationChannel(CHANNEL_TRAY) == null) {
            NotificationChannel ch = new NotificationChannel(
                    CHANNEL_TRAY,
                    context.getString(R.string.tray_channel_name),
                    NotificationManager.IMPORTANCE_DEFAULT);
            ch.setDescription(context.getString(R.string.tray_channel_description));
            ch.setShowBadge(true);
            nm.createNotificationChannel(ch);
        }
    }
}
