class SearchCop::HashParser
  attr_reader :query_info

  def initialize(query_info)
    @query_info = query_info
  end

  def parse(hash, query_options = {})
    default_operator = SearchCop::Helpers.sanitize_default_operator(query_options)

    res = hash.collect do |key, value|
      case key
      when :and
        value.collect { |val| parse val }.inject(:and)
      when :or
        value.collect { |val| parse val }.inject(:or)
      when :not
        parse(value).not
      when :query
        SearchCop::Parser.parse(value, query_info)
      else
        parse_attribute(key, value)
      end
    end

    res.inject(default_operator)
  end

  private

  def parse_attribute(key, value)
    collection = SearchCopGrammar::Attributes::Collection.new(query_info, key.to_s)

    if value.is_a?(Hash)
      raise(SearchCop::ParseError, "Unknown operator #{value.keys.first}") unless collection.valid_operator?(value.keys.first)

      generator = collection.generator_for(value.keys.first)

      if generator
        collection.generator(generator, value.values.first)
      else
        collection.send(value.keys.first, value.values.first.to_s)
      end
    else
      collection.send(:matches, value.to_s)
    end
  end
end
