using System.Collections.Generic;
using Godot;

// Галерея всех вытащенных текстур (UI, фоны, эффекты, нарезанные спрайты атласа).
//   A / D (← / →) — предыдущая / следующая картинка
//   W / S (↑ / ↓) — предыдущая / следующая категория (папка)
//   колесо мыши    — зум,  R — сброс
public partial class TextureGallery : Node2D
{
	private static readonly string[] Folders =
	{
		"ui", "ui_sliced", "backgrounds", "fx", "room_sliced", "cursors", "icons", "atlas", "misc"
	};

	private struct Cat { public string Name; public string[] Files; }

	private Cat[] _cats = System.Array.Empty<Cat>();
	private int _ci, _fi;
	private float _zoom = 1f;

	private Sprite2D _sprite;
	private Label _label;

	public override void _Ready()
	{
		var bg = new ColorRect
		{
			Color = new Color(0.10f, 0.11f, 0.13f),
			AnchorRight = 1, AnchorBottom = 1,
			MouseFilter = Control.MouseFilterEnum.Ignore
		};
		AddChild(bg);

		_sprite = new Sprite2D();
		AddChild(_sprite);

		_label = new Label { Position = new Vector2(16, 12) };
		_label.AddThemeFontSizeOverride("font_size", 18);
		_label.AddThemeConstantOverride("outline_size", 4);
		_label.AddThemeColorOverride("font_outline_color", Colors.Black);
		AddChild(_label);

		Scan();
		if (_cats.Length == 0)
			_label.Text = "Нет текстур в res://assets/";
		else
			ShowCurrent();
	}

	private void Scan()
	{
		var cats = new List<Cat>();
		foreach (string folder in Folders)
		{
			string dirPath = "res://assets/" + folder;
			var d = DirAccess.Open(dirPath);
			if (d == null)
				continue;

			var files = new List<string>();
			d.ListDirBegin();
			for (string name = d.GetNext(); name != ""; name = d.GetNext())
			{
				if (!d.CurrentIsDir() && name.EndsWith(".png"))
					files.Add(dirPath + "/" + name);
			}
			d.ListDirEnd();

			if (files.Count > 0)
			{
				files.Sort();
				cats.Add(new Cat { Name = folder, Files = files.ToArray() });
			}
		}
		_cats = cats.ToArray();
	}

	private void ShowCurrent()
	{
		Cat cat = _cats[_ci];
		string path = cat.Files[_fi];
		var tex = ResourceLoader.Load<Texture2D>(path);
		_sprite.Texture = tex;
		ApplyTransform();
		UpdateLabel();
	}

	private void ApplyTransform()
	{
		if (_sprite.Texture == null)
			return;
		Vector2 vp = GetViewportRect().Size;
		Vector2 ts = _sprite.Texture.GetSize();
		float fit = Mathf.Min(vp.X * 0.85f / ts.X, vp.Y * 0.68f / ts.Y);
		fit = Mathf.Clamp(fit, 0.02f, 8f);
		_sprite.Scale = Vector2.One * fit * _zoom;
		_sprite.Position = new Vector2(vp.X * 0.5f, vp.Y * 0.56f);
	}

	private void UpdateLabel()
	{
		Cat cat = _cats[_ci];
		string path = cat.Files[_fi];
		string file = path.GetFile();
		Vector2 ts = _sprite.Texture != null ? _sprite.Texture.GetSize() : Vector2.Zero;
		_label.Text =
			$"Категория: {cat.Name}  ({_ci + 1}/{_cats.Length})        [W/S]\n" +
			$"Файл: {file}  ({_fi + 1}/{cat.Files.Length})        [A/D]\n" +
			$"размер {ts.X:0}x{ts.Y:0}   зум x{_zoom:0.00}  —  колесо;  R — сброс   ·   Esc — меню";
	}

	private void NextCat(int dir)
	{
		_ci = Wrap(_ci + dir, _cats.Length);
		_fi = 0;
		_zoom = 1f;
		ShowCurrent();
	}

	private void NextFile(int dir)
	{
		_fi = Wrap(_fi + dir, _cats[_ci].Files.Length);
		ShowCurrent();
	}

	private void Zoom(float factor)
	{
		_zoom = Mathf.Clamp(_zoom * factor, 0.1f, 12f);
		ApplyTransform();
		UpdateLabel();
	}

	private static int Wrap(int i, int n) => n <= 0 ? 0 : ((i % n) + n) % n;

	public override void _UnhandledInput(InputEvent @event)
	{
		if (@event is InputEventKey esc && esc.Pressed && esc.Keycode == Key.Escape)
		{
			GetTree().ChangeSceneToFile("res://scenes/MainMenu.tscn");
			return;
		}
		if (_cats.Length == 0)
			return;

		if (@event is InputEventMouseButton mb && mb.Pressed)
		{
			if (mb.ButtonIndex == MouseButton.WheelUp) { Zoom(1.1f); return; }
			if (mb.ButtonIndex == MouseButton.WheelDown) { Zoom(1f / 1.1f); return; }
		}

		if (@event is not InputEventKey k || !k.Pressed || k.Echo)
			return;

		switch (k.Keycode)
		{
			case Key.D: case Key.Right: NextFile(1); break;
			case Key.A: case Key.Left: NextFile(-1); break;
			case Key.S: case Key.Down: NextCat(1); break;
			case Key.W: case Key.Up: NextCat(-1); break;
			case Key.R: _zoom = 1f; ApplyTransform(); UpdateLabel(); break;
		}
	}
}
