using System;
using ZLinq;

namespace Nox.Game {
    public interface ICharacterStatsFactory {
        EntityStats Create(IEntityDefinition entityDefinition);
    }

    public sealed class CharacterStatsFactory : ICharacterStatsFactory {
        private readonly StarterCharacterSettings baseSettings;
        private readonly IModifierResolver modifierResolver;

        public CharacterStatsFactory(StarterCharacterSettings baseSettings, IModifierResolver modifierResolver) {
            this.baseSettings = baseSettings;
            this.modifierResolver = modifierResolver ?? throw new ArgumentNullException(nameof(modifierResolver));
        }

        public EntityStats Create(IEntityDefinition entityDefinition) {
            var attributes = entityDefinition.Attributes;

            if(attributes.attributes.AsValueEnumerable().Any(a => a.value <= 0)) {
                throw new ArgumentOutOfRangeException( "attributes cannot be zero or negative.", new ArgumentException() );
            }

            var healthModifiers = modifierResolver.CollectModifiers(entityDefinition, StatType.Health);
            var manaModifiers = modifierResolver.CollectModifiers(entityDefinition, StatType.Mana);
            var levelModifiers = modifierResolver.CollectModifiers(entityDefinition, StatType.Level);
            var experienceModifiers = modifierResolver.CollectModifiers(entityDefinition, StatType.Experience);

            return new EntityStats {
                stats = new[] {
                    new Stat(StatType.Health, modifierResolver.Resolve(baseSettings.defaultEntityStats.GetValue(StatType.Health), healthModifiers, entityDefinition)),
                    new Stat(StatType.Mana, modifierResolver.Resolve(baseSettings.defaultEntityStats.GetValue(StatType.Mana), manaModifiers, entityDefinition)),
                    new Stat(StatType.Level, modifierResolver.Resolve(baseSettings.defaultEntityStats.GetValue(StatType.Level), levelModifiers, entityDefinition)),
                    new Stat(StatType.Experience,  modifierResolver.Resolve(baseSettings.defaultEntityStats.GetValue(StatType.Experience), experienceModifiers, entityDefinition))
                }
            };
        }
    }
}
