Editor/ChitChat/TemplateWindow.cs
using Sandbox;
using Editor;

namespace ChitChat.Editor;

public class TemplateWindow : Widget
{
	public static SpeakAction s_SpeakActionTemplate { get; set; } = new();
	public static EventAction s_EventActionTemplate { get; set; } = new();
	public static ChoiceAction s_ChoiceActionTemplate { get; set; } = new();

	private const string CHITCHAT_DIRECTORY_NAME = "ChitChat";

	private const string SPEAK_ACTION_FILE = "TemplateSpeakAction.json";
	private const string EVENT_ACTION_FILE = "TemplateEventAction.json";
	private const string CHOICE_ACTION_FILE = "TemplateChoiceAction.json";

	private const string SPEAK_ACTION = "Speak Action";
	private const string EVENT_ACTION = "Event Action";
	private const string CHOICE_ACTION = "Choice Action";

	private readonly Layout _content;
	
	private SpeakActionInspectorWidget _speakTemplate;
	private EventActionInspectorWidget _eventTemplate;
	private ChoiceActionInspectorWidget _choiceTemplate;

	private ActionType _selectedActionType = ActionType.Speak;

	public TemplateWindow(Widget parent) : base(parent)
	{
		WindowTitle = "Templates";
		Name = "Template Widget";
		Layout = Layout.Column();
		Size = new Vector2(ChitChatEditorWindow.WINDOW_SIZE_X * 0.5f, ChitChatEditorWindow.WINDOW_SIZE_Y * 0.5f);
		SetWindowIcon("save_as");

		Layout headerContainer = Layout.Add(Layout.Row());

		SegmentedControl segmentControl = new SegmentedControl(this);
		segmentControl.OnSelectedChanged = OnSegmentChanged;

		segmentControl.AddOption(SPEAK_ACTION, "record_voice_over");
		segmentControl.AddOption(EVENT_ACTION, "event");
		segmentControl.AddOption(CHOICE_ACTION, "alt_route");
		headerContainer.Add(segmentControl);

		headerContainer.AddSpacingCell(5);

		IconButton resetButton = new IconButton("refresh", OnResetClicked)
		{
			ToolTip = "Resets all settings for the currently selected action.",
			Background = Theme.Red
		};

		headerContainer.Add(resetButton);
		headerContainer.AddSpacingCell(3);

		//Info about templates
		Label.Header infoTemplateText = new Label.Header("Here you can set the default state of actions, next time when you add an action it will use this template.", this);
		infoTemplateText.Alignment = TextFlag.Center;
		infoTemplateText.ContentMargins += new Sandbox.UI.Margin(0, 0, 0, 0);
		infoTemplateText.SetSizeMode(SizeMode.CanGrow, SizeMode.CanShrink);
		Layout.Add(infoTemplateText);

		ScrollArea area = new ScrollArea(this);
		area.HorizontalScrollbarMode = ScrollbarMode.Off;
		area.Canvas = new Widget(area);
		area.Canvas.Layout = Layout.Column();
		area.SetSizeMode(SizeMode.CanGrow, SizeMode.CanGrow);

		_content = area.Canvas.Layout;
		_content.Alignment = TextFlag.LeftTop;

		Layout.Add(area);

		Load();

		Rebuild();
	}

	public void Clear()
	{
		_content.Clear(true);
	}

	public void Rebuild()
	{
		Clear();
		
		_speakTemplate = new SpeakActionInspectorWidget(s_SpeakActionTemplate.GetSerialized(), this);
		_eventTemplate = new EventActionInspectorWidget(s_EventActionTemplate.GetSerialized(), this);
		_choiceTemplate = new ChoiceActionInspectorWidget(s_ChoiceActionTemplate.GetSerialized(), this);

		ChangeActionSegmentVisability(_selectedActionType);

		_content.Add(_speakTemplate);
		_content.Add(_eventTemplate);
		_content.Add(_choiceTemplate);	
	}

	private void OnSegmentChanged(string name)
	{
		if (name.Equals(SPEAK_ACTION))
		{
			ChangeActionSegmentVisability(ActionType.Speak);
		}
		else if (name.Equals(EVENT_ACTION))
		{
			ChangeActionSegmentVisability(ActionType.Event);
		}
		else if (name.Equals(CHOICE_ACTION))
		{
			ChangeActionSegmentVisability(ActionType.Choice);
		}
	}

	private void OnResetClicked()
	{
		switch ( _selectedActionType )
		{
			case ActionType.Speak:
				s_SpeakActionTemplate = new SpeakAction();
				break;
			case ActionType.Event:
				s_EventActionTemplate = new EventAction();
				break;
			case ActionType.Choice:
				s_ChoiceActionTemplate = new ChoiceAction();
				break;
		}

		Rebuild();
	}

	private void ChangeActionSegmentVisability(ActionType action)
	{
		//Speak
		if(action == ActionType.Speak)
			_speakTemplate.Visible = true;
		else
			_speakTemplate.Visible = false;

		//Event
		if (action == ActionType.Event)
			_eventTemplate.Visible = true;
		else
			_eventTemplate.Visible = false;

		//Choice
		if (action == ActionType.Choice)
			_choiceTemplate.Visible = true;
		else
			_choiceTemplate.Visible = false;

		_selectedActionType = action;
	}

	public override void OnDestroyed()
	{
		Save();
	}

	public void Save()
	{
		if (!global::Editor.FileSystem.ProjectTemporary.DirectoryExists(CHITCHAT_DIRECTORY_NAME))
		{
			global::Editor.FileSystem.ProjectTemporary.CreateDirectory(CHITCHAT_DIRECTORY_NAME);
		}

		global::Editor.FileSystem.ProjectTemporary.WriteJson(CHITCHAT_DIRECTORY_NAME + "/" + SPEAK_ACTION_FILE, s_SpeakActionTemplate);
		global::Editor.FileSystem.ProjectTemporary.WriteJson(CHITCHAT_DIRECTORY_NAME + "/" + EVENT_ACTION_FILE, s_EventActionTemplate);
		global::Editor.FileSystem.ProjectTemporary.WriteJson(CHITCHAT_DIRECTORY_NAME + "/" + CHOICE_ACTION_FILE, s_ChoiceActionTemplate);
	}

	public void Load()
	{
		if (!global::Editor.FileSystem.ProjectTemporary.DirectoryExists(CHITCHAT_DIRECTORY_NAME))
		{
			global::Editor.FileSystem.ProjectTemporary.CreateDirectory(CHITCHAT_DIRECTORY_NAME);

			s_SpeakActionTemplate = new();
			s_EventActionTemplate = new();
			s_ChoiceActionTemplate = new();
		}
		else
		{
			s_SpeakActionTemplate = global::Editor.FileSystem.ProjectTemporary.ReadJsonOrDefault<SpeakAction>(CHITCHAT_DIRECTORY_NAME + "/" + SPEAK_ACTION_FILE);
			s_EventActionTemplate = global::Editor.FileSystem.ProjectTemporary.ReadJsonOrDefault<EventAction>(CHITCHAT_DIRECTORY_NAME + "/" + EVENT_ACTION_FILE);
			s_ChoiceActionTemplate = global::Editor.FileSystem.ProjectTemporary.ReadJsonOrDefault<ChoiceAction>(CHITCHAT_DIRECTORY_NAME + "/" + CHOICE_ACTION_FILE);
		}
	}

	private enum ActionType
	{
		Speak,
		Event,
		Choice
	}

	private class EventActionInspectorWidget : Widget
	{
		public EventActionInspectorWidget(SerializedObject so, Widget parent) : base(parent)
		{
			Name = "EventAction";
			Layout = Layout.Column();

			Layout.Add(new TextSeperatorWidget("Event", 40, this));

			Widget eventContainer = Layout.Add(new Widget(this));
			eventContainer.Layout = Layout.Row();

			Label eventNameLabel = new Label("Event Name")
			{
				ContentMargins = new Sandbox.UI.Margin(0, 0, 5, 0)
			};
			eventContainer.Layout.Add(eventNameLabel);

			if (so.TryGetProperty(nameof(EventAction.EventName), out SerializedProperty eventNameProp))
			{
				StringControlWidget eventTextWidget = new StringControlWidget(eventNameProp);
				eventContainer.Layout.Add(eventTextWidget);
			}
			else
			{
				Log.Error("Could not get " + nameof(EventAction.EventName) + " from serialized object!");
			}

		}
	}
}