using System;
using System.Collections.Generic;
using System.Threading.Tasks;
using Godot;
using Sfs3.Client.Entities.Audio;

public partial class CallPanel : Panel
{
	[Export]
	public Button closeButton;
	[Export]
	public Button muteButton;
	[Export]
	public AudioMeter myAudioMeter;
	[Export]
	public ScrollContainer scrollContainer;
	[Export]
	public VBoxContainer participantContainer;
	[Export]
	public bool disabled;

	private Action stopCallAction;
	private Action<bool> muteAction;

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

	public Action StopCallAction
	{
		get => stopCallAction;
		set => stopCallAction = value;
	}

	public Action<bool> MuteAction
	{
		get => muteAction;
		set => muteAction = value;
	}

	public override void _Ready()
	{
		Disabled = disabled;
	}
	
	public bool Disabled
	{
		get => disabled;

		set
		{
			closeButton.Disabled = value;
			muteButton.Disabled = value;

			if (value)
				myAudioMeter.Visible = false;
		}
	}

	public void SetVisible()
    {
        this.Visible = true;
    }

	public void Reset()
	{
		itemNodes.Clear();

		foreach (Node child in participantContainer.GetChildren())
			child.QueueFree();
	}

	public void ShowMyAudioMeter(AudioStreamInfo asi)
	{
		myAudioMeter.Visible = true;
		myAudioMeter.ASInfo = asi;
	}

	public bool HasParticipant(string userName)
	{
		return GetListItem(userName) != null;
	}

	public void AddParticipant(string userName)
	{
		// Instantiate CallyListItem and add to dictionary
		Node itemNode = ResourceLoader.Load<PackedScene>("res://scenes/sub/CallListItem.tscn").Instantiate();
		itemNodes.Add(userName, itemNode);

		// Init call list item
		CallListItem item = GetListItem(userName);
		item.userNameLabel.Text = userName;
		item.statusLabel.Text = "Connecting...";

		// Add node to scene
		participantContainer.AddChild(itemNode);
	}

	async public void RemoveParticipant(string userName, string reason)
	{
		CallListItem item = GetListItem(userName);

		if (item != null)
		{
			item.statusLabel.Text = reason;
			item.audioMeter.Visible = false;

			// Wait 2 seconds then remove
			await Task.Delay(2000);

			participantContainer.RemoveChild(item);

			itemNodes.Remove(userName);
		}
	}

	public void UpdateParticipant(AudioStreamInfo asi)
	{
		CallListItem item = GetListItem(asi.User.Name);

		if (item != null)
		{
			item.statusLabel.Text = "";
			item.audioMeter.ASInfo = asi;
			item.audioMeter.Visible = true;
		}
	}

    public void OnStopCallButtonPressed()
	{
		stopCallAction?.Invoke();
    }

    public void OnMuteToggleChange(bool isToggled)
	{
		muteAction?.Invoke(isToggled);
    }

	private CallListItem GetListItem(string userName)
    {
        if (itemNodes.TryGetValue(userName, out Node item))
			return item.GetNode<CallListItem>(".");
		else
			return null;
    }
}
