Editor/ChitChat/DialogueSelector.cs
using Sandbox;
using Editor;
using System;
using System.Linq;

namespace ChitChat.Editor;

public class DialogueSelector : Widget
{
	public Action<SerializedProperty> onDialogueActionSelected;
	public Action onSelectedDialogueRemoved;

	private ScrollArea _dialogueArea;
	private ListControlView _listView;

	private Menu _menu;

	private SerializedObject _serializedObject;
	private SerializedCollection _serializedDialogueDatasArray;
	private int _lastSelectedIndex = -1;

	public DialogueSelector(Widget parent, DialogueData data) : base(parent)
	{
		WindowTitle = "Dialogue Selector";
		Name = "Dialogue Selector";
		Size = new Vector2(ChitChatEditorWindow.WINDOW_SIZE_X * 0.5f, ChitChatEditorWindow.WINDOW_SIZE_Y * 0.5f);
		Layout = Layout.Column();
		SetWindowIcon("list_alt");

		_serializedObject = data.GetSerialized();

		Rebuild();
	}

	public void SetData(DialogueData data) => _serializedObject = data.GetSerialized();

	public void SelectLastest()
	{
		_listView.SelectItem(_lastSelectedIndex);
	}

	//TODO: Use this to see if something changed and update asset
	public override void ChildValuesChanged(Widget source)
	{
		base.ChildValuesChanged(source);
	}

	public void Rebuild()
	{
		//Needs to save last selected index to reload it at that index
		if(_listView.IsValid())
			_lastSelectedIndex = _listView.SelectedIndex;

		Layout.Clear(true);

		SerializedProperty prop = _serializedObject.GetProperty(nameof(DialogueData.DialogueDatas));

		//Scroll area
		_dialogueArea = new ScrollArea(this);
		_dialogueArea.Layout = Layout.Column();
		_dialogueArea.Canvas = new Widget(_dialogueArea);
		_dialogueArea.Canvas.Layout = Layout.Column();
		_dialogueArea.Canvas.Layout.Alignment = TextFlag.LeftTop;
		_dialogueArea.Canvas.Parent.Update();
		
		if (prop.TryGetAsObject(out var obj))
		{
			//Dialogue list
			_serializedDialogueDatasArray = (SerializedCollection)obj;
			_listView = new ListControlView(prop, _serializedDialogueDatasArray, OnCreateUIListItem, false);
			_listView.onItemSelected += OnItemSelected;
			_listView.onItemRemoved += OnItemMovedOrRemoved;
			_listView.onItemMoved += OnItemMovedOrRemoved;
			_listView.onItemRightClicked += CreateDialogueActionMenuWithIndex;
			_dialogueArea.Canvas.Layout.Add(_listView);
		}

		//Add dialogue action button
		Widget addButtonContainer = new Widget(_dialogueArea.Canvas);
		addButtonContainer.Layout = Layout.Row();
		addButtonContainer.Layout.Alignment = TextFlag.Left;
		addButtonContainer.Layout.AddSpacingCell(24);

		IconButton addDialogueActionButton = new IconButton("add", CreateDialogueActionMenu);
		addDialogueActionButton.Background = Theme.ControlBackground;
		addButtonContainer.Layout.Add(addDialogueActionButton);
		_dialogueArea.Canvas.Layout.Add(addButtonContainer);

		_dialogueArea.Canvas.Layout.AddStretchCell();

		Layout.Add(_dialogueArea);
	}

	private ControlWidget OnCreateUIListItem(SerializedProperty prop)
	{
		DialogueActionBase baseAction = prop.GetValue<DialogueActionBase>();

		if (baseAction is SpeakAction)
		{
			return new SpeakActionControlWidget(prop);
		}
		else if (baseAction is EventAction)
		{
			return new EventActionControlWidget(prop);

		}
		else if (baseAction is ChoiceAction)
		{
			return new ChoiceActionControlWidget(prop);
		}

		return ControlWidget.Create(prop);
	}

	private void CreateDialogueActionMenu()
	{
		if(_menu.IsValid())
			return;

		CreateDialogueActionMenuWithIndex(_serializedDialogueDatasArray.Count() - 1);
	}

	private void CreateDialogueActionMenuWithIndex(int index)
	{
		if (_menu.IsValid())
			return;

		_menu = new ContextMenu();
		_menu.AddHeading("Dialogue Actions");
		_menu.AddOption("Speak Action", "record_voice_over", () => _serializedDialogueDatasArray.Add(index + 1, new SpeakAction(TemplateWindow.s_SpeakActionTemplate)));
		_menu.AddSeparator();
		_menu.AddOption("Event Action", "event", () => _serializedDialogueDatasArray.Add(index + 1, new EventAction(TemplateWindow.s_EventActionTemplate)));
		_menu.AddSeparator();
		_menu.AddOption("Choice Action", "alt_route", () => _serializedDialogueDatasArray.Add(index + 1, new ChoiceAction(TemplateWindow.s_ChoiceActionTemplate)));

		_menu.OpenAtCursor(true);
		_menu.MinimumWidth = ScreenRect.Width;
	}

	private void OnItemMovedOrRemoved(int index)
	{
		if(index == _listView.SelectedIndex)
			onSelectedDialogueRemoved?.Invoke();
	}

	private void OnItemSelected(SerializedProperty prop)
	{
		onDialogueActionSelected?.Invoke(prop);
	}
}