import java.io.*;

import org.codehaus.jackson.*;
import org.codehaus.jackson.io.IOContext;
import org.codehaus.jackson.io.UTF8Reader;
import org.codehaus.jackson.map.JavaTypeMapper;
import org.codehaus.jackson.map.JsonTypeMapper;
import org.codehaus.jackson.util.BufferRecycler;

// json.org's reference implementation
import org.json.*;
// StringTree implementation
import org.stringtree.json.JSONReader;
// Jsontool implementation
import com.sdicons.json.parser.JSONParser;
// Noggit:
//import org.apache.noggit.JSONParser;

public final class TestJsonPerf
{
    private final static int REPS = 2500;

    private final static int TEST_PER_GC = 5;

    final JsonFactory mJsonFactory;

    final byte[] mData;

    protected int mBatchSize;

    public TestJsonPerf(File f)
        throws Exception
    {
        mJsonFactory = new JsonFactory();
        mData = readData(f);

        System.out.println("Read "+mData.length+" bytes from '"+f+"'");
        System.out.println();
    }

    public void test()
        throws Exception
    {
        int i = 0;
        int sum = 0;

        while (true) {
            try {  Thread.sleep(100L); } catch (InterruptedException ie) { }
            // Use 7 to test all...
            int round = (i++ % 2);
            
            long curr = System.currentTimeMillis();
            String msg;
            boolean lf = false;

            switch (round) {
            case 0:
                msg = "Jackson, stream";
                sum += testJacksonStream(REPS);
                break;
            case 1:
                lf = true;
                msg = "Noggit";
                sum += testNoggit(REPS);
                break;
            case 2:
                msg = "Jackson, Java types";
                sum += testJacksonJavaTypes(REPS);
                break;
            case 3:
                msg = "Jackson, JSON types";
                sum += testJacksonJavaTypes(REPS);
                break;
            case 4:
                msg = "Json.org";
                sum += testJsonOrg(REPS);
                break;
            case 5:
                msg = "JSONTools (berlios.de)";
                sum += testJsonTools(REPS);
                break;
            case 6:
                msg = "StringTree";
                sum += testStringTree(REPS);
                break;
            default:
                throw new Error("Internal error");
            }

            curr = System.currentTimeMillis() - curr;
            if (lf) {
                System.out.println();
            }
            System.out.println("Test '"+msg+"' -> "+curr+" msecs ("
                               +(sum & 0xFF)+").");


            if ((i % TEST_PER_GC) == 0) {
                System.out.println("[GC]");
                try {  Thread.sleep(100L); } catch (InterruptedException ie) { }
                System.gc();
                try {  Thread.sleep(100L); } catch (InterruptedException ie) { }
            }
        }
    }

    private final byte[] readData(File f)
        throws IOException
    {
        int len = (int) f.length();
        byte[] data = new byte[len];
        int offset = 0;
        FileInputStream fis = new FileInputStream(f);
        
        while (len > 0) {
            int count = fis.read(data, offset, len-offset);
            offset += count;
            len -= count;
        }

        return data;
    }

    protected int testJsonOrg(int reps)
        throws Exception
    {
        Object ob = null;
        for (int i = 0; i < reps; ++i) {
            // Json.org's code only accepts Strings:
            String input = new String(mData, "UTF-8");
            JSONTokener tok = new JSONTokener(input);
            ob = tok.nextValue();
        }
        return ob.hashCode();
    }

    protected int testJsonTools(int reps)
        throws Exception
    {
        Object ob = null;
        for (int i = 0; i < reps; ++i) {
            // Json-tools accepts streams, yay!
            JSONParser jp = new JSONParser(new ByteArrayInputStream(mData), "byte stream");
            /* Hmmmh. Will we get just one object for the whole thing?
             * Or a stream? Seems like just one
             */
            //while ((ob = jp.nextValue()) != null) { ; }
            ob = jp.nextValue();
        }
        return ob.hashCode();
    }

    protected int testStringTree(int reps)
        throws Exception
    {
        Object ob = null;
        for (int i = 0; i < reps; ++i) {
            // StringTree impl only accepts Strings:
            String input = new String(mData, "UTF-8");
            ob = new JSONReader().read(input);
        }
        return ob.hashCode();
    }

    protected int testNoggit(int reps)
        throws Exception
    {
        ByteArrayInputStream bin = new ByteArrayInputStream(mData);

        char[] cbuf = new char[mData.length];

        IOContext ctxt = new IOContext(new BufferRecycler(), this);
        int sum = 0;

        for (int i = 0; i < reps; ++i) {
            /* This may be unfair advantage (allocating buffer of exact
             * size)? But let's do that for now
             */
            //char[] cbuf = new char[mData.length];
            //InputStreamReader r = new InputStreamReader(bin, "UTF-8");
            byte[] bbuf = ctxt.allocReadIOBuffer();
            UTF8Reader r = new UTF8Reader(ctxt, bin, bbuf, 0, 0);

            bin.reset();
            org.apache.noggit.JSONParser jp = new org.apache.noggit.JSONParser(r, cbuf);
            int type;
            while ((type = jp.nextEvent()) != org.apache.noggit.JSONParser.EOF) {
                if (type == org.apache.noggit.JSONParser.STRING) {
                    sum += jp.getString().length();
                }
            }
        }
        return sum;
    }

    protected int testJacksonStream(int reps)
        throws Exception
    {
        int sum = 0;
        for (int i = 0; i < reps; ++i) {
            JsonParser jp = mJsonFactory.createJsonParser(new ByteArrayInputStream(mData));
            JsonToken t;
            while ((t = jp.nextToken()) != null) {
                // Field names are always constructed
                if (t == JsonToken.VALUE_STRING) {
                    sum += jp.getText().length();
                }
            }
            jp.close();
        }
        return sum;
    }

    protected int testJacksonJavaTypes(int reps)
        throws Exception
    {
        Object ob = null;
        JavaTypeMapper mapper = new JavaTypeMapper();
        for (int i = 0; i < reps; ++i) {
            JsonParser jp = mJsonFactory.createJsonParser(new ByteArrayInputStream(mData));
            ob = mapper.read(jp);
            jp.close();
        }
        return ob.hashCode(); // just to get some non-optimizable number
    }

    protected int testJacksonJsonTypes(int reps)
        throws Exception
    {
        Object ob = null;
        JsonTypeMapper mapper = new JsonTypeMapper();
        for (int i = 0; i < reps; ++i) {
            JsonParser jp = mJsonFactory.createJsonParser(new ByteArrayInputStream(mData));
            ob = mapper.read(jp);
            jp.close();
        }
        return ob.hashCode(); // just to get some non-optimizable number
    }

    public static void main(String[] args)
        throws Exception
    {
        if (args.length != 1) {
            System.err.println("Usage: java ... <file>");
            System.exit(1);
        }
        new TestJsonPerf(new File(args[0])).test();
    }
}

