using System;
using System.Reflection;

using RobocraftX.Common;
using Svelto.ECS;
using Svelto.ECS.Serialization;

using GamecraftModdingAPI.Persistence;
using GamecraftModdingAPI.Events;

namespace GamecraftModdingAPI.Utility
{
    /// <summary>
    /// Tracks the API version the current game was built for.
	/// For compatibility reasons, this must be enabled before it will work.
    /// </summary>
	public static class VersionTracking
	{
		private static readonly VersionTrackingEngine versionEngine = new VersionTrackingEngine();

		private static bool isEnabled = false;

        /// <summary>
        /// Gets the API version saved in the current game.
        /// </summary>
        /// <returns>The version.</returns>
        public static uint GetVersion()
		{
			if (!isEnabled) return 0u;
			return versionEngine.GetGameVersion();
		}

        /// <summary>
        /// Enable API version tracking.
        /// </summary>
        public static void Enable()
		{
			EventManager.AddEventEmitter(versionEngine);
			isEnabled = true;
		}

        /// <summary>
		/// Disable API version tracking.
        /// </summary>
        public static void Disable()
		{
			EventManager.AddEventEmitter(versionEngine);
			isEnabled = false;
		}

        public static void Init()
		{
			SerializerManager.AddSerializer<ModVersionDescriptor>(new SimpleEntitySerializer<ModVersionDescriptor>(
				(_) => { return new EGID[1] { new EGID(0u, ApiExclusiveGroups.versionGroup) }; }
			));
		}
	}

	internal class VersionTrackingEngine : IEventEmitterEngine
	{
		public string Name { get; } = "GamecraftModdingAPIVersionTrackingGameEngine";

		public EntitiesDB entitiesDB { set; private get; }

		public int type => -1;

		public bool isRemovable => false;

		public IEntityFactory Factory { set; private get; }

		public void Dispose() { }

		public void Ready()
		{
			EGID egid = new EGID(0u, ApiExclusiveGroups.versionGroup);
			if (!entitiesDB.Exists<ModVersionStruct>(egid))
			{
				Version currentVersion = Assembly.GetExecutingAssembly().GetName().Version;
				int v = (currentVersion.Major * 1000) + (currentVersion.Minor);
				Factory.BuildEntity<ModVersionDescriptor>(egid).Init<ModVersionStruct>(new ModVersionStruct
				{
					version = (uint)v
				});
			}
		}

        public uint GetGameVersion()
		{
			return entitiesDB.QueryUniqueEntity<ModVersionStruct>(ApiExclusiveGroups.versionGroup).version;
		}

		public void Emit() { }
	}

	public struct ModVersionStruct : IEntityComponent
	{
		public uint version;
	}

	public class ModVersionDescriptor: SerializableEntityDescriptor<ModVersionDescriptor._ModVersionDescriptor>
	{
		[HashName("GamecraftModdingAPIVersionV0")]
		public class _ModVersionDescriptor : IEntityDescriptor
		{
			public IComponentBuilder[] componentsToBuild { get; } = new IComponentBuilder[]{
				new SerializableComponentBuilder<SerializationType, ModVersionStruct>(((int)SerializationType.Network, new DefaultSerializer<ModVersionStruct>()), ((int)SerializationType.Storage, new DefaultSerializer<ModVersionStruct>())),
			};
		}
	}
}