using System.Globalization;
using RioJoy.Core.Calibration;
using RioJoy.Core.Mapping;

namespace RioJoy.Core.Profiles;

/// <summary>
/// Imports a legacy <c>RIO.ini</c> into a <see cref="RioProfile"/> (see the key
/// layout in <c>riovjoy2.cpp</c> around line 343). The <c>[Buttons]</c> keys are
/// <c>RIO&lt;hex addr&gt;</c> with hex/decimal map words; <c>[JoyStick]</c> holds
/// the invert/enableZR flags; <c>[Plasma] Greeting</c> is the greeting text.
/// </summary>
public static class RioIniImporter
{
    /// <summary>Parse <paramref name="iniText"/> into a profile named <paramref name="name"/>.</summary>
    public static RioProfile Import(string iniText, string name = "Imported")
    {
        if (iniText is null) throw new ArgumentNullException(nameof(iniText));
        IniFile ini = IniFile.Parse(iniText);

        var profile = new RioProfile
        {
            Name = name,
            PlasmaGreeting = StripQuotes(ini.GetString("Plasma", "Greeting")),
            WallpaperPath = ini.GetString("Desktop", "File"),
            Calibration = new AxisCalibrationConfig
            {
                InvertX = ini.GetBool("JoyStick", "invertX", false),
                InvertY = ini.GetBool("JoyStick", "invertY", false),
                InvertZ = ini.GetBool("JoyStick", "invertZ", false),
                InvertXR = ini.GetBool("JoyStick", "invertXR", false),
                InvertYR = ini.GetBool("JoyStick", "invertYR", false),
                InvertZR = ini.GetBool("JoyStick", "invertZR", false),
                EnableZR = ini.GetBool("JoyStick", "enableZR", true),
            },
        };

        foreach ((string key, string value) in ini.Section("Buttons"))
        {
            if (!TryParseButtonAddress(key, out int address))
                continue;

            int raw = IniFile.ParseInt(value);
            if (raw != 0) // skip "do nothing" entries
                profile.Buttons[address] = raw & 0xFFFF;
        }

        return profile;
    }

    // The gsheet writes the greeting as a quoted string (e.g. Greeting="Hello,");
    // strip a single pair of surrounding double quotes so it displays cleanly.
    private static string? StripQuotes(string? value)
    {
        if (value is null)
            return null;
        string v = value.Trim();
        return v.Length >= 2 && v[0] == '"' && v[^1] == '"' ? v[1..^1] : v;
    }

    // Keys look like "RIO00".."RIO6F": "RIO" + a hex address into the iRIO table.
    private static bool TryParseButtonAddress(string key, out int address)
    {
        address = 0;
        if (!key.StartsWith("RIO", StringComparison.OrdinalIgnoreCase))
            return false;

        string hex = key[3..];
        if (!int.TryParse(hex, NumberStyles.HexNumber, CultureInfo.InvariantCulture, out address))
            return false;

        return address >= 0 && address < RioAddress.TableSize;
    }
}
