using System.Text.Json;
using Microsoft.Xna.Framework;
using MrGameEng.Audio;
using MrGameEng.Mods;

namespace LittleSim.App;

/// <summary>
/// Пользовательские настройки игры, сохраняемые в <c>settings.json</c>: язык интерфейса,
/// полноэкранный режим, вертикальная синхронизация, размер окна и общая громкость.
/// </summary>
public sealed class GameSettings
{
    /// <summary>Код языка интерфейса (например, "ru" или "en").</summary>
    public string Language { get; set; } = "ru";

    /// <summary>Полноэкранный (безрамочный) режим.</summary>
    public bool Fullscreen { get; set; }

    /// <summary>Вертикальная синхронизация.</summary>
    public bool VSync { get; set; } = true;

    /// <summary>Ширина окна в пикселях.</summary>
    public int Width { get; set; } = 1280;

    /// <summary>Высота окна в пикселях.</summary>
    public int Height { get; set; } = 720;

    /// <summary>Общая громкость 0..1.</summary>
    public float Volume { get; set; } = 1f;
}

/// <summary>Чтение/запись <see cref="GameSettings"/> и применение их к движку.</summary>
public static class GameSettingsStore
{
    private static readonly JsonSerializerOptions JsonOptions = new()
    {
        WriteIndented = true,
        PropertyNameCaseInsensitive = true,
    };

    /// <summary>Загружает настройки из <see cref="GamePaths.SettingsFile"/> или возвращает значения по умолчанию.</summary>
    public static GameSettings Load()
    {
        try
        {
            if (File.Exists(GamePaths.SettingsFile))
            {
                return JsonSerializer.Deserialize<GameSettings>(
                        File.ReadAllText(GamePaths.SettingsFile),
                        JsonOptions
                    ) ?? new GameSettings();
            }
        }
        catch (Exception exception) when (exception is IOException or JsonException)
        {
            // Битый файл настроек не должен ронять запуск — откатываемся к умолчаниям.
        }

        return new GameSettings();
    }

    /// <summary>Сохраняет настройки в <see cref="GamePaths.SettingsFile"/>.</summary>
    public static void Save(GameSettings settings)
    {
        Directory.CreateDirectory(GamePaths.Root);
        File.WriteAllText(GamePaths.SettingsFile, JsonSerializer.Serialize(settings, JsonOptions));
    }

    /// <summary>
    /// Применяет настройки к движку: язык (<paramref name="languages"/>), полноэкранный
    /// режим/VSync/размер окна (<paramref name="graphics"/>) и громкость (<paramref name="audio"/>).
    /// </summary>
    public static void Apply(
        GameSettings settings,
        GraphicsDeviceManager graphics,
        LanguageManager languages,
        AudioManager audio
    )
    {
        languages.SetLanguage(settings.Language);
        audio.MasterVolume = settings.Volume;

        graphics.IsFullScreen = settings.Fullscreen;
        graphics.SynchronizeWithVerticalRetrace = settings.VSync;
        graphics.PreferredBackBufferWidth = settings.Width;
        graphics.PreferredBackBufferHeight = settings.Height;
        graphics.ApplyChanges();
    }
}
