module Bashly::ValidationHelpers

def assert(valid, message)

def assert(valid, message)
  raise ConfigurationError, message unless valid
end

def assert_array(key, value, of: nil)

def assert_array(key, value, of: nil)
  return unless value
  assert value.is_a?(Array), "#{key} must be an array"
  return unless of
  value.each_with_index do |val, i|
    send :"assert_#{of}", "#{key}[#{i}]", val
  end
end

def assert_boolean(key, value)

def assert_boolean(key, value)
  assert [true, false, nil].include?(value), "#{key} must be a boolean"
end

def assert_hash(key, value, keys: nil)

def assert_hash(key, value, keys: nil)
  assert value.is_a?(Hash), "#{key} must be a hash"
  return unless keys
  invalid_keys = (value.keys.map(&:to_sym) - keys).reject { |k| k.start_with? 'x_' }
  assert invalid_keys.empty?, "#{key} contains invalid options: #{invalid_keys.join ', '}"
end

def assert_optional_string(key, value)

def assert_optional_string(key, value)
  assert_string key, value if value
end

def assert_string(key, value)

def assert_string(key, value)
  assert value.is_a?(String), "#{key} must be a string"
end

def assert_string_or_array(key, value)

def assert_string_or_array(key, value)
  return unless value
  assert [Array, String].include?(value.class),
    "#{key} must be a string or an array"
  assert_array key, value, of: :string if value.is_a? Array
end

def assert_uniq(key, value, array_keys)

def assert_uniq(key, value, array_keys)
  return unless value
  array_keys = [array_keys] unless array_keys.is_a? Array
  list = []
  array_keys.each do |array_key|
    list += value.filter_map { |c| c[array_key] }.flatten
  end
  nonuniqs = list.nonuniq
  assert nonuniqs.empty?, "#{key} contains non-unique elements (#{nonuniqs.join ', '}) in #{array_keys.join ' or '}"
end

def refute(invalid, message)

def refute(invalid, message)
  assert !invalid, message
end