/**
 * 
 */
package org.forkalsrud.album.index;

import java.io.IOException;
import java.util.ArrayList;
import java.util.List;

import org.apache.lucene.analysis.standard.StandardAnalyzer;
import org.apache.lucene.document.Document;
import org.apache.lucene.document.Field;
import org.apache.lucene.document.StringField;
import org.apache.lucene.document.TextField;
import org.apache.lucene.facet.index.FacetFields;
import org.apache.lucene.facet.params.FacetIndexingParams;
import org.apache.lucene.facet.params.FacetSearchParams;
import org.apache.lucene.facet.search.CountFacetRequest;
import org.apache.lucene.facet.search.DrillDownQuery;
import org.apache.lucene.facet.search.FacetResult;
import org.apache.lucene.facet.search.FacetResultNode;
import org.apache.lucene.facet.search.FacetsCollector;
import org.apache.lucene.facet.taxonomy.CategoryPath;
import org.apache.lucene.facet.taxonomy.directory.DirectoryTaxonomyReader;
import org.apache.lucene.facet.taxonomy.directory.DirectoryTaxonomyWriter;
import org.apache.lucene.index.DirectoryReader;
import org.apache.lucene.index.IndexReader;
import org.apache.lucene.index.IndexWriter;
import org.apache.lucene.index.IndexWriterConfig;
import org.apache.lucene.queryparser.classic.QueryParser;
import org.apache.lucene.search.IndexSearcher;
import org.apache.lucene.search.MatchAllDocsQuery;
import org.apache.lucene.search.Query;
import org.apache.lucene.search.ScoreDoc;
import org.apache.lucene.search.TopScoreDocCollector;
import org.apache.lucene.store.Directory;
import org.apache.lucene.store.RAMDirectory;
import org.apache.lucene.util.Version;
import org.junit.Test;

/**
 * @author knut
 * 
 */
public class LuceneTest {

    Version version = Version.LUCENE_44;

    @Test
    public void testIndexCreation() throws Exception {

        StandardAnalyzer analyzer = new StandardAnalyzer(version);
        Directory index = new RAMDirectory();
        Directory taxoDir = new RAMDirectory();

        IndexWriterConfig config = new IndexWriterConfig(version, analyzer);
        IndexWriter w = new IndexWriter(index, config);

        DirectoryTaxonomyWriter taxoWriter = new DirectoryTaxonomyWriter(taxoDir);
        FacetFields facetFields = new FacetFields(taxoWriter);

        List<CategoryPath> book1 = new ArrayList<CategoryPath>();
        book1.add(new CategoryPath("Author", "Erik Hatcher"));
        book1.add(new CategoryPath("Author", "Otis Gospodnetić"));
        book1.add(new CategoryPath("Pub Date", "2004", "December", "1"));

        List<CategoryPath> book2 = new ArrayList<CategoryPath>();
        book2.add(new CategoryPath("Author", "Michael McCandless"));
        book2.add(new CategoryPath("Author", "Erik Hatcher"));
        book2.add(new CategoryPath("Author", "Otis Gospodnetić"));
        book2.add(new CategoryPath("Pub Date", "2010", "July", "28"));
        
        addDoc(w, facetFields, "Lucene in Action", "193398817", book1);
        addDoc(w, facetFields, "Lucene for Dummies", "55320055Z", book2);
        addDoc(w, facetFields, "Managing Gigabytes", "55063554A", null);
        addDoc(w, facetFields, "The Art of Computer Science", "9900333X", null);
        w.close();
        taxoWriter.close();


        IndexReader reader = DirectoryReader.open(index);
        IndexSearcher searcher = new IndexSearcher(reader);

        DirectoryTaxonomyReader taxor = new DirectoryTaxonomyReader(taxoDir);


        FacetSearchParams fsp = new FacetSearchParams(new CountFacetRequest(new CategoryPath("Author"), 10), new CountFacetRequest(new CategoryPath("Pub Date"), 10));
        FacetsCollector facetsCollector = FacetsCollector.create(fsp, reader, taxor);
        searcher.search(new MatchAllDocsQuery(), facetsCollector);

        for (FacetResult fres : facetsCollector.getFacetResults()) {
            FacetResultNode root = fres.getFacetResultNode();
            root.value = fres.getNumValidDescendants();
            System.out.println(root.toString());
        }

        String querystr = "lucene";
        Query q = new QueryParser(version, "title", analyzer).parse(querystr);
         
        showResultsForQuery(searcher, q);

        DrillDownQuery ddq = new DrillDownQuery(FacetIndexingParams.DEFAULT, q);
        ddq.add(new CategoryPath("Author", "Michael McCandless"));
        showResultsForQuery(searcher, ddq);

        
        // reader can only be closed when there
        // is no need to access the documents any more.
        reader.close();
        taxor.close();
        index.close();
        taxoDir.close();
    }

    /**
     * @param searcher
     * @param q
     * @throws IOException
     */
    public void showResultsForQuery(IndexSearcher searcher,
            Query q) throws IOException {
        int hitsPerPage = 10;

        TopScoreDocCollector collector = TopScoreDocCollector.create(hitsPerPage, true);
        searcher.search(q, collector);
        ScoreDoc[] hits = collector.topDocs().scoreDocs;

        System.out.println("Found " + hits.length + " hits.");
        for(int i=0;i<hits.length;++i) {
            int docId = hits[i].doc;
            Document d = searcher.doc(docId);
            System.out.println((i + 1) + ". " + d.get("isbn") + "\t" + d.get("title"));
        }
    }

    private void addDoc(IndexWriter w, FacetFields facetFields, String title, String isbn, List<CategoryPath> categories) throws IOException {
        Document doc = new Document();
        doc.add(new TextField("title", title, Field.Store.YES));
        doc.add(new StringField("isbn", isbn, Field.Store.YES));
        if (categories != null) {
            facetFields.addFields(doc, categories);
        }
        w.addDocument(doc);
    }
}
