using DoomDeathmatch.Component.MVC.Model.Weapon;
using DoomDeathmatch.Component.Util;
using DoomDeathmatch.Component.Util.Collision;
using Engine.Graphics.Pipeline;
using Engine.Input;
using Engine.Scene.Component.BuiltIn;
using Engine.Scene.Component.BuiltIn.Renderer;
using OpenTK.Mathematics;

namespace DoomDeathmatch.Component.MVC.Controller;

public class PlayerController : Engine.Scene.Component.Component
{
  public bool IsPaused { get; set; } = false;
  public HealthController HealthController => _healthController;
  public PerspectiveCamera Camera => _camera;

  private readonly IInputHandler _inputHandler = Engine.Engine.Instance.InputHandler!;

  private HealthController _healthController = null!;
  private WeaponController _weaponController = null!;
  private readonly PerspectiveCamera _camera;

  public PlayerController(PerspectiveCamera parCamera)
  {
    _camera = parCamera;
  }

  public override void Awake()
  {
    _healthController = GameObject.GetComponent<HealthController>()!;
    _weaponController = GameObject.GetComponent<WeaponController>()!;

    ArgumentNullException.ThrowIfNull(_healthController);
    ArgumentNullException.ThrowIfNull(_weaponController);
  }

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

    if (_inputHandler.IsKeyJustPressed(KeyboardButtonCode.C))
      _weaponController.AddWeapon(WeaponData.Shotgun);

    for (var i = 0; i < 10; i++)
    {
      if (KeyboardButtonCode.D1 + i > KeyboardButtonCode.D0)
        break;

      if (!_inputHandler.IsKeyJustPressed(KeyboardButtonCode.D1 + i))
        continue;

      _weaponController.SelectWeapon(i);
      break;
    }

    if (_inputHandler.IsKeyJustPressed(KeyboardButtonCode.Space))
    {
      if (!_weaponController.TryShoot())
        return;

      var position = _camera.GameObject.Transform.GetFullTranslation();
      var forward = (_camera.Forward - position).Normalized();
      var right = Vector3.Cross(forward, Vector3.UnitZ).Normalized();

      var collisionManager = GameObject.Scene!.FindFirstComponent<CollisionManager>();

      var offsets = _weaponController.WeaponData.ShootPattern.GetShootPattern(forward, Vector3.UnitZ, right);
      foreach (var offset in offsets)
      {
        var direction = forward + offset;
        if (!collisionManager!.Raycast(position, direction, ["enemy", "wall"], out var result))
          continue;

        var hitDisplayObject = GameObjectUtil.CreateGameObject(GameObject.Scene,
          new Transform { Translation = result.HitPoint, Size = new Vector3(0.1f) },
          [
            new Box2DRenderer { Color = new Vector4(0, 0, 1, 1), RenderLayer = RenderLayer.DEFAULT },
            new BillboardComponent { Target = _camera.GameObject.Transform }
          ]
        );

        var hitNormalDisplayObject = GameObjectUtil.CreateGameObject(GameObject.Scene,
          new Transform { Translation = result.HitPoint + result.Normal, Size = new Vector3(0.1f) },
          [
            new Box2DRenderer { Color = new Vector4(1, 0, 1, 1), RenderLayer = RenderLayer.DEFAULT },
            new BillboardComponent { Target = _camera.GameObject.Transform }
          ]
        );

        var enemyController = result.HitObject.GetComponent<EnemyController>();
        enemyController?.HealthController.TakeDamage(_weaponController.WeaponData.Damage);
      }
    }
  }
}