﻿#if UNITY_EDITOR

using System;
using System.Collections.Generic;
using UnityEngine;
using UnityEditor;

namespace AC.Downloads.SaveGameRetro
{

	public class SaveGameRetroTemplate : Template
	{

		#region Variables

		[SerializeField] private MenuManager menuManager = null;

		#endregion


		#region PublicFunctions

		public override bool CanInstall (ref string errorText)
		{
			if (KickStarter.settingsManager == null)
			{
				errorText = "No Settings Manager assigned";
				return false;
			}

			if (KickStarter.variablesManager == null)
			{
				errorText = "No Variables Manager assigned";
				return false;
			}

			if (menuManager == null || KickStarter.menuManager == null)
			{
				errorText = "No Menu Manager assigned";
				return false;
			}

			if (KickStarter.menuManager == menuManager)
			{
				errorText = "Wrong Menu Manager assigned";
				return false;
			}

			return true;
		}


		public override bool CanSuggest (NGWData data)
		{
			return true;
		}

		#endregion


		#region ProtectedFunctions

		protected override void MakeChanges (string installPath, bool canDeleteOldAssets, System.Action onComplete, System.Action<string> onFail)
		{
			Undo.RecordObjects (new UnityEngine.Object[] { KickStarter.settingsManager, KickStarter.variablesManager, KickStarter.sceneManager, KickStarter.menuManager }, "");

			// Settings
			KickStarter.settingsManager.saveScreenshots = SaveScreenshots.Never;
			KickStarter.settingsManager.maxSaves = 15;
			EditorUtility.SetDirty (KickStarter.settingsManager);

			// Variables
			GVar editingIndexVar = GetOrCreateGlobalVariable ("Save game retro/Editing save index", VariableType.Integer);
			GVar saveNameVar = GetOrCreateGlobalVariable ("Save game retro/Save name", VariableType.String);

			// Menu
			CopyMenus (installPath, menuManager, KickStarter.menuManager, canDeleteOldAssets ? ExistingMenuBehaviour.Delete : ExistingMenuBehaviour.Rename);
			Menu loadMenu = KickStarter.menuManager.GetMenuWithName ("Load");
			if (loadMenu == null)
			{
				onFail.Invoke ("No Load menu");
				return;
			}
			
			ActionListAsset loadTurnOnActionList = CreateLoadTurnOnActionList ("RetroSaves_Load_TurnOn", installPath);
			loadMenu.actionListOnTurnOn = loadTurnOnActionList;

			ActionListAsset loadClickSavesActionList = CreateLoadClickSavesActionList ("RetroSaves_Load_SaveList_OnClick", installPath, editingIndexVar.id);
			MenuElement element = MenuManager.GetElementWithName ("Load", "SaveList");
			if (element != null && element is MenuSavesList) (element as MenuSavesList).actionListOnSave = loadClickSavesActionList;
			else { onFail.Invoke ("Menu update failed."); return; }

			ActionListAsset loadClickLoadActionList = CreateLoadClickLoadActionList ("RetroSaves_Load_LoadButton_OnClick", installPath, editingIndexVar.id);
			element = MenuManager.GetElementWithName ("Load", "LoadButton");
			if (element != null && element is MenuButton) (element as MenuButton).actionList = loadClickLoadActionList;
			else { onFail.Invoke ("Menu update failed."); return; }

			Menu saveMenu = KickStarter.menuManager.GetMenuWithName ("Save");
			if (saveMenu == null)
			{
				onFail.Invoke ("No Save menu");
				return;
			}

			ActionListAsset saveTurnOnActionList = CreateSaveTurnOnActionList ("RetroSaves_Save_TurnOn", installPath);
			saveMenu.actionListOnTurnOn = saveTurnOnActionList;

			ActionListAsset saveClickSavesActionList = CreateSaveClickSavesActionList ("RetroSaves_Save_SaveList_OnClick", installPath, editingIndexVar.id, saveNameVar.id);
			element = MenuManager.GetElementWithName ("Save", "SaveList");
			if (element != null && element is MenuSavesList) (element as MenuSavesList).actionListOnSave = saveClickSavesActionList;
			else { onFail.Invoke ("Menu update failed."); return; }

			ActionListAsset saveClickSaveActionList = CreateSaveClickSaveActionList ("RetroSaves_Save_SaveButton_OnClick", installPath, editingIndexVar.id, saveNameVar.id);
			element = MenuManager.GetElementWithName ("Save", "SaveButton");
			if (element != null && element is MenuButton) (element as MenuButton).actionList = saveClickSaveActionList;
			else { onFail.Invoke ("Menu update failed."); return; }

			EditorUtility.SetDirty (KickStarter.menuManager);

			onComplete.Invoke ();
		}

		#endregion


		#region PrivateFunctions
		
		private ActionListAsset CreateLoadTurnOnActionList (string assetName, string installPath)
		{
			List<Action> actions = new List<Action>
			{
				ActionMenuState.CreateNew_SetElementVisibility ("Load", "LoadButton", false),
			};

			ActionListAsset newAsset = ActionListAsset.CreateFromActions (assetName, installPath, actions, ActionListType.RunInBackground);
			return newAsset;
		}


		private ActionListAsset CreateLoadClickSavesActionList (string assetName, string installPath, int variableID)
		{
			ActionVarSet varSet = ActionVarSet.CreateNew_Global (variableID, 0);

			List<Action> actions = new List<Action>
			{
				varSet,
				ActionMenuState.CreateNew_SetElementVisibility ("Load", "LoadButton", true),
			};

			ActionListAsset newAsset = ActionListAsset.CreateFromActions (assetName, installPath, actions, ActionListType.RunInBackground);

			newAsset.useParameters = true;
			ActionParameter newParameter = newAsset.CreateNewParameter ();
			newParameter.label = "Save index";
			newParameter.parameterType = ParameterType.Integer;

			varSet.setParameterID = newParameter.ID;
			EditorUtility.SetDirty (newAsset);

			return newAsset;
		}


		private ActionListAsset CreateLoadClickLoadActionList (string assetName, string installPath, int variableID)
		{
			ActionSaveHandle saveHandle = ActionSaveHandle.CreateNew_LoadFromSlot ("Load", "SaveList", 0);
			saveHandle.selectSaveType = SelectSaveType.SlotIndexFromVariable;
			saveHandle.slotVarID = variableID;

			List<Action> actions = new List<Action>
			{
				ActionMenuState.CreateNew_TurnOffMenu ("Load"),
				saveHandle,
			};

			ActionListAsset newAsset = ActionListAsset.CreateFromActions (assetName, installPath, actions, ActionListType.RunInBackground);
			return newAsset;
		}


		private ActionListAsset CreateSaveTurnOnActionList (string assetName, string installPath)
		{
			List<Action> actions = new List<Action>
			{
				ActionMenuState.CreateNew_SetElementVisibility ("Save", "Input", false),
				ActionMenuState.CreateNew_SetElementVisibility ("Save", "SaveButton", false),
			};

			ActionListAsset newAsset = ActionListAsset.CreateFromActions (assetName, installPath, actions, ActionListType.RunInBackground);
			return newAsset;
		}


		private ActionListAsset CreateSaveClickSavesActionList (string assetName, string installPath, int editingVarID, int labelVarID)
		{
			ActionVarSet varSet1 = ActionVarSet.CreateNew_Global (editingVarID, 0);
			
			ActionVarSet varSet2 = ActionVarSet.CreateNew_Global (labelVarID, "");
			varSet2.setVarMethodString = SetVarMethodString.SetAsMenuElementText;
			varSet2.menuName = "Save";
			varSet2.elementName = "SaveList";

			List<Action> actions = new List<Action>
			{
				varSet1,
				varSet2,
				ActionMenuSetInputBox.CreateNew_SetFromVariable ("Save", "Input", labelVarID),
				ActionMenuState.CreateNew_SetElementVisibility ("Save", "Input", true),
				ActionMenuState.CreateNew_SetElementVisibility ("Save", "SaveButton", true),
				ActionMenuSelect.CreateNew ("Save", "Input", 0),
			};

			ActionListAsset newAsset = ActionListAsset.CreateFromActions (assetName, installPath, actions, ActionListType.RunInBackground);

			newAsset.useParameters = true;
			ActionParameter newParameter = newAsset.CreateNewParameter ();
			newParameter.label = "Save index";
			newParameter.parameterType = ParameterType.Integer;

			varSet1.setParameterID = newParameter.ID;
			varSet2.slotNumberParameterID = newParameter.ID;

			EditorUtility.SetDirty (newAsset);

			return newAsset;
		}


		private ActionListAsset CreateSaveClickSaveActionList (string assetName, string installPath, int editingVarID, int labelVarID)
		{
			ActionVarSet varSet = ActionVarSet.CreateNew_Global (labelVarID, 0);
			varSet.setVarMethodString = SetVarMethodString.SetAsMenuElementText;
			varSet.menuName = "Save";
			varSet.elementName = "Input";
			varSet.preProcessTokens = true;

			ActionSaveHandle saveHandle = ActionSaveHandle.CreateNew_SaveNew (labelVarID);
			saveHandle.saveHandling = SaveHandling.OverwriteExistingSave;
			saveHandle.selectSaveType = SelectSaveType.SlotIndexFromVariable;
			saveHandle.slotVarID = editingVarID;
			saveHandle.menuName = "Save";
			saveHandle.elementName = "SaveList";
			saveHandle.updateLabel = true;

			List<Action> actions = new List<Action>
			{
				ActionMenuState.CreateNew_TurnOffMenu ("Save"),
				varSet,
				saveHandle,
			};

			ActionListAsset newAsset = ActionListAsset.CreateFromActions (assetName, installPath, actions, ActionListType.RunInBackground);
			return newAsset;
		}


		#endregion


		#region GetSet

		public override string Label { get { return "Save-game retro"; }}
		public override string PreviewText { get { return "Replaces the default Save and Load menus with a classic-styled list of files that can be renamed."; }}
		public override Type[] AffectedManagerTypes { get { return new Type[] { typeof (SettingsManager), typeof (VariablesManager), typeof (MenuManager) }; }}
		public override bool RequiresInstallPath { get { return true; }}
		public override TemplateCategory Category { get { return TemplateCategory.Misc; }}
		public override string FolderName { get { return "SaveGameRetro"; }}

		#endregion

	}


	[CustomEditor (typeof (SaveGameRetroTemplate))]
	public class SaveGameRetroTemplateEditor : TemplateEditor
	{}

}

#endif