using System;
using System.Collections.Generic;

namespace FishDice.LuckyDice
{
    public sealed class LuckyDiceRuntimeFactory
    {
        private readonly LuckyDiceConfigValidationContext _context;
        private readonly IRandomSource _random;

        public LuckyDiceRuntimeFactory(
            LuckyDiceConfigValidationContext context,
            IRandomSource random)
        {
            _context = context ?? LuckyDiceConfigValidationContext.CreateDefault();
            _random = random ?? throw new ArgumentNullException(nameof(random));
        }

        public static LuckyDiceRuntimeFactory CreateDefault(IRandomSource random)
        {
            return new LuckyDiceRuntimeFactory(LuckyDiceConfigValidationContext.CreateDefault(), random);
        }

        public LuckyDiceRollFlowService CreateDefaultFlow()
        {
            return CreateFlow(LuckyDiceDefaultConfig.CreateValidated(_context));
        }

        public LuckyDiceRollFlowService CreateFlow(
            IReadOnlyList<ComboRuleDefinition> ruleDefinitions,
            IReadOnlyList<LuckyDiceCandidateDefinition> candidateDefinitions,
            IReadOnlyList<TargetModeDefinition> targetModeDefinitions)
        {
            var config = LuckyDiceDefaultConfig.CreateValidated(
                ruleDefinitions,
                candidateDefinitions,
                targetModeDefinitions,
                _context);

            return CreateFlow(config);
        }

        public LuckyDiceRollFlowService CreateFlow(LuckyDiceDefaultConfig config)
        {
            if (config == null)
            {
                throw new ArgumentNullException(nameof(config));
            }

            return new LuckyDiceRollFlowService(
                config,
                new DiceRollService(_random),
                new ComboRuleMatcher(_context.Matchers),
                new RollActionDispatcher(_context.ActionExecutors),
                new LuckyDiceFlowService(_random),
                new TargetModeResolver());
        }
    }
}
