using System;
using System.Diagnostics;
using System.IO;
using System.Text.Json;
using System.Windows.Forms;

namespace NosClientLauncherGui
{
    public class LaunchConfig
    {
        public string ClientExePath { get; set; } = @"C:\\NosClient\\NostaleClientX.exe";
        public string WorkingDirectory { get; set; } = @"C:\\NosClient";
        public string ServerIp { get; set; } = "127.0.0.1";
        public int ServerPort { get; set; } = 4001;
        public string Arguments { get; set; } = "";
    }

    public partial class Form1 : Form
    {
        private const string ConfigFile = "launcher.config.json";
        private const string LogFile = "launcher.log";

        private TextBox txtExe = new() { Left = 20, Top = 30, Width = 500 };
        private Button btnBrowse = new() { Left = 530, Top = 28, Width = 90, Text = "Browse" };

        private TextBox txtWorkDir = new() { Left = 20, Top = 85, Width = 600 };
        private TextBox txtIp = new() { Left = 20, Top = 140, Width = 250 };
        private NumericUpDown numPort = new() { Left = 280, Top = 140, Width = 120, Minimum = 1, Maximum = 65535, Value = 4001 };
        private TextBox txtArgs = new() { Left = 20, Top = 195, Width = 600 };

        private Button btnSave = new() { Left = 20, Top = 245, Width = 120, Text = "Save" };
        private Button btnLaunch = new() { Left = 150, Top = 245, Width = 120, Text = "Launch" };
        private TextBox txtLog = new() { Left = 20, Top = 295, Width = 600, Height = 180, Multiline = true, ScrollBars = ScrollBars.Vertical, ReadOnly = true };

        public Form1()
        {
            InitializeComponent();

            Text = "Nos Client Launcher";
            Width = 670;
            Height = 560;
            FormBorderStyle = FormBorderStyle.FixedDialog;
            MaximizeBox = false;

            Controls.Clear();
            Controls.Add(new Label { Left = 20, Top = 10, Text = "Client EXE" });
            Controls.Add(txtExe);
            Controls.Add(btnBrowse);

            Controls.Add(new Label { Left = 20, Top = 65, Text = "Working Directory" });
            Controls.Add(txtWorkDir);

            Controls.Add(new Label { Left = 20, Top = 120, Text = "Server IP" });
            Controls.Add(txtIp);
            Controls.Add(new Label { Left = 280, Top = 120, Text = "Port" });
            Controls.Add(numPort);

            Controls.Add(new Label { Left = 20, Top = 175, Text = "Arguments (optional)" });
            Controls.Add(txtArgs);

            Controls.Add(btnSave);
            Controls.Add(btnLaunch);
            Controls.Add(txtLog);

            btnBrowse.Click += (_, _) => BrowseExe();
            btnSave.Click += (_, _) => SaveConfig();
            btnLaunch.Click += (_, _) => LaunchClient();

            LoadConfig();
        }

        private void BrowseExe()
        {
            using var ofd = new OpenFileDialog
            {
                Filter = "Executable (*.exe)|*.exe",
                Title = "Select NosTale Client EXE"
            };

            if (ofd.ShowDialog() == DialogResult.OK)
            {
                txtExe.Text = ofd.FileName;
                if (string.IsNullOrWhiteSpace(txtWorkDir.Text))
                    txtWorkDir.Text = Path.GetDirectoryName(ofd.FileName) ?? "";
            }
        }

        private void LoadConfig()
        {
            try
            {
                LaunchConfig cfg;
                if (!File.Exists(ConfigFile))
                {
                    cfg = new LaunchConfig();
                    File.WriteAllText(ConfigFile, JsonSerializer.Serialize(cfg, new JsonSerializerOptions { WriteIndented = true }));
                }
                else
                {
                    cfg = JsonSerializer.Deserialize<LaunchConfig>(File.ReadAllText(ConfigFile)) ?? new LaunchConfig();
                }

                txtExe.Text = cfg.ClientExePath;
                txtWorkDir.Text = cfg.WorkingDirectory;
                txtIp.Text = cfg.ServerIp;
                numPort.Value = cfg.ServerPort;
                txtArgs.Text = cfg.Arguments;

                AppendLog("Config loaded.");
            }
            catch (Exception ex)
            {
                AppendLog("LoadConfig ERROR: " + ex.Message);
            }
        }

        private void SaveConfig()
        {
            try
            {
                var cfg = ReadUi();
                File.WriteAllText(ConfigFile, JsonSerializer.Serialize(cfg, new JsonSerializerOptions { WriteIndented = true }));
                AppendLog("Config saved.");
            }
            catch (Exception ex)
            {
                AppendLog("SaveConfig ERROR: " + ex.Message);
            }
        }

        private void LaunchClient()
        {
            try
            {
                var cfg = ReadUi();
                if (!File.Exists(cfg.ClientExePath))
                {
                    MessageBox.Show("Client EXE nicht gefunden.", "Fehler", MessageBoxButtons.OK, MessageBoxIcon.Error);
                    return;
                }

                SaveConfig();

                var psi = new ProcessStartInfo
                {
                    FileName = cfg.ClientExePath,
                    WorkingDirectory = cfg.WorkingDirectory,
                    Arguments = cfg.Arguments,
                    UseShellExecute = false
                };

                psi.Environment["NOSTALE_SERVER_IP"] = cfg.ServerIp;
                psi.Environment["NOSTALE_SERVER_PORT"] = cfg.ServerPort.ToString();

                var p = Process.Start(psi);
                AppendLog(p != null
                    ? $"Client gestartet. PID={p.Id} | Target={cfg.ServerIp}:{cfg.ServerPort}"
                    : "Process.Start returned null.");
            }
            catch (Exception ex)
            {
                AppendLog("Launch ERROR: " + ex);
            }
        }

        private LaunchConfig ReadUi()
        {
            return new LaunchConfig
            {
                ClientExePath = txtExe.Text.Trim(),
                WorkingDirectory = txtWorkDir.Text.Trim(),
                ServerIp = txtIp.Text.Trim(),
                ServerPort = (int)numPort.Value,
                Arguments = txtArgs.Text.Trim()
            };
        }

        private void AppendLog(string line)
        {
            var msg = $"[{DateTime.Now:HH:mm:ss}] {line}";
            txtLog.AppendText(msg + Environment.NewLine);
            File.AppendAllText(LogFile, $"[{DateTime.Now:yyyy-MM-dd HH:mm:ss}] {line}{Environment.NewLine}");
        }
    }
}
