using Engine.Input;
using Engine.Util;

namespace DoomDeathmatch.Component.UI;

public class TextInputComponent : Engine.Scene.Component.Component
{
  public event Action<string>? OnInput;

  public bool IsActive { get; set; } = false;
  public string Input { get; private set; } = "";

  public float InputDelay
  {
    get => _inputDelay;
    set
    {
      _inputDelay = value;
      _inputTimer.TotalTime = value;
    }
  }

  private readonly IInputHandler _inputHandler = EngineUtil.InputHandler;

  private readonly KeyboardButtonCode[] _acceptedKeys =
    KeyboardButtonCodeHelper.GetAllPrintableKeys().Append(KeyboardButtonCode.Backspace).ToArray();

  private readonly TickableTimer _inputTimer;
  private float _inputDelay = 0;
  private readonly HashSet<KeyboardButtonCode> _lastKeys = [];

  public TextInputComponent(float parInputDelay = 0.2f)
  {
    _inputDelay = parInputDelay;
    _inputTimer = new TickableTimer(_inputDelay) { CurrentTime = 0 };
  }

  public override void Update(double parDeltaTime)
  {
    if (!IsActive)
      return;

    _inputTimer.Update(parDeltaTime);

    foreach (var key in _acceptedKeys)
    {
      if (_lastKeys.Contains(key) && !_inputTimer.IsFinished)
        continue;

      if (_inputHandler.IsKeyPressed(key))
      {
        var invoke = false;
        if (key == KeyboardButtonCode.Backspace)
        {
          if (Input.Length > 0)
          {
            Input = Input[..^1];
            invoke = true;
          }
        }
        else
        {
          Input += key.GetChar();
          invoke = true;
        }

        if (invoke)
          OnInput?.Invoke(Input);

        _lastKeys.Add(key);

        _inputTimer.Reset();
      }
      else
      {
        _lastKeys.Remove(key);
      }
    }
  }
}