using System.Runtime.InteropServices;

namespace RioJoy.Tray;

/// <summary>
/// Sets the Windows desktop wallpaper to a generated cockpit overlay
/// (Phase 7 — the modern replacement for manually setting the GIMP-exported
/// background). Wraps <c>SystemParametersInfo(SPI_SETDESKWALLPAPER)</c>.
///
/// <para>Windows requires a <strong>BMP</strong> file path for reliable results on
/// all versions; PNGs are accepted on modern Windows but not guaranteed, so callers
/// should hand this a path the overlay renderer wrote. Applying a wallpaper changes
/// a user-visible system setting, so it is only invoked on an explicit profile
/// activation, never speculatively.</para>
/// </summary>
public static class WallpaperApplier
{
    private const int SPI_SETDESKWALLPAPER = 0x0014;
    private const int SPIF_UPDATEINIFILE = 0x01; // persist across logon
    private const int SPIF_SENDCHANGE = 0x02;    // broadcast WM_SETTINGCHANGE

    /// <summary>
    /// Apply <paramref name="imagePath"/> as the desktop wallpaper. Returns true on
    /// success. Throws if the file does not exist.
    /// </summary>
    public static bool Apply(string imagePath)
    {
        if (string.IsNullOrWhiteSpace(imagePath)) throw new ArgumentException("Value cannot be null or whitespace.", nameof(imagePath));
        string full = Path.GetFullPath(imagePath);
        if (!File.Exists(full))
            throw new FileNotFoundException("Wallpaper image not found.", full);

#if NET40
        // Windows XP's SPI_SETDESKWALLPAPER accepts only BMP. Wallpapers are
        // authored as PNG on a modern machine, so convert beside the source on
        // apply (idempotent: reuses an up-to-date .bmp).
        if (!full.EndsWith(".bmp", StringComparison.OrdinalIgnoreCase))
        {
            string bmp = Path.ChangeExtension(full, ".bmp");
            if (!File.Exists(bmp) || File.GetLastWriteTimeUtc(bmp) < File.GetLastWriteTimeUtc(full))
            {
                using var image = System.Drawing.Image.FromFile(full);
                image.Save(bmp, System.Drawing.Imaging.ImageFormat.Bmp);
            }
            full = bmp;
        }
#endif

        return SystemParametersInfo(
            SPI_SETDESKWALLPAPER, 0, full, SPIF_UPDATEINIFILE | SPIF_SENDCHANGE);
    }

    [DllImport("user32.dll", SetLastError = true, CharSet = CharSet.Unicode)]
    [return: MarshalAs(UnmanagedType.Bool)]
    private static extern bool SystemParametersInfo(int uAction, int uParam, string lpvParam, int fuWinIni);
}
