using Godot;
using Sfs3.Client.Entities.Invitation;
using System;

/**
 * Script attached to the main node in the InvitationPanel scene.
 */
public partial class InvitationPanel : Control
{
	[Export]
	public Label invMessageLabel;
	[Export]
	public Label invDetailsLabel;
	[Export]
	public Label expirationLabel;

	private const string expirationText = "This invitation will expire in {0} second{1}.";

	private Action<Invitation, bool> invitationReplyAction;
	private InvitationWrapper invitationWrapper;
	private float inviteExpireTimerSecs = 0f;

	public Action<Invitation, bool> InvitationReplyAction
	{
		get => invitationReplyAction;
		set => invitationReplyAction = value;
	}

	/**
	 * Update the invitation expiration timer.
	 */
	public override void _Process(double delta)
	{
		if (inviteExpireTimerSecs > 0)
		{
			inviteExpireTimerSecs -= (float)delta;

			// Update expire message
			ShowCountdown();

			if ((int)Math.Round(inviteExpireTimerSecs, 0) == 0)
			{
				inviteExpireTimerSecs = 0f;

				// Refuse the invitation, as no reply was provided in time
				Reply(false);
			}
		}
	}

	/**
	 * Show the panel with the invitation details.
	 */
	public void ShowInvitation(InvitationWrapper iw)
	{
		invitationWrapper = iw;

		// Update invitation UI
		invMessageLabel.Text = iw.Invitation.Params.GetString("message");
		invMessageLabel.Visible = invMessageLabel.Text != "";

		invDetailsLabel.Text = String.Format("You have been invited by {0} to play {1}.", iw.Invitation.Inviter.Name, iw.Invitation.Params.GetString("room"));

		// Display remaining time for replying
		inviteExpireTimerSecs = iw.ExpiresInSeconds;
		ShowCountdown();

		// Show panel
		Visible = true;
	}

	/**
	 * Hide the panel, refusing the invitation being displayed (if any).
	 */
	public void HideAndRefuse()
	{
		if (invitationWrapper != null)
			Reply(false);
	}

	//----------------------------------------------------------
	// UI event listeners
	//----------------------------------------------------------
	#region
	public void OnAcceptButtonClick()
	{
		Reply(true);
	}

	public void OnRefuseButtonClick()
	{
		Reply(false);
	}

	public void OnCloseButtonClick()
	{
		Reply(false);
	}
	#endregion

	//----------------------------------------------------------
	// Helper methods
	//----------------------------------------------------------
	#region
	private void Reply(bool accept)
	{
		// Stop expiration timer
		inviteExpireTimerSecs = 0f;

		Invitation invitation = invitationWrapper.Invitation;

		// Delete reference to invitation wrapper
		invitationWrapper = null;

		// Hide panel
		Visible = false;

		// Notify the controller
		invitationReplyAction?.Invoke(invitation, accept);
	}

	/**
	 * Display the countdown to expiration.
	 */
	private void ShowCountdown()
	{
		int secs = (int)Math.Floor(inviteExpireTimerSecs);

		expirationLabel.Text = String.Format(expirationText, secs, secs == 1 ? "" : "s");
	}
	#endregion
}
