using Quadarax.Foundation.Core.Data;

namespace qdr.fnd.core.pqueue.fnd.candidates
{
    public static class TypedArgumentExt
    {
        public static TValue? GetArgumentValue<TValue>(this IEnumerable<TypedArgument> args, string argumentName)
        {
            var arg = GetArgument(args, argumentName);
            return arg.GetTypedValue<TValue>();
        }

        public static void SetArgumentValue<TValue>(this IEnumerable<TypedArgument> args, string argumentName, TValue? value)
        {
            var arg = GetArgument(args, argumentName);
            if (value!=null && value.GetType().Name != arg.ValueType.Name)
                throw new ArgumentOutOfRangeException(nameof(value), value, $"Value type '{value.GetType().Name}' is not equal to argument type '{arg.ValueType.Name}'.");
            arg.Value = value == null ? null : value.ToString();
        }

        public static TypedArgument GetArgument(this IEnumerable<TypedArgument> args, string argumentName)
        {
            if (args == null) throw new ArgumentNullException(nameof(args));
            if (string.IsNullOrWhiteSpace(argumentName)) throw new ArgumentNullException(nameof(argumentName));

            if (!args.ContainsArgument(argumentName)) throw new ArgumentOutOfRangeException(nameof(argumentName),argumentName,$"Argument named '{argumentName}' is not in argument collection.");

            return args.First(a => a.Name == argumentName);
        }

        public static bool ContainsArgument(this IEnumerable<TypedArgument> args, string argumentName)
        {
            if (args == null) throw new ArgumentNullException(nameof(args));
            if (string.IsNullOrWhiteSpace(argumentName)) throw new ArgumentNullException(nameof(argumentName));

            return args.Any(a => a.Name == argumentName);
        }
    }
}
