#nullable enable

using System;
using System.IO;
using System.Net;
using System.Net.Sockets;
using System.Text.Json;

public class UdpSender : IDisposable
{
    private readonly UdpClient client = new UdpClient();
    private IPEndPoint endpoint;

    private const string DefaultIp = "192.168.1.50";
    private const int DefaultPort = 12345;

    public UdpSender()
    {
        string exeDir = AppContext.BaseDirectory;
        string cfgPath = Path.Combine(exeDir, "config.json");

        // Create default config if missing
        if (!File.Exists(cfgPath))
        {
            var defaultCfg = new UdpConfig
            {
                esp32_ip = DefaultIp,
                esp32_port = DefaultPort
            };

            string json = JsonSerializer.Serialize(
                defaultCfg,
                new JsonSerializerOptions { WriteIndented = true }
            );

            File.WriteAllText(cfgPath, json);
        }

        // Load config
        var jsonText = File.ReadAllText(cfgPath);
        var cfg = JsonSerializer.Deserialize<UdpConfig>(jsonText)
                  ?? throw new Exception("Invalid config.json");

        endpoint = new IPEndPoint(IPAddress.Parse(cfg.esp32_ip), cfg.esp32_port);
    }

    public void SendFloats(float[] values)
    {
        try
        {
            string packet = string.Join(",", values);
            byte[] data = System.Text.Encoding.ASCII.GetBytes(packet);

            client.Send(data, data.Length, endpoint);
        }
        catch (SocketException ex) when (
            ex.SocketErrorCode == SocketError.NetworkUnreachable ||
            ex.SocketErrorCode == SocketError.HostUnreachable ||
            ex.SocketErrorCode == SocketError.NetworkDown ||
            ex.SocketErrorCode == SocketError.AddressNotAvailable)
        {
            // Network not ready (sleep, reconnecting, etc.)
            // Skip this tick silently.
        }
        catch (ObjectDisposedException)
        {
            // App is shutting down — ignore.
        }
        catch (Exception)
        {
            // Any other unexpected error — swallow to avoid crashing the tray app.
        }
    }

    public void Dispose()
    {
        client.Dispose();
    }

    private class UdpConfig
    {
        public string esp32_ip { get; set; } = DefaultIp;
        public int esp32_port { get; set; } = DefaultPort;
    }
}
