/* Filename             : clientwindow.java
* Version               : Beta V1.0
* Author                : Dr. Roger Webster
* This client is designed around the GameServer and client classes. 
* This means that the server only supports a few 
* functions.  The client must take care of pretty much everything. 
* This allows them to be very flexible and even allows the possiblity 
* of playing multiple types of games with the same GameServer.
* This provides the ability to to create an arbitrary game and 
* still use the same network functionality.
*/
import java.applet.*;
import java.awt.*;
import java.net.*;
import java.util.Vector;

class clientwindow extends Frame implements Runnable
{ 
        static final int PLAYER1 = 1;                   
        static final int PLAYER2 = 2;
        private GameClient gclient = new GameClient();
        private String text, opponent_temp;
        private Vector id_vector = new Vector(1,1);  
        private boolean game_on = false;                                 
        private boolean move_received = false;           
        private boolean finish = false;                                  
        private boolean challenged = false;              
        private int player = PLAYER1;           // who is player 1
        private int other_player = PLAYER2;     // who is player 2
        private int opponent_id;                // store id of opponent
        private int personal_id;                // store your id
        private String nextMoveBuffer;  // store next move made

        private URL base;                       
        private int port;       
        private Thread thread;          
        private int battle_id;

        private Label userlabel;
        private Label userlabel2;
        private Label userlabel3;
        private Panel mypanel;
        private String Username;        
        private List user_list;                 
        private TextArea textArea;              
        private TextField textField;            
        private Color bk_color;
        private Color fg_color;
        private Color bx_color;
        private boolean statusflag = false;     
        private Image gameimage;
        private GraphicPanel gp;
        private Game mygame;            // User fills this class in
        Applet myapplet;

clientwindow(Applet theapplet, URL base_url, int theport, String
User,Image image) 
{
                myapplet = theapplet;
                base = base_url;  
                port = theport;
                Username = User;
                gameimage = image;
                int framewidth = 410;
                int frameheight = 540;
        
                bk_color = new Color(90,90,90);
                fg_color = new Color(255,206,140);
                bx_color = new Color(2,29,15);

                this.setSize(framewidth,frameheight);                           
                this.setTitle("Scrabble Communications Window");
                this.setBackground(Color.black);
                this.setForeground(Color.black);
                this.setLayout(null);
                
                gp = new GraphicPanel(gameimage); 
                gp.setLocation(60, 30);
                gp.setSize(300,100);
                this.add(gp);

        //      userlabel = new Label();
        //      userlabel.setText(" " + User);
        //      userlabel.setFont(new Font("Helvetica",Font.PLAIN,16));
        //      userlabel.setForeground(Color.white);
        //      userlabel.setBackground(Color.black);
        //      userlabel.setLocation(framewidth / 4, 70);
        //      userlabel.setSize(100,30);
        //      this.add(userlabel);

                mypanel = new Panel();
                mypanel.setLayout(new BorderLayout());

                userlabel2 = new Label();
                userlabel2.setText("      List of Players Waiting -> to Play Double Click One");
                userlabel2.setFont(new Font("Helvetica",Font.PLAIN,16));
                userlabel2.setForeground(Color.white);
                userlabel2.setBackground(Color.black);
                mypanel.add(userlabel2, BorderLayout.NORTH);
        
                user_list=new List();
                user_list.setBackground(Color.blue);
                user_list.setForeground(Color.white);
                mypanel.add(user_list, BorderLayout.CENTER);

                mypanel.setLocation(4, 135);
                mypanel.setSize(framewidth-5,200);
                this.add(mypanel);
        
                userlabel3= new Label();
                userlabel3.setText("  Type in red box below & hit c/r to send msg to Opponent");
                userlabel3.setFont(new Font("Helvetica",Font.PLAIN,16));
                userlabel3.setForeground(Color.white);
                userlabel3.setBackground(Color.black);
                userlabel3.setLocation(1, 340);
                userlabel3.setSize(framewidth,30);
                this.add(userlabel3);

                textField=new TextField(41);
                textField.setFont(new Font("Helvetica",Font.PLAIN,16));
                textField.setBackground(Color.red);
                textField.setForeground(Color.white);
                textField.setLocation(1, 370);
                textField.setSize(framewidth,30);       
                this.add(textField);

                textArea=new TextArea(41,8);
                textArea.setFont(new Font("Helvetica",Font.PLAIN,14));
                textArea.setBackground(Color.white);
                textArea.setForeground(Color.black);
                textArea.setEditable(false);
                textArea.setLocation(1, 400);
                textArea.setSize(framewidth,100);

                this.add(textArea);

                this.setSize(framewidth, frameheight);
                this.show(); 
                this.start(); // start this thread via contructor
}

// gets the thread going
public void start() 
{
        System.out.println("starting thread");
        thread = new Thread(this,"main");
        thread.start();
}

public void run() 
{
        System.out.println("RUN ing thread");
   
        display("Trying to connect to socket...\n");
        System.out.println("server port is " + port);
        System.out.println("URL is " + base.getHost());
        statusflag = gclient.connect(base.getHost(),port);
       if (!statusflag) 
        {
                display("Unable to to connect, GameServer is probably down...\n");
        }
        else
        {       
                display ("Connected to Socket!!!\n");
                String textstream = Username;
                gclient.send_stream("!!name!!" +textstream);      
                System.out.println("gclient.send_stream username sent is " + textstream);
        }

        while (true) 
        {
   
                try{thread.sleep(50);}  
                catch(InterruptedException e){}

        if (gclient.running()) 
                        continue;       
        if (gclient.input_stream_available()) 
                {
                        text = gclient.get_input();
                        if (gclient.is_nameslist(text))
                                write_list(text.substring(9)); 
                        if (gclient.is_directive(text)) 
                                processDirective(text.substring(13)); 
                        if (!gclient.is_directive(text) && !gclient.is_nameslist(text))
                                display(text);          
         }
        }
}

// If directive, deal with it according to the message that is attached
public void processDirective(String text) 
{

        String temp;
        int next, temp_id, opp_id;
        temp = text;    
        text = text.substring(6);
        char next_char;

        // if the directive is a challenge...

        if (temp.startsWith("chlng")) 
        {
                next = text.indexOf(',');
                temp = text.substring(0,next);
                if (!game_on) 
                {
                opponent_id = Integer.parseInt(temp);
                text = text.substring(next+1);
                temp = text.substring(0);
                opponent_temp = temp.trim();
                player = PLAYER2;
                other_player = PLAYER1;
                challenged = true;
                display("You have been asked to Play by "+ temp);
                display("hit the 'Play Opponent' button to Play\n");
                        AcceptWindow accept = 
                                new AcceptWindow(this, "Do You Want to Play ", temp);
                }
                else 
                {
                opp_id = Integer.parseInt(temp);
                temp_id = id_vector.indexOf(new Integer(opp_id));
                        battle_id = id_vector.indexOf(new Integer(opp_id));
                gclient.send_stream("!!directive!!mssge,busy|"+Integer.toString(temp_id+1)+"|");
                }           
        }


        // if the directive is a message...
        if(temp.startsWith("mssge")) 
        {
                if (text.startsWith("uid")) 
                {                         
                        temp = text.substring(4);
                        personal_id = Integer.parseInt(temp.trim());
                }
                if (text.startsWith("busy"))                      
                   display ("That player is currently playing a game...\n");               
                if (text.startsWith("surrender"))
                {                 
                   display("Your opponent has surrendered\n");
                   game_on = false;
                }
        }

        // if directive is an accept challenge...
        if(temp.startsWith("accpt") && !challenged) 
        {
                next = text.indexOf(',');
                temp = text.substring(0,next);
                temp_id = Integer.parseInt(temp.trim());
                if(temp_id == opponent_id) 
                {               
                        text = text.substring(next+1);
                        game_on = true;
                        player = PLAYER1;
                        other_player = PLAYER2;
                        challenged = false;
                        display("GAME ON!! you go first\n");
                      mygame = new Game(myapplet, base, this, true, gameimage);

                }       
        }

        // if directive is a move
        if(temp.startsWith("pmove")) 
        {
                next = text.indexOf(',');
                temp = text.substring(0,next);
                move_received = true;
                nextMoveBuffer = temp;          
                mygame.set_opponent_move(nextMoveBuffer); // calls Game method
        }         
}

public void quitWindow () 
{
   int index;

        display("Preparing to log off.\n");
        if (game_on) 
        {
                index = id_vector.indexOf(new Integer(opponent_id));
                gclient.send_stream("!!directive!!mssge,surrender|"+Integer.toString(index+1)+"|");
        }
        gclient.cleanup();
        dispose();  
}

//******************************************************************
// put the unique id's into id_vector and names into user_list
public void write_list(String list) 
{ 
        int i, next, n;
        int temp_id;

        user_list.delItems( 0, user_list.countItems() -1 );     
        user_list.clear();              
        id_vector.removeAllElements();  
        for (i=0;i<list.length();i++) 
        {               
                n = list.indexOf('~',i);                        
                next = list.indexOf('|',i);             
                if (next >= list.length() || next == -1)
                break;  
                temp_id = Integer.parseInt(list.substring(i,n));
                id_vector.addElement(new Integer(temp_id));

                user_list.addItem(list.substring(n+1,next));
                i = next;       
        }
        //user_list.reshape(258,116,99,176);
} 

// display the text to the output area of the screen
public void display(String s)
{ 
        try{thread.sleep(100);}catch(InterruptedException e){}
        textArea.appendText(s);
}

// event handler for GUI components
public boolean handleEvent(Event evt) 
{ 
        int index, storage;
         
        // when you double-click on a user name in the user_list
        if (evt.id == Event.ACTION_EVENT && evt.target == user_list && !game_on) 
        {
                index = user_list.getSelectedIndex();
                opponent_id = ((Integer)id_vector.elementAt(index)).intValue();
                if (opponent_id != personal_id)
                {
                display("Challenging "+ (String)evt.arg + " to Internet Game!\n");
                gclient.send_stream("!!directive!!chlng,"+Integer.toString(personal_id)+"|"+Integer.toString(index+1)+"|");
                }
                else 
                        display("You cannot challenge yourself.\n");
        }

        // when you perform an action while you are connected
        if (evt.id == Event.ACTION_EVENT && gclient.is_connected()) 
        {
                if (gclient.stream_down())
                {
                display("A socket error has occured, you are not connected.\n");
                return super.handleEvent(evt);
                }

                if (evt.target == textField)
                {       // if want to send a message to the other player        
                        String textstream = textField.getText();
                textField.setText("");
                gclient.send_stream(textstream);
                }                       
    
          } 
        return super.handleEvent(evt);
}

public void stop()
{  

        int index;
        display("Preparing to log off.\n");
        if (game_on)    
        {
                index = id_vector.indexOf(new Integer(opponent_id));
                gclient.send_stream("!!directive!!mssge,surrender|"+Integer.toString(index+1)+"|");
        }
        gclient.cleanup();
}

//******************************************************************
//      methods to interact with your game class
//      game class calls this to send a move to other player
//******************************************************************
public void sendMove(String text) 
{
        int index;

        index = id_vector.indexOf(new Integer(opponent_id));
        gclient.send_stream("!!directive!!pmove," +text+ "|" +Integer.toString(index +1) +"|");
}

public void acceptyes() 
{
                int index;

                System.out.println ("accept yes");      
                // when you hit the Play Opponent button
                display("Opponent ready to Play! You will move second.\n");             
                index = id_vector.indexOf(new Integer(opponent_id));
 System.out.println("opponent id is " + opponent_id);
                gclient.send_stream("!!directive!!accpt,"+Integer.toString(personal_id)+"|"+Integer.toString(index+1)+"|");
                challenged = false;
                game_on = true;
                mygame = new Game(myapplet, base, this, false, gameimage);
}
} // end class

class AcceptWindow extends Frame
{
        private clientwindow parent;
        private Panel buttonPanel;
        private Button acceptyes;
        private Button acceptno;
        private Label user_label;

        public AcceptWindow(clientwindow parent, String wintitle, String User)
        {
                super(wintitle);
                this.parent = parent;
                user_label = new Label("You have been asked to play with " + User);
                buttonPanel = new Panel();
                acceptyes = new Button("Play Opponent");
                acceptno = new Button("Don't Play Opponent");

                //Add button to panel and panel to window
                setLayout(new FlowLayout());
                buttonPanel.setLayout(new GridLayout(7,1));
                buttonPanel.add(user_label);    
                buttonPanel.add(acceptyes);
                buttonPanel.add(acceptno);
                add(buttonPanel);

                //Size window to preferred size
                this.setSize(300, 300);
                this.show();
        }//end LoginWindow


        //  uses the jdk1.0.2 event handler...
        public boolean action(Event e, Object arg)
        {
                if(e.target instanceof Button)
                {
                        if(e.target == acceptyes)
                        {
                                if(this.isShowing())
                                {
                                        try
                                        {       
                                                parent.acceptyes();
                                        }
                                        catch(Exception exceptn)
                                        {
                                                exceptn.printStackTrace();
                                                System.out.println("Error:" + exceptn);
                                        }
                                        finally
                                        {
                                                this.dispose();  
                                        }
                                }
                        }
                        if(e.target == acceptno)
                        {
                                this.dispose();
                        }

                }
                return true;
        } //end action(Event, Object)
}//end class definition


