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

public class RobotClient1 extends Thread{
    static final String _FS    = "\u001c";
    static final String _CRLF  = "\r\n";
    private String host = "127.0.0.1";
    private int    port = 80;
    private Socket       sock ;
    private BufferedWriter out = null;
    private BufferedReader in  = null;
    private int  icards[]       = new int[13];
    private Card rcards[]       = new Card[13];
    private String       header= "POST /gamehandler HTTP/1.0\r\nContent-Type: text/hearts-message\r\nConnection: Keep-Alive\r\nContent-Length: ";
    private String       name;
    private static final int _DISPLAY13CARDS = 1;
    private static final int _SEND_3_CARDS   = 2;
    private static final int _PICK_A_CARD    = 3;
    private static final boolean no_stdout   = true;

    public void setHostPort(String h, int p) {
        host = h;
        port = p;
    }


/*
    public RobotClient1(String name, String host, int port, boolean st_robot) {
        this(name, host, port);
        startrobot = st_robot;
    }
*/
    public RobotClient1(String name, String host, int port) {
        this.name = name;
        setHostPort(host, port);
        try{
            sock = new Socket(host, port);
            in   = new BufferedReader(new InputStreamReader(sock.getInputStream()));
            out  = new BufferedWriter(new OutputStreamWriter(sock.getOutputStream()));
        }
        catch(IOException e) {
            System.out.println( e );
            System.exit(1);
        }

        start();
    }


    private String readResponse() throws IOException  {
        boolean read_finished = false;
        StringBuffer sb       = new StringBuffer();
        String  response      = "";

        if(in != null) {
            try {
                while(!read_finished) {
                    response = in.readLine();
                    if(response.equals("")) {
                        read_finished = true;
                        response = in.readLine();
                    }
                }
            }
            catch(IOException e) { throw e; }
        }
        else throw new IOException("InputStream is null");

        return response;
    }

    private boolean sendRequest(String request) throws IOException {

        if(!request.endsWith("\n")) request += "\n";

        if(out != null) {
            try {
                StringBuffer sb = new StringBuffer(header);
                sb.append(request.length()).append("\r\n\r\n").append(request);
                out.write(sb.toString()); // send request
                if(!no_stdout) System.out.print("[" + sb.toString() + "]");
                out.flush();              // flush the stream
            }
            catch(IOException ie) {
                out = null;
                throw ie;
            }
        }
        return true;
    }


    public int parseMessage(String msg) {
        if(!no_stdout) System.out.println("message is " + msg);
        StringTokenizer st = new StringTokenizer(msg, _FS);
        Vector vc = new Vector();
        while(st.hasMoreTokens()) {
            vc.addElement(st.nextToken());
        }

        String element1 = "";
        String element2 = "";
        String element3 = "";
        String element4 = "";
        String element5 = "";

        int vcsize = vc.size();

        if(vcsize >= 1) element1 = (String) vc.elementAt(0);
        if(vcsize >= 2) element2 = (String) vc.elementAt(1);
        if(vcsize >= 3) element3 = (String) vc.elementAt(2);
        if(vcsize >= 4) element4 = (String) vc.elementAt(3);
        if(vcsize >= 5) element5 = (String) vc.elementAt(4);

        if(element1.equals(" D")) return _PICK_A_CARD;
        if(element1.equals(" C")) {
            System.out.println("Passing 3 Cards Message : " + msg);
            return _SEND_3_CARDS;
        }
        if(element1.equals(" B") && element3.equals("H") && element4.equals("U") && element5.equals("13"))
        {
            return _DISPLAY13CARDS;
        }

        if(element1.equals(" G"))
        {
            System.out.println(" ******************* Scores are : " + msg);
        }
        if(element1.equals(" F"))
        {
            System.out.println(" ******************* Winner is : " + msg);
            try {
                System.out.println("\u0007");
                System.out.println("waiting to restart game");
                System.out.println("\u0007");

                sleep(30000);
                sendRequest(" 4"+_FS+ name + _CRLF);
            }
            catch(InterruptedException ie) {
            }
            catch(IOException e) {
                System.out.println(e);
                System.exit(1);
            }
        }


        return -1;
    }


    private boolean send3Cards() {

        StringBuffer msg = new StringBuffer(" 2");
        msg.append(_FS).append(rcards[0].getRankSuit()).append(_FS).append(rcards[1].getRankSuit());
        msg.append(_FS).append(rcards[2].getRankSuit()).append(_CRLF);
        try {
            sendRequest(msg.toString());
        }
        catch(IOException e) {
            System.out.println(e);
            System.exit(1);
        }

        return true;
    }

    private boolean sendACards(Card c) {

        StringBuffer msg = new StringBuffer(" 2");
        msg.append(_FS).append(c.getRankSuit()).append(_CRLF);
        try {
            System.out.println("Client Sending [" + msg.toString() +"]" );
            sendRequest(msg.toString());
        }
        catch(IOException e) {
            System.out.println(e);
            System.exit(1);
        }

        return true;
    }

    public void saveCards(String msg) {
        StringTokenizer st = new StringTokenizer(msg, _FS);
        Vector vc = new Vector();
        while(st.hasMoreTokens()) {
            vc.addElement(st.nextToken());
        }
        for(int i=0; i<13; i++) {
            rcards[i] = new Card((String)vc.elementAt(i+5));
            System.out.print((String)vc.elementAt(i+5) + ", ");
        }
        System.out.println();
    }

    private boolean pickACard(String msg) {

        if(!no_stdout) System.out.println("In pick a Card " + msg );
        StringTokenizer st = new StringTokenizer(msg, _FS);
        Vector vc = new Vector();
        while(st.hasMoreTokens()) {
            vc.addElement(st.nextToken());
        }

        String constraint = "";
        String rank_suit  = "";
        String csuit      = "";

        int vcsize = vc.size();

        if(vcsize >= 3) constraint = (String) vc.elementAt(2);
        if(vcsize >= 4) {
            rank_suit  = (String) vc.elementAt(3);
            csuit = rank_suit.substring(1);
            //if(!no_stdout)
            System.out.println("Constraint => " + rank_suit + "<=>"+ csuit);
        }

        for(int i=0; i<13; i++)
         if(rcards[i] == null ) System.out.print("0, ");
         else System.out.print(rcards[i].getRankSuit()+", ");
        System.out.println();

        if(constraint.equals("M")) {
            if(rank_suit.indexOf("*") >= 0) {
                for(int i=0; i<13; i++)
                    if(rcards[i] != null && csuit.equals(rcards[i].getSuit())) {
                        System.out.println(" Find Card " + rcards[i].getRankSuit());
                        sendACards(rcards[i]);
                        rcards[i] = null;
                        break;
                    }
            }
            else {
                for(int i=0; i<13; i++) {
                    if(rcards[i] != null && rcards[i].getRankSuit().equals(rank_suit)) {
                        //if(!no_stdout)
                        System.out.println(" Find Card " + rcards[i].getRankSuit());
                        sendACards(rcards[i]);
                        rcards[i] = null;
                        break;
                    }
                }
            }
        }
        else if(constraint.equals("N")) {
            for(int i=0; i<13; i++) {
                if(rcards[i] != null && !csuit.equals(rcards[i].getSuit())) {
                    if(!no_stdout) System.out.println(" Find Card " + rcards[i].getRankSuit());
                    sendACards(rcards[i]);
                    rcards[i] = null;
                    break;
                }
            }
        }
        else { // no constraint
            for(int i=0; i<13; i++) {
                if(rcards[i] != null) {
                    if(!no_stdout) System.out.println(" Find Card " + rcards[i].getRankSuit());
                    sendACards(rcards[i]);
                    rcards[i] = null;
                    break;
                }
            }
        }

        return true;
    }

    public void run() {
        int    i        = 0;
        String response = "";


        StringBuffer login = new StringBuffer(" 1");
        login.append(_FS).append(name).append(_CRLF);
        try {
            sendRequest(login.toString());

            sleep(5000);
            sendRequest(" 6"+_CRLF);             // start robot player

        }
        catch(InterruptedException ie) {

        }
        catch(IOException e) {
            System.out.println(e);
            System.exit(1);
        }


        int state ;
        while( true ) {
            try {
                this.sleep(200);
                response = readResponse();
                if(!no_stdout) System.out.println(response);

                state = parseMessage(response);

                switch(state) {
                    case _DISPLAY13CARDS:
                        saveCards(response);
                        break;
                    case _SEND_3_CARDS:
                        send3Cards();
                        break;
                    case _PICK_A_CARD:
                        pickACard(response);
                }


            }
            catch(IOException ioe) {
                System.out.println(ioe);
                System.exit(1);
            }
            catch(InterruptedException ie ) {
                System.out.println(ie);
                System.exit(1);
            }
        }
    }

    public static void main(String argv[]) {
        String host;
        int    port ;

        if(argv.length <= 2) {
            System.out.println("Usage : RobotClient1 [player name] [host] [port] ");
            System.exit(1);
        }
        host = argv[1];
        port = Integer.parseInt(argv[2]);
        RobotClient1 rc = new RobotClient1(argv[0], host, port);
    }

}