#if UNITY_EDITOR
namespace Eden.Core
{
    using System;
    using System.IO;
    using System.Reflection;
    using UnityEditor;
	using UnityEngine;

	public static class ScriptableObjectInstantiator
	{
		private static double _renameTime = 0;
		private static ScriptableObject _pendingForRename = null;

		public static T Create<T>() where T : ScriptableObject
		{
			T asset = ScriptableObject.CreateInstance<T>();

			FinalizeCreation(asset);

			return asset;
		}

		public static ScriptableObject Create(Type type)
		{
			ScriptableObject asset = ScriptableObject.CreateInstance(type);

			FinalizeCreation(asset);

			return asset;
		}

		private static void FinalizeCreation(ScriptableObject createdScriptableObject)
		{
			string folder = GetSelectedFolder();
			string assetPathAndName = AssetDatabase.GenerateUniqueAssetPath(Path.Combine(folder, createdScriptableObject.GetType().Name + ".asset"));

			AssetDatabase.CreateAsset(createdScriptableObject, assetPathAndName);

			AssetDatabase.SaveAssets();
			AssetDatabase.Refresh();

			FocusAndToggleRename(createdScriptableObject);
		}

		/// <summary>
		/// This method will trigger a focus on the given ScriptableObject. After a short delay, it will go into rename mode, where the user can rename if wanted.
		/// This is the same behavior than when creating any built-in asset.
		/// </summary>
		/// <param name="scriptableObject">ScriptableObject that we want to focus and enable renaming on.</param>
		private static void FocusAndToggleRename(ScriptableObject scriptableObject)
		{
			// Focus that item right away
			Selection.activeObject = scriptableObject;

			EditorApplication.update -= WaitForRename;

			// Account for creation delay, 0.2s should be enough
			_renameTime = EditorApplication.timeSinceStartup + 0.2d;
			_pendingForRename = scriptableObject;

			EditorApplication.update += WaitForRename;
		}

		private static void WaitForRename()
		{
			if (EditorApplication.timeSinceStartup >= _renameTime)
			{
				EditorApplication.update -= WaitForRename;

				if (Selection.activeObject == _pendingForRename)
				{
					// Simulate rename event (as if the user entered a shortcut)
					EditorWindow.focusedWindow.SendEvent(new Event() { keyCode = KeyCode.F2, type = EventType.KeyDown });
				}

				_pendingForRename = null;
			}
		}

		private static string GetSelectedFolder()
		{
			UnityEngine.Object selection = EditorWindow.focusedWindow;
			if (selection != null)
			{
				BindingFlags flags = BindingFlags.NonPublic | BindingFlags.Instance;
				FieldInfo field = selection.GetType().GetField("m_SelectedPath", flags);
				if (field == null)
				{
					return "";
				}
				return (field.GetValue(selection) as string) + "/";
			}
			return "";
		}
	}
}
#endif // UNITY_EDITOR