using Common;
using RpcComponents;
using Unity.Burst;
using Unity.Collections;
using Unity.Entities;
using Unity.Mathematics;
using Unity.NetCode;
using Unity.Rendering;
using Unity.Transforms;
using UnityEngine;

namespace Server
{
    [WorldSystemFilter(WorldSystemFilterFlags.ServerSimulation)]
    public partial struct ServerProcessGameEntryRequestSystem : ISystem
    {
        [BurstCompile]
        public void OnCreate(ref SystemState state)
        {
            state.RequireForUpdate<TdPrefabs>();
            var builder = new EntityQueryBuilder(Allocator.Temp).WithAll<TdTeamRequest, ReceiveRpcCommandRequest>();
            state.RequireForUpdate(state.GetEntityQuery(builder));
        }

        
        [BurstCompile]
        public void OnUpdate(ref SystemState state)
        {
            // var ecb                   = new EntityCommandBuffer(Allocator.Temp);

            var ecb = SystemAPI.GetSingletonRW<EndSimulationEntityCommandBufferSystem.Singleton>().ValueRW
                .CreateCommandBuffer(state.WorldUnmanaged);
            
            var tdPrefabs             = SystemAPI.GetSingleton<TdPrefabs>();  
            
            foreach (var (teamRequest, requestSource, requestEntity) in SystemAPI.Query<TdTeamRequest, ReceiveRpcCommandRequest>().WithEntityAccess())
            {
                
                var requestedTeam  = teamRequest.Value;
                var requestedColor = teamRequest.Color;
                
                    
                float3 spawnPosition = float3.zero;
                
                var clientId    = SystemAPI.GetComponent<NetworkId>(requestSource.SourceConnection).Value;
                switch (clientId)
                {
                    case 1:
                        spawnPosition     = new float3(0f, 1f, 0f);
                        break;
                    case 2:
                        spawnPosition     = new float3(2f, 1f, 0f);
                        break;
                }

                
                //instantiate prefab
                
                var characterEntity = ecb.Instantiate(tdPrefabs.Character);
                var playerEntity = ecb.Instantiate(tdPrefabs.FPSPlayer);

                //Destroy character prefab, when client disconnects
                ecb.AppendToBuffer(requestSource.SourceConnection, new LinkedEntityGroup{Value = characterEntity});
                ecb.AppendToBuffer(requestSource.SourceConnection, new LinkedEntityGroup{Value = playerEntity});
                
                //Setup ghost owner
                ecb.SetComponent(characterEntity, new GhostOwner { NetworkId = clientId});
                ecb.SetComponent(playerEntity, new GhostOwner { NetworkId = clientId});
                

                ecb.SetName(characterEntity, "Character");
                
                //Set position
                var newTransform      = LocalTransform.FromPosition(spawnPosition);
                ecb.SetComponent(characterEntity, newTransform);
                
                
                //Set config and Team
                ecb.SetComponent(characterEntity, new TdTeam     { Value = requestedTeam });
                
                ecb.SetComponent(characterEntity, new CharacterConfig
                    {
                        Color = requestedColor
                    });

                //Setup connection
                FirstPersonPlayer playerComponent = SystemAPI.GetComponent<FirstPersonPlayer>(tdPrefabs.FPSPlayer);
                playerComponent.ControlledCharacter = characterEntity;
                ecb.SetComponent(playerEntity, playerComponent);
                
                //sync server connection entity with client connection entity
                ecb.AddComponent<NetworkStreamInGame>(requestSource.SourceConnection);
                
                //destroy request entity that only holds request
                ecb.DestroyEntity(requestEntity);
            }
        }
    }
}