package se.six.cs.proto.cub;

import com.sun.grizzly.*;

import java.net.InetSocketAddress;
import java.nio.ByteBuffer;
import java.nio.channels.SelectionKey;

/**
 * Created by IntelliJ IDEA.
 * User: erik
 * Date: Jan 21, 2008
 * Time: 1:35:41 PM
 * To change this template use File | Settings | File Templates.
 */
public class Client {

  private String host;
  private int port;

  private TCPConnectorHandler connector_handler;
  private Controller controller;
  private TCPSelectorHandler tcp_selector_handler;

  private ByteBuffer buf = ByteBuffer.allocate(100);

  public static void main(String[] args) {
    Client c = new Client();
    c.execute(args);
  }

  public void execute(String[] args) {
    long elapsed = 0;
    int repeats = 0;

    for (int i = 0; i < args.length; i++) {
      if (args[i].equals("-h")) {
        // host
        host = args[++i];
      } else if (args[i].equals("-p")) {
        // port
        port = Integer.parseInt(args[++i]);
      } else if (args[i].equals("-r")) {
        repeats = Integer.parseInt(args[++i]);
      }
    }
    if (port == 0 ||host == null ) {
      System.out.println("No port or host set");
      System.exit(1);
    }
    if (repeats == 0) {
      System.out.println("No nr of repeats given. Will default to 10");
      repeats = 10;
    }

    controller  = new Controller();
    tcp_selector_handler = new TCPSelectorHandler(true); // true to get client
    controller.addSelectorHandler(tcp_selector_handler);

    controller.addStateListener(new ControllerStateListenerAdapter() {
      public void onException(Throwable e) {
        System.out.println("Grizzly controller exception:"+e.getMessage());
      }

      public void onReady() {
        System.out.println("Ready!");
      }

      public void onStarted() {
        System.out.println("Controller started!");
      }

    });

    new Thread(controller).start();
    synchronized(this) {
      try {
          wait(30000);
      } catch(Exception e) {
        System.out.println("Timeout in wait"+e.getMessage());
      }
    }

    connector_handler =(TCPConnectorHandler) controller.acquireConnectorHandler(Controller.Protocol.TCP);

    System.out.println("Thread is started.? "+(controller.isStarted() ? "Yes" : "No"));
    try {
      byte[] filler = new byte[92];

      for (int i = 0; i< filler.length; i++) {
        filler[i] = 2;
      }

      // this is how I want to do it and with my patch I can...
      //connector_handler.connect(new InetSocketAddress(host,port));

      connector_handler.connect(new InetSocketAddress(host,port), new CallbackHandler<Context>() {
        public void onConnect(IOEvent<Context> e) {
          SelectionKey k = e.attachment().getSelectionKey();
          System.out.println("Callbackhandler: OnConnect...");
          try {
            connector_handler.finishConnect(k);
          } catch(Exception ex) {
            System.out.println("exception in CallbackHandler:"+ex.getMessage());
          }

          e.attachment().getSelectorHandler().register(k,
                  SelectionKey.OP_READ);
        }

        public void onRead(IOEvent<Context> e) {
          System.out.println("Callbackhandler: OnRead...");
        }

        public void onWrite(IOEvent<Context> e) {
          System.out.println("Callbackhandler: OnWrite...");          
        }

      });

      int ctr = 0;
      while (ctr < repeats) {
        buf.putLong(System.nanoTime());
        buf.put(filler);
        buf.flip();
        long size = connector_handler.write(buf,true);
        buf.clear();
        connector_handler.read(buf,true);
        elapsed += System.nanoTime() - buf.getLong();
        buf.clear();
        ctr++;
      }
      System.out.println(""+repeats+" run at a total of "+elapsed/1000+" microseconds. Per packet it comes down to "+(elapsed/repeats)/1000+
              " microseconds per roundtrip.");
      connector_handler.close();
      controller.stop();
    } catch(Exception e) {
      System.out.println("Exception in execute..."+e);
      e.printStackTrace(System.out);
    }
  }

}