using Godot;
using System;
using System.Collections.Generic;
using System.Linq;
using Cirno.Scripts;
using Cirno.Scripts.Resources;
using Cirno.Scripts.UI;
using Cirno.Scripts.Utils;

public partial class Hud : CanvasLayer
{
	public static Hud Instance { get; private set; }
	[Signal]
	public delegate void StartGameEventHandler();
	
	//private Label _healthLabel;

	[Export]
	public PackedScene SelectorScene { get; set; }
	
	[Export]
	public PackedScene WeaponContainerTemplate { get; private set; }
	
	[Export]
	public PackedScene ItemNotificationTemplate { get; private set; }

	[Export] public float ItemsNotificationTimeout { get; private set; } = 3f;
	
	[Export]
	private Node2D _selector;

	[Export] private Label _healthLabel;
	[Export] private ProgressBar _healthBar;
	
	[Export] private Label _shieldLabel;
	[Export] private ProgressBar _shieldBar;

	[Export] private Label _motivationLabel;
	
	[Export] private Container _itemsContainer;
	
	[Export] private LabelSettings _labelSettings;
	
	[Export] private Container _gameOverPanel;
	[Export] private Container _fairyTerminatedPanel;

	[Export] private Container _hudInfoPanel;
	[Export] public Container NotificationsContainer { get; private set; }
	
	[Export] public Container WeaponContainer { get; private set; }
	
	[ExportGroup("Pause Menu")] [Export] 
	public Control PauseMenuContainer;
	[ExportGroup("Pause Menu")] [Export]
	public PackedScene PauseMenuScene;
	
	[ExportGroup("Debug Menu")]
	[Export]
	public PackedScene DebugMenuTemplate { get; set; }
	
	[ExportGroup("Debug Menu")]
	[Export]
	public Control DebugMenuHolder { get; set; }
	
	

	private Dictionary<string, WeaponAmmoCounter> _items = new();
	
	private PauseMenu _pauseMenu;

	private bool _playerDead = false; // useless

	private WeaponAmmoCounter _weapon;
	
	public override void _Ready()
	{
		Instance = this;
		// Assuming the HUD has a Label node named "HealthLabel"
		//_healthLabel = GetNode<Label>("HealthLabel");
		_gameOverPanel.Hide();
		
		InventoryManager.Instance.ItemAdded += OnItemAdded;
	}

	private void OnItemAdded(LootItem item, int currentamount)
	{
		var instance = ItemNotificationTemplate.Instantiate<ItemNotification>();
			
		NotificationsContainer.CallDeferred("add_child", instance);
		
		instance.Init(item, currentamount, ItemsNotificationTimeout);

		if (item.UiType.HasAnyFlag(UiItemType.Ammo | UiItemType.Energy))
		{
			AddWeapon(item);
			return;
		}
		
		if (item.UiType.HasAnyFlag(UiItemType.Icon | UiItemType.Count))
		{
			AddInventoryItem(item, currentamount);
		}
	}

	public void ShowMessage(string text)
	{
		var message = GetNode<Label>("Message");
		message.Text = text;
		message.Show();

		GetNode<Timer>("MessageTimer").Start();
	}

	public void ShowGameOver()
	{
		_gameOverPanel.Show();
		HideHud();
		_playerDead = true;
	}

	public void HideGameOver()
	{
		_gameOverPanel.Hide();
		ShowHud();
		_playerDead = false;
	}

	public void ShowTerminated()
	{
		_fairyTerminatedPanel.Show();
		HideHud();
		_playerDead = true;
	}

	public void HideTerminated()
	{
		_fairyTerminatedPanel.Hide();
		ShowHud();
		_playerDead = false;
	}

	public void ShowHud()
	{
		_hudInfoPanel.Show();
		WeaponContainer.Show();
	}

	public void HideHud()
	{
		_hudInfoPanel.Hide();
		WeaponContainer.Hide();
	}
	
	public void UpdateHealth(float newHealth, float maxHealth)
	{
		// Hide game over if player is no longer dead
		if (_playerDead && newHealth > 0)
		{
			_playerDead = false;
			_fairyTerminatedPanel.Hide();
		}
		
		_healthLabel.Text = $"{newHealth:N0}/{maxHealth:N0}";
		if (_healthBar != null)
		{
			_healthBar.Value = newHealth;
		}
	}
	
	public void UpdateShield(float newValue, float maxValue)
	{
		_shieldLabel.Text = $"{newValue:N0}/{maxValue:N0}";
		if (_shieldBar != null)
		{
			_shieldBar.Value = newValue;
		}
	}
	
	public void UpdateMotivation(float newValue, float maxValue)
	{
		_motivationLabel.Text = $"{newValue:N0}%";
	}

	public void UpdateInteractable(Interactable interactable) {
		GD.Print($"Interactable ${interactable.Name} entered in HUD");
		//_selector.Position = _selector.tolo
	}

	private void AddWeapon(LootItem item)
	{
		_weapon?.Delete();
		
		var instance = WeaponContainerTemplate.Instantiate<WeaponAmmoCounter>();
			
		WeaponContainer.CallDeferred("add_child", instance);
		
		instance.Init(item);

		_weapon = instance;
	}
	
	public void AddInventoryItem(LootItem item, int currentAmount)
	{
		if (item.UiType == 0) return;
		
		if (!_items.TryGetValue(item.ItemKey, out var item1))
		{
			var instance = WeaponContainerTemplate.Instantiate<WeaponAmmoCounter>();
			
			_itemsContainer.CallDeferred("add_child", instance);
			
			// var hbox = new HBoxContainer();
			// _itemsContainer.AddChild(hbox);
			//
			// var instance = new TextureRect();
			// instance.Texture = item.InventorySprite;
			// instance.StretchMode = TextureRect.StretchModeEnum.Keep;
		
			// hbox.AddChild(instance);

			// var hudItem = new HudItem()
			// {
			// 	Item = item,
			// 	Container = hbox,
			// 	//Amount = currentAmount
			// };
			
			// if (item.UiType == UiItemType.IconText)
			// {
			// 	var label = new Label();
			// 	label.Text = currentAmount.ToString();
			// 	
			//
			// 	label.LabelSettings = _labelSettings;
			// 	hbox.AddChild(label);
			//
			// 	hudItem.Label = label;
			// }
			
			_items.Add(item.ItemKey, instance);
			
			instance.Init(item);
		}
		else
		{
			// nothing
			// if (item.UiType == UiItemType.IconText && item1.Label != null)
			// {
			// 	item1.Label.Text = currentAmount.ToString();
			// }
		}
		
		// TextureRect texture = new TextureRect();
		// texture.Texture = item.InventorySprite;
		//
		// texture.ExpandMode = TextureRect.ExpandModeEnum.KeepSize;
		// texture.StretchMode = TextureRect.StretchModeEnum.Keep;
		//
		// _itemsContainer.AddChild(texture);
	}

	public void OnGameStateChanged(GameState state)
	{
		switch (state)
		{
			case GameState.Paused:
				SpawnPauseMenu();
				break;
			case GameState.Controlling:
			case GameState.Menu:
			case GameState.Playing:
			case GameState.Dialogue:
			default:
				ClearPauseMenu();
				break;
		}
	}

	private void SpawnPauseMenu()
	{
		if (PauseMenuContainer is null || PauseMenuScene is null) return;

		PauseMenuContainer.Visible = true;
		
		_pauseMenu = PauseMenuScene.Instantiate<PauseMenu>();

		PauseMenuContainer.CallDeferred("add_child", _pauseMenu);

		_pauseMenu.SpawnDebugMenu += SpawnDebugMenu;
	}

	private void ClearPauseMenu()
	{
		if (PauseMenuContainer is null) return;

		if (_pauseMenu is not null)
		{
			_pauseMenu.SpawnDebugMenu -= SpawnDebugMenu;
		}

		PauseMenuContainer.Visible = false;
		
		var children = PauseMenuContainer.GetChildren();
		foreach (var child in children)
		{
			child.QueueFree();
		}
	}

	// public void RemoveInventoryItem(string itemKey, int currentAmount)
	// {
	// 	if (_items.TryGetValue(itemKey, out var itm))
	// 	{
	// 		if (currentAmount <= 0)
	// 		{
	// 			itm.Container.QueueFree();
	// 			_items.Remove(itemKey);
	// 		}
	// 		else
	// 		{
	// 			if (itm.Item.UiType == UiItemType.IconText)
	// 			{
	// 				itm.Label.Text = currentAmount.ToString();
	// 			}
	// 		}
	// 	}
	// 	else
	// 	{
	// 		GD.Print($"Tried to remove item  {itemKey} but it was not found");
	// 	}
	// 	
	// 	// var containerItem = _items.FirstOrDefault(x => x.Item == item);
	// 	// if (containerItem == null)
	// 	// {
	// 	// 	GD.Print($"Tried to remove item {item.ItemName} but it was not found");
	// 	// 	return;
	// 	// }
	// 	//
	// 	// containerItem.Container.QueueFree();
	// 	
	// }

	private void SpawnDebugMenu()
	{
		ClearPauseMenu();
		
		if (DebugMenuTemplate is null || DebugMenuHolder is null) return;
		DebugMenuHolder.Visible = true;
			
		var children = DebugMenuHolder.GetChildren();
		foreach (var child in children)
		{
			child.QueueFree();
		}
			
		var menu = DebugMenuTemplate.Instantiate<DebugMenu>();
			
		DebugMenuHolder.CallDeferred("add_child", menu);

		menu.MenuClosed += () =>
		{
			DebugMenuHolder.Visible = false;
			if (GameManager.Instance.GameState is GameState.Paused)
			{
				SpawnPauseMenu();
			}
		};
	}

	public class HudItem
	{
		public LootItem Item { get; set; }
		public HBoxContainer Container { get; set; }
		public Label Label { get; set; }
		
		//public int Amount { get; set; }
	}

	public void EquipWeapon(string itemKey)
	{
		if (_items.TryGetValue(itemKey, out var localItem))
		{
			// It's already in the hud, abort
			GD.Print($"Item with key {itemKey} is already in hud, aborting.");
			return;
		}
		
		if (!InventoryManager.Instance.TryGetItem(itemKey, out var item))
		{
			GD.Print($"Item with key {itemKey} not found in inventory when equipping in hud.");
			return;
		}
		
		// Clear all items
		// foreach (var hudItem in _items)
		// {
		// 	hudItem.Value.Delete();
		// }
		// _items.Clear();
		
		AddWeapon(item.Item);
		//AddInventoryItem(item.Item, item.Count);
	}

	
}
