using RobocraftX.Common;
using RobocraftX.UECS;
using Svelto.ECS;
using Svelto.ECS.EntityStructs;
using Unity.Transforms;
using Unity.Mathematics;

using GamecraftModdingAPI.Utility;
using GamecraftModdingAPI.Engines;

namespace GamecraftModdingAPI.Blocks
{
    /// <summary>
    /// Engine which executes block movement actions
    /// </summary>
    public class MovementEngine : IApiEngine
    {
        public string Name { get; } = "GamecraftModdingAPIMovementGameEngine";

        public EntitiesDB entitiesDB { set; private get; }

		public bool isRemovable => false;

		public bool IsInGame = false;

        public void Dispose()
        {
            IsInGame = false;
        }

        public void Ready()
        {
            IsInGame = true;
        }

        // implementations for Movement static class

        internal float3 MoveBlock(EGID blockID, BlockEngine.BlockInitData data, float3 vector)
        {
            if (!entitiesDB.Exists<PositionEntityStruct>(blockID))
            {
                if (data.Group == null) return float3.zero;
                var init = new EntityComponentInitializer(blockID, data.Group);
                init.Init(new PositionEntityStruct {position = vector});
                init.Init(new GridRotationStruct {position = vector});
                init.Init(new LocalTransformEntityStruct {position = vector});
                return vector;
            }
            ref PositionEntityStruct posStruct = ref this.entitiesDB.QueryEntity<PositionEntityStruct>(blockID);
            ref GridRotationStruct gridStruct = ref this.entitiesDB.QueryEntity<GridRotationStruct>(blockID);
            ref LocalTransformEntityStruct transStruct = ref this.entitiesDB.QueryEntity<LocalTransformEntityStruct>(blockID);
            ref UECSPhysicsEntityStruct phyStruct = ref this.entitiesDB.QueryEntity<UECSPhysicsEntityStruct>(blockID);
            // main (persistent) position
            posStruct.position = vector;
            // placement grid  position
            gridStruct.position = vector;
            // rendered position
            transStruct.position = vector;
            // collision position
            FullGameFields._physicsWorld.EntityManager.SetComponentData(phyStruct.uecsEntity, new Translation
            {
                Value = posStruct.position
            });
            entitiesDB.QueryEntity<GridConnectionsEntityStruct>(blockID).isProcessed = false;
            return posStruct.position;
        }

        internal float3 GetPosition(EGID blockID, BlockEngine.BlockInitData data)
        {
            if (!entitiesDB.Exists<PositionEntityStruct>(blockID))
            {
                if (data.Group == null) return float3.zero;
                var init = new EntityComponentInitializer(blockID, data.Group);
                return init.Has<PositionEntityStruct>() ? init.Get<PositionEntityStruct>().position : float3.zero;
            }
            ref PositionEntityStruct posStruct = ref this.entitiesDB.QueryEntity<PositionEntityStruct>(blockID);
            return posStruct.position;
        }
    }
}