using System;
using System.Collections.Generic;
using System.Linq;

using Svelto.ECS;
using Svelto.ECS.Serialization;

using GamecraftModdingAPI.Utility;

namespace GamecraftModdingAPI.Persistence
{
    /// <summary>
    /// Keeps track of serializers.
	/// This is used to add and retrieve serializers.
	/// Added IEntitySerializations are used in serializing and deserializing Gamecraft save files (GameSave.GC).
    /// </summary>
    public static class SerializerManager
    {
		private static Dictionary<string, IEntitySerializer> _serializers = new Dictionary<string, IEntitySerializer>();

		private static Dictionary<string, Action<IEntitySerialization>> _registrations = new Dictionary<string, Action<IEntitySerialization>>();

		private static EnginesRoot _lastEnginesRoot;

		public static void AddSerializer<T>(IEntitySerializer serializer) where T : ISerializableEntityDescriptor, new()
		{
			string name = typeof(T).FullName;
			_serializers[name] = serializer;
			_registrations[name] = (IEntitySerialization ies) => { ies.RegisterSerializationFactory<T>(serializer); };
			if (_lastEnginesRoot != null)
			{
				serializer.EntityFactory = _lastEnginesRoot.GenerateEntityFactory();
				_registrations[name].Invoke(_lastEnginesRoot.GenerateEntitySerializer());
				_lastEnginesRoot.AddEngine(serializer);
			}
		}

        public static bool ExistsSerializer(string name)
		{
			return _serializers.ContainsKey(name);
		}

		public static bool ExistsSerializer<T>(IEntitySerializer serializer) where T : ISerializableEntityDescriptor, new()
        {
			return ExistsSerializer(typeof(T).FullName);
        }

		public static IEntitySerializer GetSerializer(string name)
		{
			return _serializers[name];
		}

		public static string[] GetSerializerNames()
        {
            return _serializers.Keys.ToArray();
        }

        public static int GetSerializersCount()
		{
			return _serializers.Count;
		}

		public static void RegisterSerializers(EnginesRoot enginesRoot)
		{
			_lastEnginesRoot = enginesRoot;
			IEntityFactory factory = enginesRoot.GenerateEntityFactory();
			IEntitySerialization ies = enginesRoot.GenerateEntitySerializer();
			foreach (string key in _serializers.Keys)
			{
				Logging.MetaDebugLog($"Registering IEntitySerializer for {key}");
				_serializers[key].EntityFactory = factory;
				_registrations[key].Invoke(ies);
				enginesRoot.AddEngine(_serializers[key]);
			}
		}
    }
}