using System;
using System.Collections.Generic;
using System.Linq;
using Sirenix.Utilities;
using VOID.Generic.Dict;
using VOID.Generic.Objects.Unit.Events;
using VOID.Generic.Status.Effect;

namespace VOID.Generic.Objects.Unit.DataCalculator
{
    public class SubAttributeCalcGroup : ICalcGroup
    {
        public string GetMarkerGroup()
        {
            return "SubAttribute";
        }

        public IEnumerable<string> GetMarkerItems()
        {
            return GetEnums().Select(@enum => @enum.ToString());
        }

        public Type GetEnumType()
        {
            return typeof(SubAttributeType);
        }

        public IEnumerable<Enum> GetEnums()
        {
            return Enum.GetValues(GetEnumType()).OfType<Enum>();
        }

        public Enum GetEnum(string markerItem)
        {
            return Enum.Parse<SubAttributeType>(markerItem, true);
        }

        public float GetEffectValue(UnitObject unit, string markerItem)
        {
            var @enum = Enum.Parse<SubAttributeType>(markerItem, true);
            return unit.statusManager.GetStatuses()
                .SelectMany(status => status.effects)
                .FilterCast<PointChangeSubAttributeEffect>()
                .Where(effect => effect.subAttributeType == @enum)
                .Select(effect => effect.pointModificator)
                .Sum();
        }

        public float GetBaseValue(UnitObject unit, string markerItem)
        {
            return unit.unitData.baseSubAttributes.Get(Enum.Parse<SubAttributeType>(markerItem, true));
        }

        public float GetValue(UnitObject unit, string markerItem)
        {
            return unit.unitData.subAttributes.Get(Enum.Parse<SubAttributeType>(markerItem, true));
        }

        public void UpdateWithValue(UnitObject unit, string markerItem, float formulaValue)
        {
            var @enum = Enum.Parse<SubAttributeType>(markerItem, true);
            var baseValue = GetBaseValue(unit, markerItem);
            var effectValue = GetEffectValue(unit, markerItem);
            var previousValue = GetValue(unit, markerItem);
            var newValue = baseValue + effectValue + formulaValue;
            var diffValue = newValue - previousValue;
            unit.unitData.subAttributes.Set(@enum, newValue);

            unit.unitEvents.onSubAttributeChange.Invoke(
                new SubAttributeChangeEvent
                {
                    unit = unit,
                    type = @enum,
                    changedValue = diffValue,
                    newValue = newValue,
                    oldValue = previousValue
                }
            );
        }
    }
}