package org.neoref.query;


import java.io.IOException;
import java.net.URLEncoder;
import java.sql.SQLException;
import java.util.ArrayList;
import java.util.List;
import java.util.HashMap;
import java.util.Iterator;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import org.apache.log4j.Logger;

import org.apache.lucene.queryParser.ParseException;
import org.apache.lucene.queryParser.TokenMgrError;

import org.dspace.query.NRQuery;
import org.dspace.query.QueryArgs;
import org.dspace.query.QueryResults;

public class SimpleSearchServlet extends HttpServlet
{
    /** log4j category */
    private static Logger log = Logger.getLogger(SimpleSearchServlet.class);
    
    protected void doPost(Context context,
        HttpServletRequest request,
        HttpServletResponse response)
        throws ServletException, IOException, SQLException, AuthorizeException
    {
        // Get the query
        String query 	  = request.getParameter("query");
        String advanced   = request.getParameter("advanced");
        String fromAdvanced   = request.getParameter("from_advanced");
        String advancedQuery = "";
        HashMap queryHash = new HashMap();
        
        List collectionHandles = new ArrayList();
        List communityHandles  = new ArrayList();

        Item       [] resultsItems;

        QueryResults qResults = null;
        QueryArgs    qArgs    = new QueryArgs();

		// if the "advanced" flag is set, build the query string from the 
		// multiple query fields
        if (advanced != null) 
        {
        	query = qArgs.buildQuery(request);
        	advancedQuery = qArgs.buildHTTPQuery(request);
        } 

        // Ensure the query is non-null
        if (query == null)
        {
            query = "";
        }

        // Get the location parameter, if any
        String location = request.getParameter("location");
        String newURL;

        // Build log information
        String logInfo = "";

        // Get our location
        Community community   = UIUtil.getCommunityLocation(request);
        Collection collection = UIUtil.getCollectionLocation(request);

        // get the start of the query results page
        qArgs.setQuery( query );
        qArgs.setStart( start );
                
        // Perform the search
        try
        {
                // Get all communities for dropdown box
                Community[] communities = Community.findAll(context);
                request.setAttribute("community.array", communities);

                qResults = DSQuery.doQuery(context, qArgs);
            }

            // now instantiate the results and put them in their buckets
            for( int i = 0; i < qResults.getHitHandles().size(); i++ )
            {
                String myHandle = (String )qResults.getHitHandles().get(i);
                Integer myType  = (Integer)qResults.getHitTypes().get(i);
                
                // add the handle to the appropriate lists
                switch( myType.intValue() )
                {
                    case Constants.ITEM:
                        itemHandles.add( myHandle );
                        break;
                        
                    case Constants.COLLECTION:
                        collectionHandles.add( myHandle );
                        break;
                        
                    case Constants.COMMUNITY:
                        communityHandles.add( myHandle );
                        break;
                }
            }
            
            int numCommunities = communityHandles.size();
            int numCollections = collectionHandles.size();
            int numItems       = itemHandles.size();
            
            // Make objects from the handles - make arrays, fill them out
            resultsCommunities = new Community [numCommunities];
            resultsCollections = new Collection[numCollections];
            resultsItems       = new Item      [numItems      ];
            
            for (int i = 0; i < numItems; i++)
            {
                String myhandle = (String) itemHandles.get(i);
                
                Object o = HandleManager.resolveToObject(context, myhandle);
                
                resultsItems[i] = (Item)o;
                if (resultsItems[i] == null)
                {
                    throw new SQLException("Query \"" + query +
                        "\" returned unresolvable handle: " + myhandle);
                }
            }

            for (int i = 0; i < collectionHandles.size(); i++)
            {
                String myhandle = (String) collectionHandles.get(i);
                
                Object o = HandleManager.resolveToObject(context, myhandle);
                
                resultsCollections[i] = (Collection)o;
                if (resultsCollections[i] == null)
                {
                    throw new SQLException("Query \"" + query +
                        "\" returned unresolvable handle: " + myhandle);
                }
            }

            for (int i = 0; i < communityHandles.size(); i++)
            {
                String myhandle = (String) communityHandles.get(i);
                
                Object o = HandleManager.resolveToObject(context, myhandle);
                
                resultsCommunities[i] = (Community)o;
                if (resultsCommunities[i] == null)
                {
                    throw new SQLException("Query \"" + query +
                        "\" returned unresolvable handle: " + myhandle);
                }
            }

            // Log
            log.info(LogManager.getHeader(context,
                "search",
                logInfo + "query=\"" + query + "\",results=(" + resultsCommunities.length + "," + resultsCollections.length + "," + resultsItems.length + ")"));
        }
        catch (ParseException pe)
        {
            /*
             * A parse exception means there were some weird characters in
             * the query we couldn't resolve.  We'll pretend the search went
             * OK but with no results for the user, but log the error, since
             * this shouldn't really happen.
             */
            log.warn(LogManager.getHeader(context,
                "search_exception",
                logInfo + "query=\"" + query + "\""),
                pe);

            // Empty results
            resultsItems       = new Item      [0];
            resultsCommunities = new Community [0];
            resultsCollections = new Collection[0];
        }
    	catch (TokenMgrError tme)
        {
            // Similar to parse exception
            log.warn(LogManager.getHeader(context,
                "search_exception",
                logInfo + "query=\"" + query + "\""),
                tme);

            // Empty results
            resultsItems       = new Item      [0];
            resultsCommunities = new Community [0];
            resultsCollections = new Collection[0];
        }

        // Pass in some page qualities
        
        // total number of pages
        int pageTotal  = 1 + (qResults.getHitCount() - 1)/qResults.getPageSize();
        
        // current page being displayed
        int pageCurrent= 1 + (qResults.getStart()/qResults.getPageSize());
        
        // pageLast = min(pageCurrent+9,pageTotal)
        int pageLast   = (pageCurrent + 9) > pageTotal ? pageTotal : (pageCurrent+9);
        
        // pageFirst = max(1,pageCurrent-9)
        int pageFirst  = (pageCurrent - 9) > 1 ? (pageCurrent - 9) : 1;  

        // Pass the results to the display JSP
        request.setAttribute("items",       resultsItems      );
        request.setAttribute("communities", resultsCommunities);
        request.setAttribute("collections", resultsCollections);

        request.setAttribute("pagetotal",   new Integer(pageTotal  ) );
        request.setAttribute("pagecurrent", new Integer(pageCurrent) );
        request.setAttribute("pagelast",    new Integer(pageLast   ) );
        request.setAttribute("pagefirst",   new Integer(pageFirst  ) );

        request.setAttribute("queryresults", qResults );

        // And the original query string
        request.setAttribute("query", query);
        
        if ((fromAdvanced != null) && (qResults.getHitCount() == 0))
        {
        	// send back to advanced form if no results
        	Community[] communities = Community.findAll(context);
        	request.setAttribute("communities", communities);
        	request.setAttribute("no_results", "yes");

			queryHash = qArgs.buildQueryHash(request);
        	Iterator i = queryHash.keySet().iterator();
        	while(i.hasNext())
        	{
            	String key   = (String)i.next();
            	String value = (String)queryHash.get(key);
            	
            	request.setAttribute(key, value);
            }

        	JSPManager.showJSP(request, response, "/search/advanced.jsp");
        } else {
        	JSPManager.showJSP(request, response, "/search/results.jsp");
        }
    }
}
