UI/ChatBox.razor
@using Sandbox;
@using Sandbox.UI;
@using System;
@using TikTokTTS;
@attribute [Icon("chat")]
@implements Component.INetworkListener
@inherits PanelComponent

<root>
	<label style="font-weight: 700">Voice: @Player.Local?.Speech.VoiceName</label>
	<label>Q/R to go Forward/Backward</label>
	<TextEntry @ref="InputBox" class="chat-box" @onsubmit=@ChatFinished/>
</root>

@code
{
	public TextEntry InputBox { get; set; }
	private TimeSince TimeSinceChatted { get; set; } = 0;


	protected override void OnUpdate()
	{
		base.OnUpdate();

		if (InputBox is null)
			return;
		
		if (!Player.Local.IsValid())
			return;

		if (string.IsNullOrEmpty(InputBox.Text))
		{
			InputBox.Placeholder = "Press enter to chat";
		} else if (TimeSinceChatted <= 4 && string.IsNullOrEmpty(InputBox.Text))
		{
			InputBox.Placeholder = $"Please wait {TimeSinceChatted.Relative.CeilToInt()} seconds";
		}


		if (Input.Pressed("chat"))
		{
			InputBox.Focus();
		}

		if (Input.Pressed("Menu"))
		{
			CycleVoice(-1);
		}
		if (Input.Pressed("Reload"))
		{
			CycleVoice(1);
		}
	}

	private void CycleVoice(int offset)
	{
		TikTokSpeech speech = Player.Local?.Speech;
		if (!speech.IsValid())
			return;

		TikTokVoice[] tikTokVoices = Enum.GetValues<TikTokVoice>();
		int currentIndex = Array.IndexOf(tikTokVoices, speech.Voice);
		int nextIndex = (currentIndex + offset + tikTokVoices.Length) % tikTokVoices.Length;

		speech.Voice = tikTokVoices[nextIndex];
	}

	private void ChatFinished()
	{
		string text = InputBox.Text.Trim();
		InputBox.Text = "";

		if (string.IsNullOrWhiteSpace(text)) return;

		Player.Local?.Speech.Speak(text.Normalize(), Player.Local?.Speech?.VoiceName);
	}



	/// <summary>
	/// the hash determines if the system should be rebuilt. If it changes, it will be rebuilt
	/// </summary>
	protected override int BuildHash() => System.HashCode.Combine(Time.Now);
}