using System;
using Schema;
using Sirenix.OdinInspector;
using UnityEngine;
using VOID.Generic.Objects.Unit;
using VOID.Generic.Util;
using Action = Schema.Action;

namespace VOID.Generic.AI.Schema.Actions
{
    [Description("Gets distance between ThisUnit and target position or unit, minus radius of both of units")]
    [Category(SchemaCategory.ThisUnit)]
    public class GetDistanceTo : Action
    {
        private enum DistanceFrom
        {
            Current,
            Another
        }
        
        private enum DistanceTo
        {
            Position,
            Unit
        }
        
         [SerializeField] private DistanceFrom _distanceFrom;
         [SerializeField, ShowIf(nameof(_distanceFrom), DistanceFrom.Another)] private BlackboardEntrySelector<Vector3> _position;
         [SerializeField, Space(15)] private DistanceTo _distanceTo;
         [SerializeField, ShowIf(nameof(_distanceTo), DistanceTo.Position)] private BlackboardEntrySelector<Vector3> _toPosition;
         [SerializeField, ShowIf(nameof(_distanceTo), DistanceTo.Unit)] private BlackboardEntrySelector<UnitObject> _toUnit;

         [WriteOnly, SerializeField, Space(15)] private BlackboardEntrySelector<float> _saveTo;

        public override NodeStatus Tick(object nodeMemory, SchemaAgent agent)
        {
            var unitAgent = (UnitObjectSchemaAgent)agent;
            var thisUnit = unitAgent.unit;

            _saveTo.value = (_distanceFrom, _distanceTo) switch
            {
                (DistanceFrom.Current, DistanceTo.Position) => RangeUtil.GetDistance(thisUnit, _toPosition.value),
                (DistanceFrom.Current, DistanceTo.Unit) => RangeUtil.GetDistance(thisUnit, _toUnit.value),
                (DistanceFrom.Another, DistanceTo.Position) => RangeUtil.GetDistance(_toPosition.value, _position.value) - thisUnit.basicData.radius,
                (DistanceFrom.Another, DistanceTo.Unit) => RangeUtil.GetDistance(_toUnit.value, _position.value) - thisUnit.basicData.radius,
                _ => throw new ArgumentOutOfRangeException()
            };

            return NodeStatus.Success;
        }
    }
}