package com.lumos.lucene.index;

import java.io.*;
import java.util.*;

import org.apache.lucene.analysis.*;
import org.apache.lucene.document.*;
import org.apache.lucene.search.*;
import org.apache.lucene.queryParser.*;
import org.apache.lucene.store.*;

/**
 *
 */
public final class RBench
{
	/**
	 *
	 */
	private RBench()
	{
	}

	/**
	 *
	 */
	public static void main(String[] args)
		throws Throwable
	{
		String srch = null;
		String indexName = "index";
		boolean ram = false;
		int its = 10;
			
		for ( int i = 0 ; i< args.length; i++)
		{
			if ( args[ i].equals( "-i"))
				indexName = args[ ++i];
			else if ( args[ i].equals( "-ram"))
				ram = true;
			else if ( args[ i].equals( "-its"))
				its = Integer.parseInt( args[ ++i]);
			else
			{
				o.println( "Hmm? " + args[ i]);
				System.exit( 2);
			}
		}
		int numDocs = 0;
		long size = 0;
			
		long t1 = System.currentTimeMillis();
		if ( ram)
		{
			o.print( "Ramming..."); o.flush();
			Directory tmp = FSDirectory.getDirectory( indexName, false);
			RAMDirectory ramd = new RAMDirectory( tmp);
			tmp.close();
			searcher = new IndexSearcher( ramd);
			//o.println( "" + ramd.numDocs() + " docs");
		}
		else
		{
			o.println( "FSing..");
			Directory tmp = FSDirectory.getDirectory( indexName, false);			
			searcher = new IndexSearcher( tmp);
			//o.println( "" + tmp.numDocs() + " docs");			
		}
		o.println();		
		long dt = System.currentTimeMillis() - t1;
		o.println( "Startup:: "+ dt);




		final Runtime r = Runtime.getRuntime();
		System.gc();
		o.println( "free :: " + prettyBytes( r.freeMemory()));
		o.println( "total:: " + prettyBytes( r.totalMemory())); 				
		benchmark2( its);
		System.gc();
		o.println( "free :: " + prettyBytes( r.freeMemory()));
		o.println( "total:: " + prettyBytes( r.totalMemory())); 
		System.exit( 0);
	}

	/**
	 *
	 */
	private static void benchmark2( int its)
		throws Throwable
	{
		long min = 0;
		long max = 0;
		long tot =0;
		String[] queries =; // put in queries here - this line won't compile and that's intentional
		for ( int i = 0; i< its; i++)
		{
			long t1 = System.currentTimeMillis();
			once2( queries[ i % queries.length]);
			long t2 = System.currentTimeMillis();
			long dt = t2-t1;
			if ( i == 0) { min = max = dt; }
			else
			{
				min= Math.min( min, dt);
				max = Math.max( max, dt);
			}
			tot += dt;
			o.println( "dt=" + (t2-t1));
		}
		o.println( "min:: "+ min);
		o.println( "max:: "+ max);
		o.println( "avg:: "+ ((tot+(its/2))/its));

	}

	/**
	 * Benchmark worker.
	 */
	private static void once2( String srch)
		throws Throwable
	{
		final Analyzer analyzer = new StopAnalyzer();		
		Query query = QueryParser.parse(srch, DFields.CONTENTS, analyzer);
		
		Hits hits = searcher.search(query);
		int matches = hits.length();
		o.println( "matches=" + matches+ " for " + srch);
		o.println( "Query: " + query.toString( ""));					

		double max = 0;
		for ( int i = 0; i < matches; i++)
		{
			Document d		= hits.doc( i);
			double score	= hits.score( i);
			if ( max < 0) max = score;

			double pc = score/max * 100.0;

			Enumeration e = d.fields();
			while ( e.hasMoreElements())
			{
				Field z = (Field) e.nextElement();
				String name = z.name();
			}
		}
	}

	/**
     * Fair division taking rounding into account.
     */
    public static long fairDivide( long a, long b)
    {
		if ( b == 0)
			return a;
        a += (b/2);
        return a/b;
    }

	public static String prettyBytes( int bytes)
	{
		return prettyBytes( (long) bytes);
	}
	
	public static String prettyBytes( long bytes)
    {
        if ( bytes <= 1024)
            return "" + bytes;
        else if ( bytes < MB)
        {
            // convert to kb
            bytes = fairDivide( bytes, 1024);

            return "" + bytes + "kb";
        }
		else if ( bytes < GB)
        {
            bytes = fairDivide( bytes, MB);
            return "" + bytes + "MB";
        }
		else
		{
            bytes = fairDivide( bytes, GB);
            return "" + bytes + "GB";			
		}
    }
	
	private static PrintStream o = System.out;
	private static Searcher searcher;
    private static final long MB = (1024 * 1024);
    private static final long GB = (1024 * MB);	
}
