using Ehwrj.App.ViewModels;

namespace Ehwrj.App.Models;

public sealed class OverlaySettings : ObservableObject
{
    private bool _showMiniMap = true;
    private bool _showMach = true;
    private bool _showSpotRadar = true;
    private bool _spotShowDistance = true;
    private bool _spotShowMach;
    private bool _spotShowRelativeSpeed = true;
    private double _size = 560;
    private double _top = 24;
    private double _right = 24;
    private double _zoomPercent = 92;
    private double _miniMapMinimumMach;
    private double _miniMapAircraftScale = 125;
    private double _spotOpacity = 70;
    private double _spotDistance = 529;
    private double _spotVerticalScale = 68;
    private double _spotVerticalOffset = 224;
    private double _spotArrowScale = 140;
    private double _spotOutlineWidth = 2;
    private double _spotDetectDistanceKm = 15;
    private double _spotMinimumMach = 0.5;
    private double _spotFontOpacity = 70;
    private double _distanceFontSize = 31;
    private double _distanceOutlineWidth = 2;
    private double _machFontSize = 27;
    private double _machOutlineWidth = 2;
    private double _relativeFontSize = 24;
    private double _relativeOutlineWidth = 2;
    private string _spotArrowColor = "#ff1e1e";
    private string _spotTextColor = "#ffffff";
    private string _distanceTextColor = "#ff1e1e";
    private string _machTextColor = "#57c7f2";
    private string _relativeTextColor = "#19f24f";

    public bool ShowMiniMap
    {
        get => _showMiniMap;
        set => SetProperty(ref _showMiniMap, value);
    }

    public bool ShowMach
    {
        get => _showMach;
        set => SetProperty(ref _showMach, value);
    }

    public bool ShowSpotRadar
    {
        get => _showSpotRadar;
        set => SetProperty(ref _showSpotRadar, value);
    }

    public bool SpotShowDistance
    {
        get => _spotShowDistance;
        set => SetProperty(ref _spotShowDistance, value);
    }

    public bool SpotShowMach
    {
        get => _spotShowMach;
        set => SetProperty(ref _spotShowMach, value);
    }

    public bool SpotShowRelativeSpeed
    {
        get => _spotShowRelativeSpeed;
        set => SetProperty(ref _spotShowRelativeSpeed, value);
    }

    public double Size
    {
        get => _size;
        set => SetProperty(ref _size, Math.Clamp(value, 160, 2000));
    }

    public double Top
    {
        get => _top;
        set => SetProperty(ref _top, Math.Clamp(value, 0, 500));
    }

    public double Right
    {
        get => _right;
        set => SetProperty(ref _right, Math.Clamp(value, 0, 2000));
    }

    public double ZoomPercent
    {
        get => _zoomPercent;
        set => SetProperty(ref _zoomPercent, Math.Clamp(value, 25, 400));
    }

    public double MiniMapMinimumMach
    {
        get => _miniMapMinimumMach;
        set => SetProperty(ref _miniMapMinimumMach, Math.Clamp(value, 0, 2));
    }

    public double MiniMapAircraftScale
    {
        get => _miniMapAircraftScale;
        set => SetProperty(ref _miniMapAircraftScale, Math.Clamp(value, 50, 200));
    }

    public double SpotOpacity
    {
        get => _spotOpacity;
        set => SetProperty(ref _spotOpacity, Math.Clamp(value, 0, 100));
    }

    public double SpotDistance
    {
        get => _spotDistance;
        set => SetProperty(ref _spotDistance, Math.Clamp(value, 40, 600));
    }

    public double SpotVerticalScale
    {
        get => _spotVerticalScale;
        set => SetProperty(ref _spotVerticalScale, Math.Clamp(value, 40, 140));
    }

    public double SpotVerticalOffset
    {
        get => _spotVerticalOffset;
        set => SetProperty(ref _spotVerticalOffset, Math.Clamp(value, -500, 500));
    }

    public double SpotArrowScale
    {
        get => _spotArrowScale;
        set => SetProperty(ref _spotArrowScale, Math.Clamp(value, 50, 200));
    }

    public double SpotOutlineWidth
    {
        get => _spotOutlineWidth;
        set => SetProperty(ref _spotOutlineWidth, Math.Clamp(value, 0, 10));
    }

    public double SpotDetectDistanceKm
    {
        get => _spotDetectDistanceKm;
        set => SetProperty(ref _spotDetectDistanceKm, Math.Clamp(value, 0, 30));
    }

    public double SpotMinimumMach
    {
        get => _spotMinimumMach;
        set => SetProperty(ref _spotMinimumMach, Math.Clamp(value, 0, 2));
    }

    public double SpotFontOpacity
    {
        get => _spotFontOpacity;
        set => SetProperty(ref _spotFontOpacity, Math.Clamp(value, 0, 100));
    }

    public double DistanceFontSize
    {
        get => _distanceFontSize;
        set => SetProperty(ref _distanceFontSize, Math.Clamp(value, 10, 60));
    }

    public double DistanceOutlineWidth
    {
        get => _distanceOutlineWidth;
        set => SetProperty(ref _distanceOutlineWidth, Math.Clamp(value, 0, 8));
    }

    public double MachFontSize
    {
        get => _machFontSize;
        set => SetProperty(ref _machFontSize, Math.Clamp(value, 10, 60));
    }

    public double MachOutlineWidth
    {
        get => _machOutlineWidth;
        set => SetProperty(ref _machOutlineWidth, Math.Clamp(value, 0, 8));
    }

    public double RelativeFontSize
    {
        get => _relativeFontSize;
        set => SetProperty(ref _relativeFontSize, Math.Clamp(value, 10, 60));
    }

    public double RelativeOutlineWidth
    {
        get => _relativeOutlineWidth;
        set => SetProperty(ref _relativeOutlineWidth, Math.Clamp(value, 0, 8));
    }

    public string SpotArrowColor
    {
        get => _spotArrowColor;
        set => SetProperty(ref _spotArrowColor, NormalizeColor(value, "#ff1e1e"));
    }

    public string SpotTextColor
    {
        get => _spotTextColor;
        set => SetProperty(ref _spotTextColor, NormalizeColor(value, "#ffffff"));
    }

    public string DistanceTextColor
    {
        get => _distanceTextColor;
        set => SetProperty(ref _distanceTextColor, NormalizeColor(value, "#ff1e1e"));
    }

    public string MachTextColor
    {
        get => _machTextColor;
        set => SetProperty(ref _machTextColor, NormalizeColor(value, "#57c7f2"));
    }

    public string RelativeTextColor
    {
        get => _relativeTextColor;
        set => SetProperty(ref _relativeTextColor, NormalizeColor(value, "#19f24f"));
    }

    public void Reset()
    {
        ShowMiniMap = true;
        ShowMach = true;
        ShowSpotRadar = true;
        SpotShowDistance = true;
        SpotShowMach = false;
        SpotShowRelativeSpeed = true;
        Size = 560;
        Top = 24;
        Right = 24;
        ZoomPercent = 92;
        MiniMapMinimumMach = 0;
        MiniMapAircraftScale = 125;
        SpotOpacity = 70;
        SpotDistance = 529;
        SpotVerticalScale = 68;
        SpotVerticalOffset = 224;
        SpotArrowScale = 140;
        SpotOutlineWidth = 2;
        SpotDetectDistanceKm = 15;
        SpotMinimumMach = 0.5;
        SpotFontOpacity = 70;
        DistanceFontSize = 31;
        DistanceOutlineWidth = 2;
        MachFontSize = 27;
        MachOutlineWidth = 2;
        RelativeFontSize = 24;
        RelativeOutlineWidth = 2;
        SpotArrowColor = "#ff1e1e";
        SpotTextColor = "#ffffff";
        DistanceTextColor = "#ff1e1e";
        MachTextColor = "#57c7f2";
        RelativeTextColor = "#19f24f";
    }

    private static string NormalizeColor(string? value, string fallback)
    {
        if (string.IsNullOrWhiteSpace(value))
        {
            return fallback;
        }

        var trimmed = value.Trim();
        if (!trimmed.StartsWith('#'))
        {
            trimmed = $"#{trimmed}";
        }

        return trimmed.Length is 7 or 9 ? trimmed : fallback;
    }
}
