/*
    WUMP (specifically BUMP) in java. starter file
 */
import java.lang.*;     //pld
import java.net.*;      //pld
import java.io.*;
import wumppkt;         // be sure wumppkt.java is in your current directory
//import java.io.Externalizable;

public class wclient {

    //public wclient () {}

    // The following is useful if you run this from a dynamic console.
    // But don't do that.
    static public void winwait() {
        byte ch[] = new byte[1];
        try {
            System.in.read(ch);
        } catch (IOException ioe) {
            return;
        }
    }

    static wumppkt wp = new wumppkt();    // stupid inner-class nonsense

    //============================================================
    //============================================================

    static public void main(String args[]) {
        int destport = wumppkt.SERVERPORT;
        //String filename = args[0];
        //String desthost = args[1]; //"ulam.math.luc.edu";
        String desthost = "ulam.math.luc.edu";
        String filename = "vanilla";
        int winsize = 1;                // default

        DatagramSocket s;
        try {
            s = new DatagramSocket();
        }
        catch (SocketException se) {
            System.err.println("no socket available");
            return;
        }

        try {
            s.setSoTimeout(wumppkt.INITTIMEOUT);       // time in milliseconds
        } catch (SocketException se) {
            System.err.println("socket exception: timeout not set!");
        }

       if (args.length != 2) {
            System.err.println("usage: wclient filename  [winsize [hostname]]");
            //exit(1);
        }

        if (args.length >= 1) filename = args[0];
        if (args.length >= 2) winsize = (new Integer(args[1])).intValue();
        if (args.length >= 3) desthost = args[2];

        InetAddress dest;
        System.err.print("Looking up address of " + desthost + "...");
        try {
            dest = InetAddress.getByName(desthost);
        }
        catch (UnknownHostException uhe) {
            System.err.println("unknown host: " + desthost);
            return;
        }
        System.err.println(" got it!");

        wumppkt.REQ req = wp.new REQ(wumppkt.BUMPPROTO, winsize, filename); // ctor for REQ

        System.err.println("req size = " + req.size() + ", filename=" + req.filename());

        DatagramPacket reqDG
            = new DatagramPacket(req.write(), req.size(), dest, destport);
        try {s.send(reqDG);}
        catch (IOException ioe) {
            System.err.println("send() failed");
            return;
        }

        //============================================================

        // now receive the response
        DatagramPacket replyDG            // we don't set the address here!
            = new DatagramPacket(new byte[wumppkt.MAXSIZE] , wumppkt.MAXSIZE);
        DatagramPacket ackDG = new DatagramPacket(new byte[0], 0);
        ackDG.setAddress(dest);

        short block = 1;
        long starttime = System.currentTimeMillis();
        long sendtime = starttime;

        wumppkt.DATA data = wp.new DATA();
        wumppkt.ACK  ack  = wp.new ACK(0);

        int proto;        // for proto of incoming packets
        int opcode;

        //============================================================

        while (true) {
            // get packet
            try {
                s.receive(replyDG);
            }
            catch (InterruptedIOException iioe) {
                System.err.println("Response timed out!");
                return;
            }
            catch (IOException ioe) {
                System.err.println("receive() failed");
                return;
            }

            byte[] replybuf = replyDG.getData();
            proto = wumppkt.proto(replybuf);
            opcode = wumppkt.opcode(replybuf);

            data = wp.new DATA(replyDG.getData(), replyDG.getLength());

            System.err.print("received packet of length = " + replyDG.getLength());
            System.err.print("; proto = ");
            System.err.print(wumppkt.proto(replyDG.getData()));
            System.err.print("; opcode=");
            System.err.print(wumppkt.opcode(replyDG.getData()));
            System.err.print("; block# = ");
            System.err.print(data.blocknum());
            System.err.print("; port =");
            System.err.print(replyDG.getPort());
            System.err.print("; host=");
            System.err.print(replyDG.getAddress().toString());
            System.err.print("; time = ");
            System.err.print(System.currentTimeMillis()-starttime);
            System.err.println();

            // check port, packet size, type, block, etc
	    // latch on to port, if block == 1

            // send ack
            ack = wp.new ACK(wumppkt.BUMPPROTO, block);
            ackDG.setData(ack.write());
            ackDG.setLength(ack.size());
            try {s.send(ackDG);}
            catch (IOException ioe) {
                System.err.println("send() failed");
                return;
            }
            sendtime = System.currentTimeMillis();

            //write data
	    // exit if data size is < 512

            block++;
        } // while
        //winwait();
    }
}
