import java.net.*;
import java.io.*;

public class Client {

    public static void main (String args []) throws Exception {
	String test = System.getProperty ("test");

	if (test == null) {
	    usage ();
	    System.exit (1);
	}
    
	if (test.equalsIgnoreCase ("load")) {
	    if (args.length != 3) {
		usage();
	    }

	    int nMsg = Integer.parseInt(args[1]);
	    int nThread = Integer.parseInt(args[2]);
	    String cmd = args[0];
	    Thread[] ths = new Thread[nThread];

	    for (int i = 0; i < nThread; i ++) {
		ths[i] = new LoadTest(nMsg, cmd);
		ths[i].start();
	    }
	    for (int i = 0; i < nThread; i ++) {
		ths[i].join();
	    }
	} else if (test.equalsIgnoreCase ("functional")) {
	    if (args.length != 0) {
		usage();
	    }
	    new FunctionalTest (args);
	} else {
	    usage ();
	}

	System.exit (1);
    }

    public static void usage () {
	Thread.dumpStack();
	System.out.println 
	    ("usage: java -Dtest=load Client <PUT|GET> <nmsg> <nthread>");
	System.out.println ();

	System.out.println 
	    ("usage: java -Dtest=functional Client");
    
	System.exit(1);
    }

    private static class LoadTest extends Thread {
	int nMsg;
	String cmd;

	LoadTest(int nMsg, String cmd) throws Exception {
	    this.nMsg = nMsg;
	    this.cmd = cmd;
	}

	public void run() {
	    long t1, t2;
	    DbaseLib store = new DbaseLib();

	    try {
		if (cmd.equals ("PUT")) {
		    t1 = System.currentTimeMillis ();

		    for (int i = 0; i < nMsg; i ++) {
			byte[] k = Charset.makeBytes("KEY-" + i);
			byte[] v = Charset.makeBytes("VAL-" + i);
			store.put (k, v);
		    }

		    t2 = System.currentTimeMillis ();
		    System.out.println ("done (time=" + (t2-t1) + ", puts/sec=" + (nMsg / (t2-t1)) * 1000 + ")");
		} else {
		    t1 = System.currentTimeMillis ();

		    for (int i = 0; i < nMsg; i ++) {
			byte[] k = Charset.makeBytes("KEY-" + i);
			byte[] val = store.get (k);
			if (val == null) {
			    System.out.println ("oops " + val);
			}
			String s = Charset.makeString(val, 0, val.length);
			if (! s.equals ("VAL-"+i)) {
			    System.out.println ("oops " + val);
			}
		    }
      
		    t2 = System.currentTimeMillis ();
		    System.out.println ("done (time=" + (t2-t1) + ", gets/secs=" + (nMsg / (t2-t1)) * 1000 + ")");
		}
	    } 
      
	    catch (Throwable t) {
		t.printStackTrace();
	    }
	}
    }

    private static class FunctionalTest {
	BufferedReader bin = new BufferedReader (new InputStreamReader (System.in));

	String input (String quest) throws IOException {
	    System.out.println (quest);
	    String resp = null;

	    while ((resp = bin.readLine ()) == null || resp.length () == 0);
	    return (resp);
	}

	int inputInt (String quest) throws Exception {
	    String s = input(quest);
	    return (Integer.parseInt(s));
	}

	FunctionalTest (String args []) throws Exception {
	    long t1, t2;
	    DbaseLib store = new DbaseLib();

	    while (true) {
		System.out.println ("\nSelect Action: \n" +
				    "Select action :\n" +
				    "\ti) insert 1 record\n" +
				    "\tI) insert N records\n" +
				    "\ts) search 1 record\n" +
				    "\tS) search N records\n" +
				    "\td) delete record\n" +
				    "\tq) quit");
	
		System.out.print ("> ");
		int c = System.in.read ();
	
		String key, val;
		String key2, val2;
		byte[] bkey, bval;
		int N;	
	
		switch (c) {
		case 'i':
		    key = input("Enter key ");
		    val = input("Enter val ");
		    store.put (Charset.makeBytes(key), Charset.makeBytes(val));
		    System.out.println ("object inserted");
		    break;

		case 'I':
		    key = input("Enter key ");
		    val = input("Enter val ");
		    N = inputInt("Enter Number ");
	  
		    t1 = System.currentTimeMillis();
		    for (int j = 0; j < N; j ++) {
			key2 = key + j;
			val2 = val + j;
			store.put (Charset.makeBytes(key2), Charset.makeBytes(val2));
		    }
		    t2 = System.currentTimeMillis();
		    System.out.println (N + " objects inserted in " + (t2 - t1) + " millis.");
		    break;
	  
		case 's':
		    key = input("Enter key ");
		    bval = store.get(Charset.makeBytes(key));
		    if (bval != null) {
			System.out.println ("found " + Charset.makeString(bval, 0, bval.length));
		    } else {
			System.out.println ("not found");
		    }
		    break;
	  
		case 'S':
		    key = input("Enter key ");
		    val = input("Enter val ");
		    N = inputInt("Enter Number ");

		    t1 = System.currentTimeMillis();
		    for (int i = 0; i < N; i ++) {
			key2 = key + i;
			bval = store.get (Charset.makeBytes(key2));
			if (bval == null || ! (Charset.makeString(bval, 0, bval.length)).equals(val + i)) {
			    System.out.println(key2 + " not found");
			}
		    }

		    t2 = System.currentTimeMillis();
		    System.out.println (N + " objects retrieved in " + (t2 - t1) + " millis.");
		    break;

		case 'd':
		case 'D':
		    key = input("Enter key ");
		    store.remove (Charset.makeBytes(key));
		    System.out.println ("record deleted");
		    break;
	  
		case 'q':
		case 'Q':
		    System.out.println ("closed");
		    System.exit (1);

		default: continue;
		}
	    }
	}
    }
}
