using System;
using System.Collections.Generic;
using Sirenix.OdinInspector;
using UnityEngine;
using VOID.Generic.AreaOfEffect;
using VOID.Generic.Projectile.HitValidator;
using VOID.Generic.Projectile.TargetValidator;
using VOID.Generic.Trajectory;
using VOID.ScriptableObjects.Abilities;

namespace VOID.Generic.Projectile
{
    /// <summary>
    /// Defined in <see cref="BasicAbility"/> and used by <see cref="ProjectileObject"/>.
    /// Defines how projectile will move and hit. 
    /// </summary>
    [Serializable]
    public class ProjectileStep
    {
        // Projectile own HitBox and speed
        [MinValue(.1f)] public float radius = .1f;
        [OnValueChanged(nameof(OnValidate)), ShowIf(nameof(ShowSpeed)), MinValue(1f), SuffixLabel("m/s")] public float speed = 10f;
        
        // Variables which enhance projectile movement and trajectory
        [OnValueChanged(nameof(OnValidate)), ShowIf(nameof(ShowHitType)), Required] public ProjectileHitType hitType;
        [OnValueChanged(nameof(OnValidate)), Required] public ProjectileCollisionType collisionType;
        [Required] public ProjectileStepStartFrom startFrom;
        
        // Validating if can be targeted or hit
        [InfoBox("Validates if target can be selected")]
        [SerializeReference, HorizontalGroup("validating")] public List<IProjectileTargetValidator> validTargets = new();
        [InfoBox("Validates if object touched by AOE can be hit")]
        [SerializeReference, HorizontalGroup("validating")] public List<IProjectileHitValidator> validHits = new();
        
        // Generic definition of TRAJECTORY and AOE
        [SerializeReference, Required] public AbstractTrajectory trajectory;
        [SerializeReference, Required] public AbstractAreaOfEffect areaOfEffect;

        private void OnValidate()
        {
            if (!ShowSpeed()) speed = 10f;
            if (!ShowHitType()) hitType = ProjectileHitType.Never;
        }
        
        private bool ShowSpeed() => trajectory is not InstantTrajectory;
        private bool ShowHitType() => areaOfEffect is not NoneAreaOfEffect;
    }
}