using Godot;
using Sfs3.Client.Entities;
using System;
using System.Collections.Generic;

/**
 * Script attached to the main node in the BuddyList scene.
 */
public partial class BuddyList : VBoxContainer
{
	private Action<string> startChatAction;
	private Action<string> blockAction;
	private Action<string> removeAction;
	private Action<string> addAction;

	private readonly Dictionary<string, BuddyListItem> itemNodes = [];

	public Action<string> StartChatAction
	{
		get => startChatAction;
		set => startChatAction = value;
	}

	public Action<string> BlockAction
	{
		get => blockAction;
		set => blockAction = value;
	}

	public Action<string> RemoveAction
	{
		get => removeAction;
		set => removeAction = value;
	}

	public Action<string> AddAction
	{
		get => addAction;
		set => addAction = value;
	}

	public void AddListItem(Buddy buddy, bool toTop = false)
	{
		// Check if buddy list item already exist
		// This could happen if a temporary buddy is added permanently
		BuddyListItem item = GetListItem(buddy.Name);

		if (item != null)
		{
			item.Update(buddy);
		}
		else
		{
			// Instantiate BuddyListItem and add to dictionary
			item = ResourceLoader.Load<PackedScene>("res://scenes/sub/BuddyListItem.tscn").Instantiate<BuddyListItem>();
			itemNodes.Add(buddy.Name, item);

			// Init buddy list item
			item.Update(buddy);

			// Set unread messages counter
			// (buddy could have sent messages while user was in the game scene)
			item.UpdateUnreadMsgCounter(BuddyChatHistoryManager.GetUnreadMessagesCount(buddy.Name));

			// Add node to scene
			AddChild(item);

			if (toTop)
				MoveListItemToTop(buddy.Name);

			// Add listeners to buttons
			item.chatButton.Pressed += () => { startChatAction?.Invoke(buddy.Name); };
			item.blockButton.Pressed += () => { blockAction?.Invoke(buddy.Name); };
			item.unblockButton.Pressed += () => { blockAction?.Invoke(buddy.Name); };
			item.removeButton.Pressed += () => { removeAction?.Invoke(buddy.Name); };
			item.addButton.Pressed += () => { addAction?.Invoke(buddy.Name); };
		}
	}

	public void MoveListItemToTop(string buddyName)
	{
		if (itemNodes.TryGetValue(buddyName, out BuddyListItem item))
			MoveChild(item, 0);
	}

	public void UpdateListItem(Buddy buddy)
	{
		// Get reference to buddy list item corresponding to Buddy
		BuddyListItem item = GetListItem(buddy.Name);

		if (item != null)
		{
			// Check if the update was caused by a block/unblock request
			if (buddy.IsBlocked != item.BuddyBlocked)
			{
				// Move buddy to the bottom of the list if blocked, to top otherwise
				if (buddy.IsBlocked)
					MoveChild(item, GetChildCount() - 1);
				else
					MoveListItemToTop(buddy.Name);
			}

			// Update buddy list item
			item.Update(buddy);
		}
	}

	public void SetItemState(Buddy buddy)
	{
		GetListItem(buddy.Name)?.Update(buddy);
	}

	public void RemoveListItem(string buddyName)
	{
		if (itemNodes.TryGetValue(buddyName, out BuddyListItem item))
		{
			itemNodes.Remove(buddyName);

			RemoveChild(item);
			item.QueueFree();
		}
	}

	public void SetItemChatMsgCounter(string buddyName, int cnt)
	{
		GetListItem(buddyName)?.UpdateUnreadMsgCounter(cnt);
	}

	private BuddyListItem GetListItem(string buddyName)
	{
		itemNodes.TryGetValue(buddyName, out BuddyListItem item);

		return item;
	}
}
