using Krypton.Toolkit;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Hosting;
using qtcnet_client.Factories;
using qtcnet_client.Model;
using qtcnet_client.Services;
using QtCNETAPI.Services;
using QtCNETAPI.Services.ApiService;
using QtCNETAPI.Services.GatewayService;
using System.Text.Json;

namespace qtcnet_client
{
    internal static class Program
    {
        /// <summary>
        ///  The main entry point for the application.
        /// </summary>
        [STAThread]
        static void Main()
        {
            // To customize application configuration such as set high DPI settings or default font,
            // see https://aka.ms/applicationconfiguration.
            ApplicationConfiguration.Initialize();

            var host = CreateHostBuilder().Build();
            ServiceProvider = host.Services;

            Application.Run(ServiceProvider.GetRequiredService<MainForm>());
        }

        private static JsonSerializerOptions JsonSerializerOptions { get; } = new() { WriteIndented = true };
        public static IServiceProvider? ServiceProvider { get; private set; }
        static IHostBuilder CreateHostBuilder()
        {
            return Host.CreateDefaultBuilder()
                .ConfigureServices((context, service) =>
                {
                    service.AddTransient<MainForm>();
                    service.AddSingleton<LoggingService>();
                    service.AddSingleton<CredentialService>();
                    service.AddSingleton<ImageFactory>();
                    service.AddSingleton<UpdateService>();
                    service.AddSingleton<AudioService>();
                    service.AddSingleton(provider => GetOrCreateClientConfig());
                    service.AddSingleton<IApiService>(provider => new ApiService(provider.GetService<ClientConfig>()!.ServerBaseUri + "/api", provider.GetService<LoggingService>()!, provider.GetService<CredentialService>()!));
                    service.AddSingleton<IGatewayService>(provider => new GatewayService(provider.GetService<ClientConfig>()!.ServerBaseUri + "/chat", provider.GetService<IApiService>()!, provider.GetService<LoggingService>()!));
                });
        }

        static ClientConfig GetOrCreateClientConfig()
        {
            var _configPath = $"{Application.StartupPath}/config.json";
            try
            {
                if (!File.Exists(_configPath))
                {
                    var _defaultConfig = new ClientConfig();

                    // create the config using the default config model
                    string serializedModel = JsonSerializer.Serialize(_defaultConfig, JsonSerializerOptions);

                    // write it to a new file
                    File.WriteAllText(_configPath, serializedModel);

                    // return it
                    return _defaultConfig;
                }
                else
                {
                    // deserialize the contents of config.json and return it
                    ClientConfig? _deserializedConfig = JsonSerializer.Deserialize<ClientConfig>(File.ReadAllText(_configPath));
                    if (_deserializedConfig != null)
                        return _deserializedConfig;
                }
            }
            catch (JsonException)
            {
            }

            // if the functions gets here, inform the user their config is incorrect and create a new one if allowed
            var _diagResult = KryptonMessageBox.Show($"Your Config Is Incorrect. Would You Like To Create A New One?", "Uh Oh.", KryptonMessageBoxButtons.YesNo);
            if (_diagResult == DialogResult.Yes)
            {
                var _defaultConfig = new ClientConfig();

                // create the config using the default config model
                string serializedModel = JsonSerializer.Serialize(_defaultConfig, JsonSerializerOptions);

                // write it to a new file
                File.WriteAllText(_configPath, serializedModel);

                // return it
                return _defaultConfig;
            }
            else
            {
                Application.Exit();
                return default!; // application should exit before it can return this lol
            }
        }
    }
}