using System;
using System.Collections.Generic;
using System.Linq;

namespace FishDice.LuckyDice
{
    public sealed class ComboRuleMatcher
    {
        private readonly IReadOnlyDictionary<string, IComboMatcher> _matchers;

        public ComboRuleMatcher()
            : this(ComboMatcherRegistry.CreateDefaultMatchers())
        {
        }

        public ComboRuleMatcher(IEnumerable<IComboMatcher> matchers)
        {
            if (matchers == null)
            {
                throw new ArgumentNullException(nameof(matchers));
            }

            _matchers = matchers.ToDictionary(matcher => matcher.MatcherType, matcher => matcher);
        }

        public ComboRuleMatchResult Match(ComboFacts facts, IReadOnlyList<ComboRule> rules)
        {
            if (facts == null)
            {
                throw new ArgumentNullException(nameof(facts));
            }

            if (rules == null)
            {
                throw new ArgumentNullException(nameof(rules));
            }

            var matches = new List<ComboRuleMatch>();
            foreach (var rule in rules.OrderByDescending(rule => rule.Priority))
            {
                if (!MatchesRule(facts, rule.Matcher))
                {
                    continue;
                }

                matches.Add(new ComboRuleMatch(rule));
                if (rule.StopAfterMatched)
                {
                    break;
                }
            }

            return new ComboRuleMatchResult(matches);
        }

        private bool MatchesRule(ComboFacts facts, ComboMatcherSpec matcher)
        {
            if (!_matchers.TryGetValue(matcher.MatcherType, out var registeredMatcher))
            {
                return false;
            }

            return registeredMatcher.IsMatch(facts, matcher);
        }
    }
}
