using Godot;
using Sfs3.Client.Entities;
using Sfs3.Client.Entities.Managers;
using Sfs3.Client.Entities.Variables;
using System;
using System.Collections.Generic;
using System.Linq;

public partial class GameLauncher : Control
{
	[Export]
	public PopupDialog launchPanel;
	[Export]
	public CheckBox publicGameCheck;
	[Export]
	public Label expLabel;
	[Export]
	public Label rankLabel;
	[Export]
	public LineEdit invitationMsgInput;
	[Export]
	public VBoxContainer invitationBuddyList;
	[Export]
	public Label offlineAlertLabel;

	private readonly Dictionary<string, CheckBox> inviteCheckBoxes = [];
	private ButtonGroup inviteCheckBoxButtonGroup;

	private Action showLauncherAction;
	private Action<bool, string> startGameAction;

	public override void _Ready()
	{
		inviteCheckBoxButtonGroup = new ButtonGroup();
		inviteCheckBoxButtonGroup.AllowUnpress = true;
	}

	public Action ShowLauncherAction
	{
		get => showLauncherAction;
		set => showLauncherAction = value;
    }

	public Action<bool, string> StartGameAction
	{
		get => startGameAction;
		set => startGameAction = value;
	}

	public string InvitationMessage => invitationMsgInput.Text;

	public void Init(bool isUserOnline, string userExp, short userRank)
	{
		publicGameCheck.SetPressedNoSignal(true);
		EnableInvitations(false);

		foreach (CheckBox cb in inviteCheckBoxes.Values)
        	cb.SetPressedNoSignal(false);

		expLabel.Text = userExp;
		rankLabel.Text = userRank.ToString();

		// Show/hide buddy list
		invitationBuddyList.Visible = isUserOnline;
		offlineAlertLabel.Visible = !isUserOnline;
	}

	public void UpdateInviteList(Buddy buddy, bool doRemove = false)
	{
		inviteCheckBoxes.TryGetValue(buddy.Name, out CheckBox inviteCheckBox);

		if (inviteCheckBox != null)
		{
			if (doRemove)
			{
				// Remove buddy list item from dictionary
				inviteCheckBoxes.Remove(buddy.Name);

				// Remove invite list item
				invitationBuddyList.RemoveChild(inviteCheckBox);
			}
			else
			{
				// Update existing item
				SetInviteListItemState(inviteCheckBox, buddy);
			}
		}
		else
		{
			// Create invite list item
			inviteCheckBox = new CheckBox();
			inviteCheckBox.ButtonGroup = inviteCheckBoxButtonGroup;
			inviteCheckBox.SetPressedNoSignal(false);
			inviteCheckBox.SetMeta("value", buddy.Name);

			// Add buddy list item to container
			invitationBuddyList.AddChild(inviteCheckBox);

			// Add buddy list item to dictionary
			inviteCheckBoxes.Add(buddy.Name, inviteCheckBox);

			// Init invite list toggle
			SetInviteListItemState(inviteCheckBox, buddy);
		}
	}

	private void SetInviteListItemState(CheckBox inviteListItem, Buddy buddy)
	{
		// Nickname
		inviteListItem.Text = buddy.DisplayName;

		// Status
		inviteListItem.Disabled = buddy.IsBlocked || !buddy.IsOnline || buddy.State == "Away";

		if (inviteListItem.Disabled)
			inviteListItem.SetPressedNoSignal(false);
	}
	
	private void EnableInvitations(bool enable)
    {
		invitationMsgInput.Editable = enable;

		// Disable interaction for all items
		if (!enable)
		{
			invitationBuddyList.PropagateCall("set_mouse_filter", new Godot.Collections.Array { (int)Control.MouseFilterEnum.Ignore });

			// Also inhibit focus and uncheck all
			foreach (CheckBox cb in inviteCheckBoxes.Values)
			{
				cb.SetPressedNoSignal(false);
				cb.FocusMode = FocusModeEnum.None;
			}
		}
		else
		{
			invitationBuddyList.PropagateCall("set_mouse_filter", new Godot.Collections.Array { (int)Control.MouseFilterEnum.Stop });

			// Also re-enable focus
			foreach (CheckBox cb in inviteCheckBoxes.Values)
			{
				cb.FocusMode = FocusModeEnum.All;
			}
		}
    }

	// -------------------------------------------------------------------

	public void OnNewGameButtonClick()
    {
		launchPanel.Visible = true;

		// Fire event
		showLauncherAction?.Invoke();
    }

    public void OnPublicGameCheckChange(bool isChecked)
	{
		invitationMsgInput.Editable = !isChecked;

		EnableInvitations(!isChecked);
    }

	public void OnStartGameButtonClick()
	{
		// Get invited buddy
		string invitedBuddyName = null;

		foreach (CheckBox cb in inviteCheckBoxes.Values)
			if (cb.ButtonPressed)
				invitedBuddyName = (string)cb.GetMeta("value");

		// Dispatch event
		startGameAction?.Invoke(publicGameCheck.ButtonPressed, invitedBuddyName);

        // Hide panel
		launchPanel.Visible = false;
    }
}
