﻿#if UNITY_EDITOR

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

namespace AC.Downloads.ShopSystem
{

	public class ShopSystemTemplate : Template
	{

		#region Variables

		[SerializeField] private Texture2D coinsTexture = null;
		[SerializeField] private Container shopPrefab = null;
		[SerializeField] private MenuManager defaultMenuManager = null;
		[SerializeField] private Texture2D containerIcon = null;

		#endregion


		#region PublicFunctions

		public override bool CanInstall (ref string errorText)
		{
			if (KickStarter.sceneManager == null)
			{
				errorText = "No Scene Manager assigned";
				return false;
			}
			
			if (KickStarter.inventoryManager == null)
			{
				errorText = "No Inventory Manager assigned";
				return false;
			}

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

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

			if (shopPrefab == null)
			{
				errorText = "No shop prefab assigned";
				return false;
			}

			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.cursorManager, KickStarter.menuManager, KickStarter.speechManager }, "");
			
			// Inventory
			int tradeableCategoryID = GetOrCreateItemCategory ("Tradeable").id;
			int nonTradeableCategoryID = GetOrCreateItemCategory ("Non-tradeable").id;
			InvVar costProperty = GetOrCreateItemProperty ("Cost", VariableType.Integer);
			costProperty.limitToCategories = true;
			costProperty.categoryIDs = new List<int> () { tradeableCategoryID };
			InvItem coinsItem = GetOrCreateItem ("Coins", coinsTexture);
			coinsItem.binID = nonTradeableCategoryID;
			EditorUtility.SetDirty (KickStarter.inventoryManager);

			// Variables
			int playerMoneyVarID = GetOrCreateGlobalVariable ("Shop/Player money", VariableType.Integer).id;
			int totalCostVarID = GetOrCreateGlobalVariable ("Shop/Total cost", VariableType.Integer).id;

			// Prefab
			Container newShopPrefab = CopyAsset<Container> (installPath, shopPrefab, ".prefab");
			if (newShopPrefab == null)
			{
				onFail.Invoke ("Prefab copy failed.");
				return;
			}
			newShopPrefab.limitToCategory = true;
			newShopPrefab.categoryIDs.Clear ();
			newShopPrefab.categoryIDs.Add (tradeableCategoryID);
			EditorUtility.SetDirty (newShopPrefab);

			// Scene
			KickStarter.sceneManager.AddPrefab (new SceneManagerPrefabData ("Logic", "Shop", "A Container with items that the Player can trade for.", containerIcon, newShopPrefab.gameObject));
			
			// ActionLists
			CreateActionList ("ShopBuy", "BeginBuying", installPath);
			CreateActionList ("ShopSell", "BeginSelling", installPath);

			// Menu
			CopyMenus (installPath, defaultMenuManager, KickStarter.menuManager);
			MenuElement element = MenuManager.GetElementWithName ("ShopBuy", "PlayerMoney");
			if (element != null && element is MenuLabel) (element as MenuLabel).label = "Coins: [var:" + playerMoneyVarID.ToString () + "]g";
			else { onFail.Invoke ("Menu update failed."); return; }

			element = MenuManager.GetElementWithName ("ShopBuy", "TotalCost");
			if (element != null && element is MenuLabel) (element as MenuLabel).label = "Total cost: [var:" + totalCostVarID.ToString () + "]g";
			else { onFail.Invoke ("Menu update failed."); return; }

			element = MenuManager.GetElementWithName ("ShopSell", "PlayerItems");
			if (element != null && element is MenuInventoryBox) (element as MenuInventoryBox).categoryIDs = new List<int> () { tradeableCategoryID };
			else { onFail.Invoke ("Menu update failed."); return; }

			element = MenuManager.GetElementWithName ("ShopSell", "PlayerMoney");
			if (element != null && element is MenuLabel) (element as MenuLabel).label = "Coins: [var:" + playerMoneyVarID.ToString () + "]g";
			else { onFail.Invoke ("Menu update failed."); return; }

			element = MenuManager.GetElementWithName ("ShopSell", "TotalValue");
			if (element != null && element is MenuLabel) (element as MenuLabel).label = "Total value: [var:" + totalCostVarID.ToString () + "]g";
			else { onFail.Invoke ("Menu update failed."); return; }

			EditorUtility.SetDirty (KickStarter.menuManager);

			onComplete.Invoke ();
		}

		#endregion


		#region PrivateFunctions
		
		private ActionListAsset CreateActionList (string menuName, string assetName, string installPath)
		{
			ActionContainerOpen containerOpen = ActionContainerOpen.CreateNew (null);
			containerOpen.setElement = true;
			containerOpen.menuName = menuName;
			containerOpen.containerElementName = "ShopItems";

			List<Action> actions = new List<Action>
			{
				containerOpen,
				ActionMenuState.CreateNew_TurnOnMenu (menuName, false),
			};

			ActionListAsset newAsset = ActionListAsset.CreateFromActions (assetName, installPath, actions, ActionListType.RunInBackground);
			newAsset.useParameters = true;
			ActionParameter newParameter = newAsset.CreateNewParameter ();
			newParameter.label = "Shop";
			newParameter.parameterType = ParameterType.GameObject;

			containerOpen.parameterID = newParameter.ID;

			EditorUtility.SetDirty (newAsset);

			return newAsset;
		}

		#endregion



		#region GetSet

		public override string Label { get { return "Shop system"; }}
		public override string PreviewText { get { return "Adds the means to trade inventory items with shopkeepers in exchange for money."; }}
		public override Type[] AffectedManagerTypes { get { return new Type[] { typeof (SceneManager), typeof (InventoryManager), typeof (MenuManager), typeof (VariablesManager) }; }}
		public override bool RequiresInstallPath { get { return true; }}
		public override string FolderName { get { return "ShopSystem"; }}

		#endregion

	}


	[CustomEditor (typeof (ShopSystemTemplate))]
	public class ShopSystemTemplateEditor : TemplateEditor
	{}

}

#endif