/// <summary>
        /// Validate a change.
        /// </summary>
        /// <param name="setting">A setting for validation.</param>
        /// <returns>Validation Status enumeration.</returns>
        private ValidationStatus ValidateChange(SettingChange setting)
        {
            if (setting == null)
            {
                throw new ArgumentNullException(nameof(setting));
            }

            ValidationStatus validity = ValidationStatus.Valid;

            if (string.IsNullOrEmpty(setting.SettingName))
            {
                return(ValidationStatus.InvalidMissingSetting);
            }

            if (string.IsNullOrEmpty(setting.Value) && setting.Amount == null)
            {
                return(ValidationStatus.InvalidMissingValue);
            }

            var settingInfo = settingList.FindSetting(setting.SettingName);

            if (settingInfo == null)
            {
                return(ValidationStatus.InvalidSettingName);
            }

            AvailableSettingValue settingValueInfo = null;

            foreach (var valueInfo in settingInfo.Values)
            {
                if (Util.NullSafeEquals(setting.Value, valueInfo.CanonicalName) ||
                    (string.IsNullOrEmpty(setting.Value) && "SET".Equals(valueInfo.CanonicalName.ToUpperInvariant())))
                {
                    settingValueInfo = valueInfo;
                    setting.Value    = valueInfo.CanonicalName;
                    break;
                }
            }

            if (settingValueInfo == null)
            {
                return(ValidationStatus.InvalidSettingValueCombination);
            }

            if (setting.Amount == null)
            {
                if (settingValueInfo.RequiresAmount)
                {
                    validity = ValidationStatus.InvalidMissingAmount;
                }

                return(validity);
            }

            if (!settingInfo.AllowsAmount || Util.IsNullOrEmpty(settingInfo.Amounts))
            {
                return(ValidationStatus.InvalidExtraAmount);
            }

            AvailableSettingAmount settingAmountInfo = null;

            foreach (var amountInfo in settingInfo.Amounts)
            {
                if (Util.NullSafeEquals(setting.Amount.Unit, amountInfo.Unit))
                {
                    settingAmountInfo = amountInfo;
                    break;
                }
            }

            if (settingAmountInfo == null)
            {
                if ("%".Equals(setting.Amount.Unit))
                {
                    settingAmountInfo = new AvailableSettingAmount()
                    {
                        Unit = "%",
                        Min  = 0,
                        Max  = 100,
                    };
                }
                else
                {
                    return(ValidationStatus.InvalidAmountUnit);
                }
            }

            if (!setting.IsRelativeAmount)
            {
                if (setting.Amount.Amount < settingAmountInfo.Min || setting.Amount.Amount > settingAmountInfo.Max)
                {
                    return(ValidationStatus.InvalidAmountOutOfRange);
                }
            }
            else if (settingAmountInfo.Min != null && settingAmountInfo.Max != null)
            {
                var maxRelative = settingAmountInfo.Max - settingAmountInfo.Min;
                var minRelative = -maxRelative;
                if (setting.Amount.Amount < minRelative || setting.Amount.Amount > maxRelative)
                {
                    return(ValidationStatus.InvalidAmountOutOfRange);
                }
            }

            return(validity);
        }
        /// <summary>
        /// Apply the user's selection to the setting values.
        /// </summary>
        /// <param name="state">State object.</param>
        /// <param name="entityValues">List of entity values.</param>
        /// <returns>The selected SettingChanges or null if no selection was made.</returns>
        public IList <SettingChange> ApplySelectionToSettingValues(AutomotiveSkillState state, List <string> entityValues)
        {
            if (state == null)
            {
                throw new ArgumentNullException(nameof(state));
            }

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

            var settingValues = state.GetUniqueSettingValues();

            ISet <string> selectedSettingValues = new HashSet <string>();

            if (entityValues.Any() && settingValues.Any())
            {
                IList <SelectableSettingValue> selectableSettingValues = new List <SelectableSettingValue>();
                foreach (var change in state.Changes)
                {
                    SelectableSettingValue selectable = new SelectableSettingValue
                    {
                        CanonicalSettingName = change.SettingName
                    };
                    var availableValue = this.settingList.FindSettingValue(change.SettingName, change.Value);
                    if (availableValue != null)
                    {
                        selectable.Value = availableValue;
                    }
                    else
                    {
                        availableValue = new AvailableSettingValue
                        {
                            CanonicalName = change.Value
                        };
                        selectable.Value = availableValue;
                    }

                    selectableSettingValues.Add(selectable);
                }

                var selected_values = this.settingMatcher.DisambiguateSettingValues(
                    entityValues,
                    selectableSettingValues, SettingValueAntonymDisambThreshold, SettingValueAntonymDisambPercentageOfMax);

                foreach (var selected_value in selected_values)
                {
                    selectedSettingValues.Add(selected_value.Value.CanonicalName);
                }
            }

            IList <SettingChange> newCandidates = new List <SettingChange>();

            foreach (var candidate in state.Changes)
            {
                if (selectedSettingValues.Contains(candidate.Value))
                {
                    newCandidates.Add(candidate);
                }
            }

            if (!Util.IsNullOrEmpty(newCandidates))
            {
                return(newCandidates);
            }

            return(null);
        }