using DoomDeathmatch.Component;
using DoomDeathmatch.Component.MVC.Controller;
using DoomDeathmatch.Component.MVC.View;
using DoomDeathmatch.Component.UI;
using DoomDeathmatch.Component.Util;
using Engine.Asset.Mesh;
using Engine.Graphics.Pipeline;
using Engine.Graphics.Texture;
using Engine.Scene;
using Engine.Scene.Component.BuiltIn;
using Engine.Scene.Component.BuiltIn.Renderer;
using OpenTK.Mathematics;

namespace DoomDeathmatch.Scene.Play;

public static class PlayScene
{
  public static Engine.Scene.Scene Create(Engine.Engine parEngine)
  {
    var scene = new Engine.Scene.Scene();

    var (hudCameraObject, hudCamera) = UiUtil.CreateOrthographicCamera(scene, RenderLayer.HUD);
    var (uiContainerObject, uiContainer) =
      UiUtil.CreateContainerUi(scene, new UiContainerComponent { Camera = hudCamera });

    var (bottomContainerObject, bottomContainer) =
      UiUtil.CreateContainerUi(scene, new UiContainerComponent { Container = uiContainer });
    bottomContainer.Anchor = Anchor.BottomCenter;
    bottomContainer.Center = Anchor.BottomCenter;
    bottomContainerObject.AddComponent(new Box2DRenderer
    {
      Color = new Vector4(1, 0, 0, 1), RenderLayer = RenderLayer.HUD
    });
    bottomContainerObject.AddComponent(new CopySizeComponent
    {
      Target = uiContainerObject.Transform, Coefficient = new Vector3(1, 0, 1)
    });
    bottomContainerObject.Transform.Size.Y = 1.5f;
    scene.AddChild(uiContainerObject, bottomContainerObject);

    var (gunObject, (gunUi, gunSprite)) = UiUtil.CreateSpriteUi(scene, bottomContainer,
      parEngine.AssetResourceManager.Load<Texture>("texture/pistol.png"), RenderLayer.HUD);
    gunObject.Transform.Scale = new Vector3(5);
    gunUi.Anchor = Anchor.TopCenter;
    gunUi.Center = Anchor.BottomCenter;
    scene.AddChild(bottomContainerObject, gunObject);

    var (healthObject, healthUi, (_, healthTextRenderer)) =
      UiUtil.CreateTextUi(scene, bottomContainer, UiUtil.GetDoomFont(parEngine), "Здоровье: 000",
        TextAlignComponent.Align.Center,
        RenderLayer.HUD);
    healthObject.Transform.Scale = new Vector3(0.75f);
    healthUi.Anchor = Anchor.CenterLeft;
    healthUi.Center = Anchor.CenterLeft;
    scene.AddChild(bottomContainerObject, healthObject);

    var (ammoObject, ammoUi, (_, ammoTextRenderer)) =
      UiUtil.CreateTextUi(scene, bottomContainer, UiUtil.GetDoomFont(parEngine), "Патроны: 00/00",
        TextAlignComponent.Align.Center,
        RenderLayer.HUD);
    ammoObject.Transform.Scale = new Vector3(0.75f);
    ammoUi.Anchor = Anchor.TopRight;
    ammoUi.Center = Anchor.TopRight;
    scene.AddChild(bottomContainerObject, ammoObject);

    var (weaponObject, weaponUi, (_, weaponTextRenderer)) =
      UiUtil.CreateTextUi(scene, bottomContainer, UiUtil.GetDoomFont(parEngine), "Оружие: ОРУЖИЕОР",
        TextAlignComponent.Align.Center,
        RenderLayer.HUD);
    weaponObject.Transform.Scale = new Vector3(0.75f);
    weaponUi.Anchor = Anchor.BottomRight;
    weaponUi.Center = Anchor.BottomRight;
    scene.AddChild(bottomContainerObject, weaponObject);

    var (topContainerObject, topContainer) =
      UiUtil.CreateContainerUi(scene, new UiContainerComponent { Container = uiContainer });
    topContainer.Anchor = Anchor.TopCenter;
    topContainer.Center = Anchor.TopCenter;
    topContainerObject.AddComponent(
      new Box2DRenderer { Color = new Vector4(1, 0, 0, 1), RenderLayer = RenderLayer.HUD });
    topContainerObject.AddComponent(new CopySizeComponent
    {
      Target = uiContainerObject.Transform, Coefficient = new Vector3(1, 0, 1)
    });
    topContainerObject.Transform.Size.Y = 1f;
    scene.AddChild(uiContainerObject, topContainerObject);

    var (timerObject, timerUi, _) =
      UiUtil.CreateTextUi(scene, topContainer, UiUtil.GetDoomFont(parEngine), "Время: 00:00",
        parRenderLayer: RenderLayer.HUD);
    timerUi.Anchor = Anchor.CenterLeft;
    timerUi.Center = Anchor.CenterLeft;
    scene.AddChild(topContainerObject, timerObject);

    var (scoreObject, scoreUi, (_, scoreTextRenderer)) =
      UiUtil.CreateTextUi(scene, topContainer, UiUtil.GetDoomFont(parEngine), "Счет: 00000",
        parRenderLayer: RenderLayer.HUD);
    scoreUi.Anchor = Anchor.CenterRight;
    scoreUi.Center = Anchor.CenterRight;
    scene.AddChild(topContainerObject, scoreObject);

    var playerObject = GameObjectUtil.CreateGameObject(scene, [
      new RigidbodyComponent(),
      new ControllerComponent { Speed = 5f },
      new DragComponent { Drag = 5f, Coefficient = new Vector3(1, 1, 0) },

      new PlayerController(),

      new WeaponController(),
      new WeaponView(weaponTextRenderer, ammoTextRenderer, gunSprite),

      new HealthController(),
      new HealthView(healthTextRenderer),

      new ScoreController(),
      new ScoreView(scoreTextRenderer),
    ]);

    var (perspectiveCameraObject, perspectiveCamera) = UiUtil.CreatePerspectiveCamera(scene);
    perspectiveCameraObject.Transform.Translation.Z = 2;

    var mapObject = GameObjectUtil.CreateGameObject(scene, [
      new MeshRenderer { Mesh = parEngine.AssetResourceManager.Load<Mesh>("model/map.obj") },
    ]);

    var impObject = GameObjectUtil.CreateGameObject(scene,
      new Transform { Translation = new Vector3(0, 0, 1), Scale = new Vector3(1, 2, 1), }, [
        new Box2DRenderer { Texture = parEngine.AssetResourceManager.Load<Texture>("texture/imp.png") },
        new BillboardComponent { Target = perspectiveCameraObject.Transform }
      ]);

    scene.AddChild(playerObject, perspectiveCameraObject);

    return scene;
  }
}