package org.zanata.hibernate.search;

import java.io.IOException;
import java.io.StringReader;
import java.util.List;
import java.util.Map;

import org.apache.lucene.document.Document;
import org.apache.lucene.document.Field;
import org.hibernate.search.bridge.FieldBridge;
import org.hibernate.search.bridge.LuceneOptions;
import org.hibernate.search.bridge.ParameterizedBridge;
import org.jboss.seam.annotations.Logger;
import org.jboss.seam.log.Log;

/**
 * Index a list of strings in multiple fields, appending the string index to the
 * field name to produce unique fields.
 * 
 * e.g. For a field labeled 'fieldName' for a list of 3 strings
 * <ul>
 * <li>First string is indexed as 'fieldName0'</li>
 * <li>Second string is indexed as 'fieldName1'</li>
 * <li>Third string is indexed as 'fieldName2'</li>
 * </ul>
 * 
 * @author David Mason, damason@redhat.com
 * 
 */
public class StringListBridge implements FieldBridge, ParameterizedBridge
{

   @Logger
   Log log;

   private ConfigurableNgramAnalyzer analyzer;
   private boolean caseSensitive = false;
   private boolean multiNgrams = false;

   @Override
   public void setParameterValues(@SuppressWarnings("rawtypes") Map parameters)
   {
      if (parameters.containsKey("case"))
      {
         String caseBehaviour = (String) parameters.get("case");
         if ("fold".equals(caseBehaviour))
         {
            caseSensitive = false;
         }
         else if ("preserve".equals(caseBehaviour))
         {
            caseSensitive = true;
         }
         else
         {
            log.warn("invalid value for parameter \"case\": \"{0}\", default will be used", caseBehaviour);
            caseSensitive = false;
         }
      }
      if (parameters.containsKey("ngrams"))
      {
         String ngrams = (String) parameters.get("ngrams");
         if ("multisize".equals(ngrams))
         {
            multiNgrams = true;
         }
         else
         {
            log.warn("invalid value for parameter \"ngrams\": \"{0}\", default will be used", ngrams);
            multiNgrams = false;
         }
      }
   }

   @Override
   public void set(String name, Object value, Document luceneDocument, LuceneOptions luceneOptions)
   {
      if (caseSensitive)
      {
         if (multiNgrams)
         {
            analyzer = new CaseSensitiveNgramAnalyzer(1, 3);
         }
         else
         {
            analyzer = new CaseSensitiveNgramAnalyzer();
         }
      }
      else if (multiNgrams)
      {
         analyzer = new CaseInsensitiveNgramAnalyzer(1, 3);
      }
      else
      {
         analyzer = new CaseInsensitiveNgramAnalyzer();
      }

      if (!(value instanceof List<?>))
      {
         throw new IllegalArgumentException("this bridge must be applied to a List");
      }
      List<String> strings = (List<String>) value;
      for (int i = 0; i < strings.size(); i++)
      {
         addStringField(name + i, strings.get(i), luceneDocument, luceneOptions);
      }
   }

   private void addStringField(String fieldName, String fieldValue, Document luceneDocument, LuceneOptions luceneOptions)
   {
      Field field = new Field(fieldName, fieldValue, luceneOptions.getStore(), luceneOptions.getIndex(), luceneOptions.getTermVector());
      field.setBoost(luceneOptions.getBoost());

      // manually apply token stream from analyzer, as hibernate search does not
      // apply the specified analyzer properly
      try
      {
         field.setTokenStream(analyzer.reusableTokenStream(fieldName, new StringReader(fieldValue)));
      }
      catch (IOException e)
      {
         log.error("Failed to get token stream from analyzer for field \"{0}\" with content \"{1}\"", e, fieldName, fieldValue);
      }
      luceneDocument.add(field);
   }

}

@@ -2223,44 +2223,8 @@
   %7B%0A
-      if (caseSensitive)%0A      %7B%0A   
     
@@ -2242,19 +2242,16 @@
 Ngrams)%0A
-   
       %7B%0A
@@ -2251,35 +2251,32 @@
      %7B%0A         
-   
 analyzer = new C
@@ -2271,35 +2271,34 @@
 yzer = new C
-aseSensitiv
+onfigurabl
 eNgramAnalyz
@@ -2308,114 +2308,26 @@
 1, 3
-);%0A         %7D%0A         else%0A         %7B%0A            analyzer = new CaseSensitiveNgramAnalyzer();%0A         %7D
+, !caseSensitive);
 %0A   
@@ -2341,33 +2341,16 @@
     else
- if (multiNgrams)
 %0A      %7B
@@ -2371,37 +2371,34 @@
 yzer = new C
-aseInsensitiv
+onfigurabl
 eNgramAnalyz
@@ -2404,95 +2404,25 @@
 zer(
-1, 3);%0A      %7D%0A      else%0A      %7B%0A         analyzer = new CaseInsensitiveNgramAnalyzer(
+3, !caseSensitive
 );%0A 

simplify ngram analyzer selection in StringListBridge