/*
 * Copyright (c) 2004 Brian McCallister. All Rights Reserved.
 */
package org.skife.gear.service;

import org.apache.lucene.analysis.Analyzer;
import org.apache.lucene.document.Document;
import org.apache.lucene.index.IndexReader;
import org.apache.lucene.index.Term;
import org.apache.lucene.queryParser.ParseException;
import org.apache.lucene.queryParser.QueryParser;
import org.apache.lucene.search.Hits;
import org.apache.lucene.search.IndexSearcher;
import org.apache.lucene.search.Query;
import org.skife.gear.ServiceException;
import org.skife.gear.Student;
import org.skife.gear.search.SmarterAnalyzer;

import javax.servlet.ServletContext;
import java.io.File;
import java.io.IOException;
import java.util.ArrayList;
import java.util.Collections;
import java.util.Comparator;
import java.util.List;

public class StudentIndex
{
    private final File index;
    private final StudentDAO dao;
    private final Analyzer analyzer;

    public StudentIndex(final Analyzer analyzer,
                        final String dir,
                        final StudentDAO dao)
    {
        this.analyzer = analyzer;
        this.dao = dao;
        index = new File(dir);
    }

    public StudentIndex(final String dir, final StudentDAO dao)
    {
        this(new org.skife.gear.search.SmarterAnalyzer(), dir, dao);
    }

    public StudentIndex(final ServletContext ctx, final StudentDAO dao)
    {
        this(new SmarterAnalyzer(), ctx.getRealPath("WEB-INF/student-index"), dao);
    }

    public List findStudents(final String search, final int numberOfResults) throws ServiceException
    {
        final Query query;
        try
        {
            query = QueryParser.parse(search, StudentIndexer.NAME, analyzer);
        }
        catch (ParseException e)
        {
            throw new ServiceException("Unable to make any sense of the query", e);
        }
        final ArrayList ids = new ArrayList();
        try
        {
            final IndexReader reader = IndexReader.open(index);
            final IndexSearcher searcher = new IndexSearcher(reader);
            final Hits hits = searcher.search(query);
            for (int i = 0; i != hits.length() && i != numberOfResults; ++i)
            {
                final Document doc = hits.doc(i);
                ids.add(new Integer(doc.getField(StudentIndexer.IDENTITY).stringValue()));
            }
            searcher.close();
            reader.close();
        }
        catch (IOException e)
        {
            throw new ServiceException("Error while reading student data from index", e);
        }
        final List students = dao.findStudentsWithIdsIn(ids);
        Collections.sort(students, new Comparator()
        {
            public int compare(final Object o1, final Object o2)
            {
                final Integer id_1 = ((Student) o1).getId();
                final Integer id_2 = ((Student) o1).getId();
                for (int i = 0; i < ids.size(); i++)
                {
                    final Integer integer = (Integer) ids.get(i);
                    if (integer.equals(id_1))
                    {
                        return -1;
                    }
                    if (integer.equals(id_2))
                    {
                        return 1;
                    }
                }
                return 0;
            }
        });
        return students;
    }

    public List findStudents(final String search) throws ServiceException
    {
        return this.findStudents(search, Integer.MAX_VALUE);
    }

    public void remove(final Student student) throws ServiceException
    {
        try
        {
            final IndexReader reader = IndexReader.open(index);
            final Term term = new Term(StudentIndexer.IDENTITY, student.getId().toString());
            reader.delete(term);
            reader.close();
        }
        catch (IOException e)
        {
            throw new ServiceException("Error while removing student data from index", e);
        }
    }
}
