using System;

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

using RobocraftX.Common;

namespace GamecraftModdingAPI.Persistence
{
    /// <summary>
    /// Simple entity serializer sufficient for simple entity components.
    /// </summary>
	public class SimpleEntitySerializer<Descriptor> : IEntitySerializer where Descriptor : ISerializableEntityDescriptor, new()
	{
        /// <summary>
        /// Delegate function called when the serializer needs to know what entities to serialize.
        /// </summary>
		public delegate EGID[] GetEntitiesToSerialize(EntitiesDB entitiesDB);

		private GetEntitiesToSerialize getEntitiesToSerialize;

		protected int serializationType;

		public IEntityFactory EntityFactory { set; protected get; }

		public EntitiesDB entitiesDB { set; protected get; }

		public EntityComponentInitializer BuildDeserializedEntity(EGID egid, ISerializationData serializationData, ISerializableEntityDescriptor entityDescriptor, int serializationType, IEntitySerialization entitySerialization)
		{
			EntityComponentInitializer esi = EntityFactory.BuildEntity<Descriptor>(egid);
            entitySerialization.DeserializeEntityComponents(serializationData, entityDescriptor, ref esi, serializationType);
			return esi;
		}

		public bool Deserialize(ref ISerializationData serializationData, IEntitySerialization entitySerializer)
		{
			BinaryBufferReader bbr = new BinaryBufferReader(serializationData.data.ToArrayFast(out uint count), serializationData.dataPos);
			uint entityCount = bbr.ReadUint();
			serializationData.dataPos = bbr.Position;
			for (uint i = 0; i < entityCount; i++)
            {
				entitySerializer.DeserializeEntity(serializationData, serializationType);
            }
			return true;
		}

		public void Ready() { }

		public bool Serialize(ref ISerializationData serializationData, EntitiesDB entitiesDB, IEntitySerialization entitySerializer)
		{
			serializationData.data.ExpandBy(4u);
			BinaryBufferWriter bbw = new BinaryBufferWriter(serializationData.data.ToArrayFast(out uint count), serializationData.dataPos);
			EGID[] toSerialize = getEntitiesToSerialize(entitiesDB);
			bbw.Write((uint)toSerialize.Length);
			serializationData.dataPos = bbw.Position;
			for (uint i = 0; i < toSerialize.Length; i++)
			{
				entitySerializer.SerializeEntity(toSerialize[i], serializationData, serializationType);
			}
			return true;
		}

        /// <summary>
        /// Construct the entity serializer.
        /// </summary>
        /// <param name="getEntitiesToSerialize">Provider of entity IDs to serialize.</param>
		public SimpleEntitySerializer(GetEntitiesToSerialize getEntitiesToSerialize)
		{
			this.getEntitiesToSerialize = getEntitiesToSerialize;
			serializationType = (int)SerializationType.Storage;
		}
	}
}