using RioJoy.Core.Profiles;

namespace RioJoy.Tray;

internal static class Program
{
    // Per-session single-instance guard. Two instances would both grab the RIO COM
    // port, so a second launch (e.g. the launcher starting it while an instance is
    // already running) must exit immediately. A named mutex is released by the OS if the owner dies,
    // so a crash never leaves a stale lock.
    private const string SingleInstanceMutex = "RIOJoy.Tray.SingleInstance";

    /// <summary>
    /// Entry point. RIOJoy runs as a background tray application with no main
    /// window: an ApplicationContext owns the NotifyIcon and the runtime, so the
    /// message loop stays alive while the only UI is the tray icon and its menu.
    ///
    /// <para><c>--import-profile &lt;profile.json&gt;</c> merges a single-profile
    /// document (a repo's <c>profiles/*.json</c>) into this user's config and
    /// exits without starting the tray. Output goes to stdout/stderr, which a
    /// GUI-subsystem exe only delivers when redirected — check the exit code
    /// (0 ok, 1 failed, 2 usage, 3 tray running) when scripting it.</para>
    /// </summary>
    [STAThread]
    private static int Main(string[] args)
    {
        if (args.Length >= 1 && string.Equals(args[0], "--import-profile", StringComparison.OrdinalIgnoreCase))
            return ImportProfile(args);

        using var instance = new Mutex(initiallyOwned: true, SingleInstanceMutex, out bool createdNew);
        if (!createdNew)
            return 0; // another RIOJoy is already running in this session

        // net48 has no source-generated ApplicationConfiguration.Initialize();
        // do the equivalent setup directly.
        Application.EnableVisualStyles();
        Application.SetCompatibleTextRenderingDefault(false);
        Application.Run(new TrayApplicationContext());
        return 0;
    }

    private static int ImportProfile(string[] args)
    {
        if (args.Length != 2)
        {
            Console.Error.WriteLine("usage: RioJoy.Tray --import-profile <profile.json>");
            return 2;
        }

        // A running tray holds the config in memory and rewrites it on its own
        // saves, which would silently discard this import — refuse instead.
        // (OpenExisting + catch rather than TryOpenExisting: net40 lacks the Try form.)
        try
        {
            using Mutex running = Mutex.OpenExisting(SingleInstanceMutex);
            Console.Error.WriteLine("RIOJoy is running in this session - quit it from the tray menu, import, then relaunch.");
            return 3;
        }
        catch (WaitHandleCannotBeOpenedException)
        {
            // not running — proceed
        }

        try
        {
            ProfileImportResult result = ConfigStore.ImportProfile(TrayApplicationContext.ConfigPath, args[1]);
            Console.WriteLine($"{(result.Replaced ? "Replaced" : "Added")} profile '{result.Name}' in {TrayApplicationContext.ConfigPath}");
            return 0;
        }
        catch (Exception ex)
        {
            Console.Error.WriteLine($"import failed: {ex.Message}");
            return 1;
        }
    }
}
