using System.Text.RegularExpressions;
using Cogwheel;
using ImGuiNET;
using Raylib_cs;

namespace RaylibCogwheel;

public class RaylibCogwheelConsole : ICogwheelConsole
{
    public string OpeningMessage { get; set; } = 
        "===========================\n" +
        "| COGWHEEL RAYLIB CONSOLE |\n" +
        "===========================";
    public bool IsRunning { get; set; }
    public CommandsManager CommandsManager { get; set; }
    public bool IsOpen { get; set; } = false;
    
    private string _input = string.Empty;
    private string _output = string.Empty;
    private int _output_buffer_size = 1000;
    //private List<string> _history = new();
    
    private bool _scrollToBottom = false;
    private string hint = "";
    
    
    public void Initialize(CommandsManager commandsManager)
    {
        COGWHEEL.RegisterObject(this);
        CommandsManager = commandsManager;
        
        Write(OpeningMessage);
    }

    [Command(Name = "log", Description = "Logs a message to the console.")]
    public void Log(string message)
    {
        Write(message);
    }

    public void LogError(string message)
    {
        WriteColor("[COGWHEEL ERROR] " + message, new Color(255, 0, 0, 255)); // Red color
    }

    public void LogWarning(string message)
    {
        WriteColor("[COGWHEEL WARNING] " + message, new Color(255, 255, 0, 255)); // Yellow color
    }
    
    public void WriteColor(string message, Color color)
    {
        string colorCode = $"{color.R},{color.G},{color.B},{color.A}";
        _output += $"[Color={colorCode}]{message}[/Color]\n";
        TrimOutputBuffer();
    }
    
    public void Write(string message)
    {
        _output += message;
        // log [Color=255,0,0,255]G[/Color][Color=0,255,0,255]A[/Color][Color=0,0,255,255]Y[/Color]
        TrimOutputBuffer();
    }

    public void ClearConsole()
    {
        _output = string.Empty;
    }

    public void Exit()
    {
        Raylib.CloseWindow();
    }
    
    public void ToggleConsole()
    {
        IsOpen = !IsOpen;
    }
    
    public void Update()
    {
        if (Raylib.IsKeyPressed(KeyboardKey.Grave))
        {
            ToggleConsole();
        }

        if (CommandsManager.CurrentContext != null && hint != CommandsManager.CurrentContext.GetType().FullName)
        {
            hint = CommandsManager.CurrentContext.GetType().FullName;
        }
    }

    public void Draw()
    {
        if (!IsOpen) return;

        ImGui.SetNextWindowSize(new System.Numerics.Vector2(Raylib.GetScreenWidth(), (float)(Raylib.GetScreenHeight() * 0.75)), ImGuiCond.Always);
        ImGui.SetNextWindowPos(new System.Numerics.Vector2(0, 0), ImGuiCond.Always);

        if (ImGui.Begin("Cogwheel Console", ImGuiWindowFlags.NoResize | ImGuiWindowFlags.NoMove | ImGuiWindowFlags.NoCollapse | ImGuiWindowFlags.NoTitleBar))
        {
            // Display the output text in a scrollable region
            ImGui.BeginChild("ScrollingRegion", new System.Numerics.Vector2(0, -ImGui.GetTextLineHeightWithSpacing() - 10), ImGuiChildFlags.None);

            // Split the output into lines
            var lines = _output.Split('\n');
            var regex = new Regex(@"\[Color=(\d+),(\d+),(\d+),(\d+)\](.*?)\[/Color\]", RegexOptions.Compiled);

            foreach (var line in lines)
            {
                var matches = regex.Matches(line);
                int lastIndex = 0;

                foreach (Match match in matches)
                {
                    // Add text before the color tag
                    if (match.Index > lastIndex)
                    {
                        ImGui.PushStyleColor(ImGuiCol.Text, new System.Numerics.Vector4(1.0f, 1.0f, 1.0f, 1.0f)); // White for normal text
                        ImGui.Text(line.Substring(lastIndex, match.Index - lastIndex));
                        ImGui.PopStyleColor();
                        ImGui.SameLine(0, 0);
                    }

                    // Set the color for the text inside the color tags
                    var color = new System.Numerics.Vector4(
                        float.Parse(match.Groups[1].Value) / 255.0f,
                        float.Parse(match.Groups[2].Value) / 255.0f,
                        float.Parse(match.Groups[3].Value) / 255.0f,
                        float.Parse(match.Groups[4].Value) / 255.0f
                    );

                    ImGui.PushStyleColor(ImGuiCol.Text, color);
                    ImGui.Text(match.Groups[5].Value);
                    ImGui.PopStyleColor();
                    ImGui.SameLine(0, 0);

                    lastIndex = match.Index + match.Length;
                }

                // Add remaining text after the last color tag
                if (lastIndex < line.Length)
                {
                    ImGui.PushStyleColor(ImGuiCol.Text, new System.Numerics.Vector4(1.0f, 1.0f, 1.0f, 1.0f)); // White for normal text
                    ImGui.Text(line.Substring(lastIndex));
                    ImGui.PopStyleColor();
                }
                ImGui.NewLine(); // Move to the next line after processing the current line
            }

            if (_scrollToBottom)
            {
                ImGui.SetScrollHereY(1.0f);
                _scrollToBottom = false;
            }
            ImGui.EndChild();

            ImGui.Separator();

            ImGui.SetKeyboardFocusHere();
            ImGui.PushStyleColor(ImGuiCol.FrameBg, new System.Numerics.Vector4(0, 0, 0, 1));
            ImGui.PushItemWidth(-1);
            ImGui.InputText("", ref _input, 256, ImGuiInputTextFlags.EnterReturnsTrue);
            ImGui.PopItemWidth();
            ImGui.PopStyleColor();

            if (_input != "" && ImGui.IsKeyPressed(ImGuiKey.Enter))
            {
                ProcessInput(_input);
                _input = string.Empty;
                _scrollToBottom = true;
            }
        }
    }

    private void ProcessInput(string input)
    {
        _output += "\n" + "> " + input + "\n";
        TrimOutputBuffer();
        
        COGWHEEL.RunCommand(input);
    }
    
    private void TrimOutputBuffer()
    {
        var lines = _output.Split('\n');
        if (lines.Length > _output_buffer_size)
        {
            _output = string.Join("\n", lines.Skip(lines.Length - _output_buffer_size));
        }
    }

    [Command(Name = "test")]
    private void Test()
    {
        Write("[COLOR=255,0,255,255] Test command executed!");
    }
}