using System.Collections.Generic;
using System.Linq;
using Intrepid.Core.Tags;
using Intrepid.TagSystem;
using Intrepid.Utilities;
using Intrepid.Utilities.Updatable;
using Sirenix.OdinInspector;
using UnityEngine;

namespace Intrepid.Core.Entities
{
    public abstract class Entity : AbstractTagBehaviour<PhysicsTag>, IUpdatable
    {
        [GroupInjections, SerializeField] private EntityBrain brain;
        [GroupInjections, SerializeField] private EntitySensor entitySensor;
        [GroupIdentification, ReadOnly, SerializeField] private string id = Functions.GenerateUuid();

        public string Id => id;

        [GroupIdentification, Button(ButtonStyle.FoldoutButton, Icon = SdfIconType.Send)]
        public void SetId(string myId)
        {
            id = myId;
        }

        [GroupIdentification, Button(ButtonStyle.FoldoutButton, Icon = SdfIconType.Rainbow)]
        public void GenerateRandomId()
        {
            id = Functions.GenerateUuid();
        }
        
        protected EntityBrain EntityBrain => brain;
        
        public EntitySensor EntitySensor => entitySensor;
        
        protected void OnEnable()
        {
            UpdatableCollection.Instance.Add(this);
        }
        
        protected void OnDisable()
        {
            UpdatableCollection.Instance?.Remove(Id);
        }
        

        public virtual void UpdateFromUpdatable()
        {
            EntityBrain.UpdateFromUpdatable();
        }

        public virtual void LateUpdateFromUpdatable()
        {
            EntityBrain.LateUpdateFromUpdatable();
        }

        public virtual void FixedUpdateFromUpdatable()
        {
            EntityBrain.FixedUpdateFromUpdatable();
        }

        public bool ShouldBeTriggered(IEnumerable<EntityTag> entity, IEnumerable<PhysicsTag> physicsTags)
        {
            return entity.Contains(EntitySensor.EntityTag) && HasAnyTags(physicsTags);
        }

        public bool ShouldNotBeTriggered(IEnumerable<EntityTag> entities, IEnumerable<PhysicsTag> physicsTags)
        {
            return !ShouldBeTriggered(entities, physicsTags);
        }
        
        public abstract void DeployEntity(Vector3 position, Vector2 direction);
        public abstract void RetreatEntity();
    }
}