using Log;
using Microsoft.AspNetCore.SignalR.Client;
using System.Text;
using Universal;

namespace OnlineLogViewer;

public class LogInfo(LogLevel logLevel, string message, DateTime dateTime)
{
    public LogLevel Level { get; } = logLevel;
    public string Message { get; } = message;
    public DateTime DateTime { get; } = dateTime;
}

public class LogHub
{
    public LogHub()
    {
        this._LogEventQueue = new(LogHandler);
    }

    private HubConnection? _hubConnection;
    public readonly EventQueue<LogInfo> _LogEventQueue;

    private int _logLevel;

    private static void LogHandler(LogInfo logInfo)
    {
        StringBuilder sb = new();
        sb.Append(logInfo.Level.ToString().PadRight(10));
        sb.Append(logInfo.DateTime.ToString("HH:mm:ss.ff").PadRight(18));
        sb.Append(logInfo.Message);

        Console.WriteLine(sb);
    }



    public bool Initialize(string ip, int port, string hub, LogLevel logLevel)
    {
        if (_hubConnection is not null)
            return false;
        this._logLevel = (int)logLevel;
        HubConnection temp = new HubConnectionBuilder().WithUrl($"http://{ip}:{port}/{hub}").WithAutomaticReconnect().Build();
        temp.On<string, DateTime>("Debug", this.Debug);
        temp.On<string, DateTime>("Info", this.Info);
        temp.On<string, DateTime>("Warning", this.Warning);
        temp.On<string, DateTime>("Error", this.Error);
        temp.On<string, DateTime>("Fatal", this.Fatal);

        while (true)
        {
            try
            {
                temp.StartAsync().Wait();
                _hubConnection = temp;
                Console.WriteLine("Connected");
                break;
            }
            catch
            {
                Thread.Sleep(1000);
            }
        }

        return true;
    }

    public void Debug(string message, DateTime dateTime)
    {
        this._LogEventQueue.Enqueue(new(LogLevel.Debug, message, dateTime));
    }

    public void Info(string message, DateTime dateTime)
    {
        if (_logLevel < (int)LogLevel.Info)
            return;
        this._LogEventQueue.Enqueue(new(LogLevel.Info, message, dateTime));
    }

    public void Warning(string message, DateTime dateTime)
    {
        if (_logLevel < (int)LogLevel.Warning)
            return;
        this._LogEventQueue.Enqueue(new(LogLevel.Warning, message, dateTime));
    }

    public void Error(string message, DateTime dateTime)
    {
        if (_logLevel < (int)LogLevel.Error)
            return;
        this._LogEventQueue.Enqueue(new(LogLevel.Error, message, dateTime));
    }

    public void Fatal(string message, DateTime dateTime)
    {
        if (_logLevel < (int)LogLevel.Fatal)
            return;
        this._LogEventQueue.Enqueue(new(LogLevel.Fatal, message, dateTime));
    }
}
