# Filter für einfachen Wert mit Wertebereich als Collection
# und Darstellung als Select-Box.
# Der Wertebereich wird dabei über eine FacetSuche ermittelt (per Methode 'list_possible_values' des Searchers)
#
class MultiSolr::SolrFilterCollection < MultiSolr::SolrFilterSimple

  # Constructor des Filters
  # Params:
  #   filter_name: Name des Filters als Symbol
  #   options:     optionale Hash mit den folgenden Optionen (sind alle optional):
  #     :render_value      siehe Optionen bei MultiSolr::SolrFilterSimple.initialize
  #     :solr_query        siehe Optionen bei MultiSolr::SolrFilterSimple.initialize
  #     :collection_data:  Proc, welches den Wertebereich(Array) liefert
  #                        Wenn nicht angegeben, dann wird per 'Searcher.list_possible_values'
  #                        mit den Name des Filters der Wertebereich ermittelt.
  #                        Das Proc bekommt den Such-Context(Hash) als Parameter (enthält i.a. Searcher und force-query-params).
  #                        Beispiel: :collection_data => lambda{|context| (2..10).to_a }
  #     :after_collect:    optionales Proc, welches den Wertebereich(Array) nachbearbeitet
  #                        Das Proc bekommt den Wertebereich(Array) als Parameter
  #                        Beispiel: :after_collect => lambda{|data| MasterData::LockType.cached_find_for_short_names(data).map{|l| [l.full_label, l.short_name] } }
  #
  def initialize filter_name, options={}
    @collection_proc = options.delete(:collection_data)
    @after_collect_proc = options.delete(:after_collect)
    if options[:render_value].nil?
      options[:render_value] = lambda{|value| compact_values(value).join(' oder ') }
    end
    if options[:solr_query].nil?
      options[:solr_query] = lambda do |value|
        if value.is_a?(Array)
          values = compact_values(value)
          if values.empty?
            ''
          else
            q = values.map{|val| "#{@name}:#{val}"}.join(' OR ')
            "(#{q})"
          end
        else
          "#{@name}:#{value}"
        end
      end
    end
    super filter_name, options
  end


  # Generieren Select-Box für ein Sematic-Form
  # Params:   siehe MultiSolr::SolrFilterSimple#render_for_semantic_form
  # returns:  HTML-Code des Input-Feldes als Select-Box
  def render_for_semantic_form sform, value, context=nil, form_input_options={}
    form_input_options = @options[:semantic_form].merge form_input_options if @options.key? :semantic_form
    set_label form_input_options
    data = self.collection_data(nil, context)
    html_options = form_input_options[:input_html]
    if html_options
      if html_options[:size]
        # size wird als max-size verstanden. wenn akt. Data-Range kleiner
        # ist, dann darauf reduzieren
        html_options[:size] = [data.size+1, html_options[:size].to_i].min
      end
    end
    form_input_options.merge! :collection => data
    sform.input "filter_#{@name}", form_input_options
  end


  # Ermittelt den Wertebereich entweder über die bei den Options angegebene Proc
  # oder über list_possible_values des Searchers (mit den Namen des Filters als Parameter)
  # Params:
  #   core_handler:   Instanz des konkreten Solr-CoreHandler (MultiSolr::SingleCoreHandler)
  #   context:        Hash mit dem Such-Context.
  #   search_request: optional bestehendes SearchRequest (für DrillDown-Funktionalität)
  # returns:    Array mit dem Wertebereich
  def collection_data core_handler, context, search_request=nil
    if @collection_proc
      data = @collection_proc.call(context)
    else
      data = core_handler.cached_list_possible_values(self.name, context, search_request)
    end
    if @after_collect_proc
      data = @after_collect_proc.call(data)
      data.compact!
    end
    data
  end


  # Wandeltangegebener value in ein Array (wenn es noch keins ist)
  # Bereinigt das Array von leeren Elementen

  def compact_values value
    value = [value] unless value.is_a?(Array)
    value.delete_if(&:blank?)
  end

end