ChitChat/Components/DialoguePanelComponent.cs
using Sandbox;
using Sandbox.UI;
using System;
using System.Collections.Generic;
using System.Runtime.CompilerServices;

namespace ChitChat;

[Title("Dialogue Panel")]
public class DialoguePanelComponent : PanelComponent
{
	[Property][Description("Use a predefined dialogue UI.")]
	public DialogueUIOptions UIOptions 
	{ 
		get => _uiOptions;
		set
		{
			_uiOptions = value;
			
			if(value != DialogueUIOptions.Custom)
				PanelType = null;
		}
	}

	[ShowIf(nameof(UIOptions), DialogueUIOptions.Custom)]
	[Property][TargetType(typeof(DialoguePanelBase))]
	[Description("If you want to use custom dialogue UI then set this to the one you want use. UI needs to inherit from " + nameof(DialoguePanelBase) + " to show up.")] 
	public Type PanelType { get; set; }

	[ShowIf(nameof(UIOptions), DialogueUIOptions.Custom)][Property]
	public bool CreatePanelOnStart { get; set; } = true;

	public DialoguePanelBase DialoguePanel { get; private set; }

	private DialogueUIOptions _uiOptions = DialogueUIOptions.Simple;
	private bool _isSetup = false;

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

		if(CreatePanelOnStart && UIOptions == DialogueUIOptions.Custom)
			SetDialoguePanelType();
	}

	///<summary>Creates a panel using the already defined panel type from <see cref="DialoguePanelComponent.DialoguePanel"/> property.</summary>
	public void SetDialoguePanelType()
	{
		if (PanelType == null)
		{
			Log.Error("Couldn't create dialogue panel because the type was null!");
			return;
		}

		if (PanelType.IsAbstract)
		{
			Log.Error(PanelType.Name + " is abstract!");
			return;
		}

		DialoguePanel = (DialoguePanelBase)TypeLibrary.Create(PanelType.FullName, PanelType);

		CheckForOldPanel();
	}

	///<summary>Creates a panel of type T.</summary>
	public void SetDialoguePanelType<T>() where T : DialoguePanelBase, new()
	{
		DialoguePanel = new T();

		CheckForOldPanel();
	}

	private void CheckForOldPanel()
	{
		//When chaning panel, delete old panel. 
		if (Panel.IsValid() && Panel.ChildrenCount > 0)
		{
			Panel.GetChild(0).Delete();
			_isSetup = false;
		}
	}

	public void SetupDialogue()
	{
		if(_isSetup)
			return;
		
		_isSetup = true;
		if (DialoguePanel == null)
		{
			switch(UIOptions)
			{
				case DialogueUIOptions.Simple:
					DialoguePanel = new DefaultDialoguePanel();
					break;
			}
		}

		if(DialoguePanel != null)
			Panel.AddChild(DialoguePanel);
		else
			Log.Error("No Dialogue panel set.");
	}

	public void Activate() 
	{
		Enabled = true;
		SetupDialogue();
	}

	public void Deactivate() 
	{
		Enabled = false;
		_isSetup = false;
	}

	[MethodImpl(MethodImplOptions.AggressiveInlining)]
	public void SetText(string text) => DialoguePanel.OnText(text);

	[MethodImpl(MethodImplOptions.AggressiveInlining)]
	public void SetCharacterPicture(Texture tex, PicturePosition position) => DialoguePanel.OnCharacterPicture(tex, position);
	
	[MethodImpl(MethodImplOptions.AggressiveInlining)]
	public void SetCharacterName(string name) => DialoguePanel.OnCharacterName(name);

	[MethodImpl(MethodImplOptions.AggressiveInlining)]
	public void SetChoices(List<Choice> choices) => DialoguePanel.OnChoices(choices);
}

public enum DialogueUIOptions
{
	Custom,
	Simple,
}