using System;
using System.Collections.Generic;
using System.Globalization;
using System.IO;
using Gtk;
using UI = Gtk.Builder.ObjectAttribute;

public class MainWindow : Window
{
    [UI] private Button Option1Button = null;
    [UI] private Button Option2Button = null;
    [UI] private Button Option3Button = null;
    [UI] private Switch LanguageSwitch = null;
    [UI] private Label  LanguageLabel = null;
    [UI] private Button CloseButton = null;
    [UI] private Button SettingButton = null;
    [UI] private Image  ConnectionIcon = null;   // was GtkIconView in the old glade

    private CssProvider _scaleCssProvider;
    // private CssProvider _languageCssProvider;
    private int _lastAppliedWidth = -1;

    private const int BaseWidth = 1920;
    private const int BaseHeight = 1080;

    // private const string EngCssPath = "lang_eng.css";
    // private const string JpnCssPath = "lang_jpn.css";

    // private Dictionary<string, string> _engText;
    // private Dictionary<string, string> _jpnText;
    private Dictionary<string, Button> _buttonsById;

    private readonly ArduinoConnection _arduino = new ArduinoConnection();
    internal SettingsWindow _settingsWindow;
    internal Language _Language;

    public MainWindow() : this(CreateBuilder()) { }

    private static Builder CreateBuilder()
    {
        var builder = new Builder();
        builder.AddFromFile("homepage.glade");
        return builder;
    }

    private MainWindow(Builder builder) : base(builder.GetObject("SplashWindow").Handle)
    {
        builder.Autoconnect(this);

        _scaleCssProvider = new CssProvider();
        // _languageCssProvider = new CssProvider();

        StyleContext.AddProviderForScreen(Gdk.Screen.Default, _scaleCssProvider, 600);
        // StyleContext.AddProviderForScreen(Gdk.Screen.Default, _Language._languageCssProvider, 600);

        this.Fullscreen();

        Option1Button.Clicked += OnNormalSessionClicked;
        Option2Button.Clicked += OnPositionRecordingClicked;
        Option3Button.Clicked += OnExamModeClicked;
        CloseButton.Clicked   += OnCloseClicked;
        SettingButton.Clicked += OnSettingClicked;
        LanguageSwitch.AddNotification("active", OnLanguageSwitchNotify);

        DeleteEvent   += OnDeleteEvent;
        SizeAllocated += OnWindowSizeAllocated;

        _arduino.ConnectionChanged += OnArduinoConnectionChanged;

        _buttonsById = new Dictionary<string, Button>
        {
            { "Option1Button", Option1Button },
            { "Option2Button", Option2Button },
            { "Option3Button", Option3Button },
            { "CloseButton",   CloseButton   },
            { "SettingButton", SettingButton },
        };

        // CSS ID selectors (#Option1Button etc.) need the widget Name set explicitly
        foreach (var kvp in _buttonsById)
            kvp.Value.Name = kvp.Key;

        // _engText = LoadButtonText("info_eng.csv");
        // _jpnText = LoadButtonText("info_jpn.csv");

        _Language = new Language(_buttonsById,LanguageLabel);

        _Language.ApplyLanguage(LanguageSwitch.Active);
        OnArduinoConnectionChanged(false);
    }

    // ---------- settings panel ----------

    private void OnSettingClicked(object sender, EventArgs e)
    {
        if (_settingsWindow == null)
        {
            _settingsWindow = new SettingsWindow(_arduino);
            _settingsWindow.BackRequested += OnSettingsClosed;
            _settingsWindow.ShowAll();      // build it fullscreen once, up front
            _settingsWindow.Fullscreen();
        }

        
        _settingsWindow.ShowAll();
        _settingsWindow.Present();
        this.Hide();
    }

    private void OnSettingsClosed(object sender, EventArgs e)
    {
        this.ShowAll();
        this.Present();
        _settingsWindow.Hide(); 
    }

    private void OnArduinoConnectionChanged(bool connected)
    {
        if (ConnectionIcon == null) return;

        ConnectionIcon.SetFromIconName(
            connected ? "network-transmit-receive" : "network-offline",
            IconSize.Dnd);

        ConnectionIcon.TooltipText = connected
            ? $"Connected to {_arduino.PortName}"
            : "Device not connected";
    }

    // ---------- localisation ----------

    private Dictionary<string, string> LoadButtonText(string path)
    {
        var result = new Dictionary<string, string>();

        if (!File.Exists(path))
        {
            Console.WriteLine($"Warning: text file not found: {path}");
            return result;
        }

        var lines = File.ReadAllLines(path);
        for (int i = 1; i < lines.Length; i++) // skip header row
        {
            var line = lines[i].Trim();
            if (string.IsNullOrEmpty(line)) continue;

            var parts = line.Split(new[] { ',' }, 2);
            if (parts.Length < 2) continue;

            result[parts[0]] = parts[1];
        }

        return result;
    }

    // private void ApplyLanguage(bool isEnglish)
    // {
    //     var text = isEnglish ? _engText : _jpnText;
    //     string cssPath = isEnglish ? EngCssPath : JpnCssPath;

    //     foreach (var kvp in _buttonsById)
    //     {
    //         if (text.TryGetValue(kvp.Key, out var buttonText))
    //             kvp.Value.Label = buttonText;
    //     }

    //     if (File.Exists(cssPath))
    //         _languageCssProvider.LoadFromPath(cssPath);
    //     else
    //         Console.WriteLine($"Warning: CSS file not found: {cssPath}");

    //     LanguageLabel.Text = isEnglish ? "あ" : "A";
    // }

    // ---------- scaling ----------

    private void OnWindowSizeAllocated(object o, SizeAllocatedArgs args)
    {
        int width = args.Allocation.Width;
        int height = args.Allocation.Height;

        if (width == _lastAppliedWidth) return;
        _lastAppliedWidth = width;

        double scaleX = (double)width / BaseWidth;
        double scaleY = (double)height / BaseHeight;

        ApplyScale(Math.Min(scaleX, scaleY));
    }

    private void ApplyScale(double scale)
    {
        int fontSize    = Math.Max(10, (int)(20 * scale));
        int buttonPadV  = Math.Max(4,  (int)(12 * scale));
        int buttonPadH  = Math.Max(8,  (int)(24 * scale));
        int switchWidth = Math.Max(30, (int)(40 * scale));
        int switchHeight= Math.Max(18, (int)(24 * scale));

        // NOTE: integers + InvariantCulture. Interpolating a double here emitted
        // "40,5px" under ja_JP / de_DE locales and GTK silently dropped the rule.
        string css = string.Format(CultureInfo.InvariantCulture, @"
            grid, label, button, switch {{
                font-size: {0}px;
            }}
            button {{
                padding: {1}px {2}px;
            }}
            switch {{
                min-width: {3}px;
                min-height: {4}px;
            }}
        ", fontSize, buttonPadV, buttonPadH, switchWidth, switchHeight);

        _scaleCssProvider.LoadFromData(css);
    }

    // ---------- lifecycle ----------

    private void OnDeleteEvent(object sender, DeleteEventArgs a)
    {
        Shutdown();
        a.RetVal = true;
    }

    private void OnCloseClicked(object sender, EventArgs e)
    {
        Shutdown();
    }

    private void Shutdown()
    {
        _arduino.Disconnect();
        _arduino.Dispose();
        _settingsWindow?.Destroy();
        Application.Quit();
    }

    private void OnNormalSessionClicked(object sender, EventArgs e)
    {
        Console.WriteLine("Normal Session selected");
    }

    private void OnPositionRecordingClicked(object sender, EventArgs e)
    {
        Console.WriteLine("Position Recording Mode selected");
    }

    private void OnExamModeClicked(object sender, EventArgs e)
    {
        Console.WriteLine("Exam Mode selected");
    }

    private void OnLanguageSwitchNotify(object o, GLib.NotifyArgs args)
    {
        Language.LanguageSwitchValue = LanguageSwitch.Active;
        _Language.ApplyLanguage(LanguageSwitch.Active);
         _settingsWindow?._Language?.ApplyLanguages(LanguageSwitch.Active);
    }
}