import java.awt.*;
import java.awt.event.*;
import java.io.BufferedReader;
import java.io.InputStreamReader;
import java.io.PrintWriter;
import java.net.Socket;
import java.util.StringTokenizer;

import javax.swing.*;
import javax.swing.event.*;

class Pong extends JFrame
{
	static int width = 640, height = 480;
	
	//serveri ühendamine
	public static final int PORT = 1234;     // server details
	public static final String HOST = "ws8";
    private static final int MAX_PLAYERS = 2;
	private final static int PLAYER1    = 1;
	private final static int PLAYER2    = 2;   // use to be MACHINE
	private Socket sock;
	public PrintWriter out;  
	//stuff for menus
	JMenuBar menuBar;
	JMenu fileMenu;
	JMenuItem exitItem;
	JMenu helpMenu;
	JMenuItem keysItem;
	
	//game stuff
	PongPane mainPane;
	PongGame mainGame;
	Timer aTimer;
	//minu lisatud gamestuff
	  private int playerID;
	  private String status;         
	  private int numPlayers;
	  private int currPlayer;        // which player can take a turn now?
	  private boolean isDisabled;    // to indicate that the game has ended
	  private double xvel;
	  private double yvel;
	  private boolean xvelkaes;
	  private boolean yvelkaes;
	  private String temptext;
	  private double temp;
	
	public Pong(String name)
	{
		super(name);
		playerID = 0;     // no id as yet
	    status = null;    // no status to report 
	    numPlayers = 0;
	    currPlayer = 1;    // player 1 starts first
	    isDisabled = false;

	    makeContact();
	    
		getContentPane().setLayout(null);
		setSize(width + 8, height + 56);
		
		//menus
		menuBar = new JMenuBar();
		this.setJMenuBar(menuBar);
		
		fileMenu = new JMenu("File");
		fileMenu.setMnemonic('F');
		menuBar.add(fileMenu);
		
		exitItem = new JMenuItem("Exit");
		exitItem.setMnemonic('x');
		exitItem.addActionListener(new ExitMenuItemListener());
		fileMenu.add(exitItem);
		
		helpMenu = new JMenu("Help");
		helpMenu.setMnemonic('H');
		menuBar.add(helpMenu);
		
		keysItem = new JMenuItem("Keys");
		keysItem.setMnemonic('K');
		keysItem.addActionListener(new KeysMenuItemListener());
		helpMenu.add(keysItem);
		
		
		//game stuff
		mainGame = new PongGame(width, height);
		
		mainPane = new PongPane(width, height, mainGame);
		mainPane.setLocation(0,0);
		mainPane.setSize(width, height);
		getContentPane().add(mainPane);
		
		aTimer = new Timer(10, new TimerRepaintListener());
		aTimer.start();
	    //pack();
	    //setResizable(false);    // fixed size display
	    //show();
		//setVisible(true);
		//to make the game listen to the keyboard
		this.addKeyListener(new PaddleListener());
	}
	
	private void update()
	{
		mainGame.update();
		repaint();
	}
	
	private class PaddleListener implements KeyListener
	{
		public void keyPressed(KeyEvent e)
		{
			char key = e.getKeyChar();
			if((key == 'a') && (playerID==1) ){
				mainGame.setP1Move(-1);
			    out.println("P1Move(-1)");
			} else if((key == 'z') && (playerID==1)){
				mainGame.setP1Move(1);
			    out.println("P1Move(1)");
			} else if((key == 'k') && (playerID==2) ){
				mainGame.setP2Move(-1);
				out.println("P2Move(-1)");
			} else if((key == 'm') && (playerID==2) ){
				mainGame.setP2Move(1);
				out.println("P2Move(1)");
			}
			/*System.out.println(playerID);
			char key = e.getKeyChar();
			if((key == 'a') || (key == 'A') && (playerID==1) )
				mainGame.setP1Move(-1);
			else if((key == 'z') || (key == 'Z') && (playerID==1))
				mainGame.setP1Move(1);
			else if((key == 'k') || (key == 'K') && (playerID==2) )
				mainGame.setP2Move(-1);
			else if((key == 'm') || (key == 'M') && (playerID==2) )
				mainGame.setP2Move(1);*/
		}
		
		public void keyReleased(KeyEvent e)
		{
			char key = e.getKeyChar();
			if((key == 'a') || (key == 'A') || (key == 'z') || (key == 'Z')&& (playerID==1)){
				mainGame.setP1Move(0);
				out.println("P1Move(0)");
			} else if((key == 'k') || (key == 'K') || (key == 'm') || (key == 'M')&& (playerID==2)){
				mainGame.setP2Move(0);
				out.println("P2Move(0)");}
		}
		
		public void keyTyped(KeyEvent e)
		{
			if(e.getKeyChar() == ' '){
				mainGame.spaceBarPressed();
			    out.println("spaceBar");}

		   /*if(e.getKeyChar() == 'n'){
			out.println("randomize");}*/

	}
	}
	private class TimerRepaintListener implements ActionListener
	{
		public void actionPerformed(ActionEvent e)
		{
			update();
		}
	}
	
	private class KeysMenuItemListener implements ActionListener
	{
		public void actionPerformed(ActionEvent e)
		{
			JOptionPane.showMessageDialog(getContentPane(),
			"Controls:\nPlayer1:\nUp: A  Down: Z\nPlayer2:\nUp: K  Down: M",
			"Keys", JOptionPane.PLAIN_MESSAGE);
		}
	}
	
	private class ExitMenuItemListener implements ActionListener
	{
		public void actionPerformed(ActionEvent e)
		{
			System.exit(100);
		}
	}
	  private void makeContact()
	  // contact the FBFServer, and then one of its player handlers
	  {
	    try {
	      sock = new Socket(HOST, PORT);
	      BufferedReader in  = new BufferedReader( 
			  		new InputStreamReader( sock.getInputStream() ) );
	      out = new PrintWriter( sock.getOutputStream(), true );  // autoflush
	      //out.println("server hakka tööle");

	      //new FBFWatcherpong(this, in).start();    // start watching for server msgs
	      new FBFWatcherpong(in).start();    // start watching for server msgs
	    }
	    catch(Exception e)
	    {  // System.out.println(e);
	       System.out.println("Cannot contact the Server");
	       System.exit(0);
	     }
	  }  // end of makeContact()*/

	  private int otherPlayer(int id)
	  // we assume there are only two players
	  { int otherID = ((id == PLAYER1) ? PLAYER2 : PLAYER1 );
	    return otherID;
	  } 


	  synchronized public void disable(String msg)
	  /* Disconnect from network but do not terminate.
	  */
	  { if (!isDisabled) {    // the client can only be disabled once
	      try {
	        isDisabled = true;
	        //out.println("disconnect");  // tell server
	        sock.close();
	        setStatus("Game Over: " + msg);
	         System.out.println("Disabled: " + msg);
	      }
	      catch(Exception e)
	      {  System.out.println( e );  }
	    }
	  }  // end of disable()

	  synchronized public void setStatus(String msg)
	  {  System.out.println("Status: " + msg);
	    status = msg;
	  }
	  synchronized public String getStatus()
	  {  return status; }


	  // -------------------------------------------------
	  // the following methods are only called from FBFWatcher
	  public void addPlayer()
	  // add the other player
	  { numPlayers++; 
	    if (numPlayers == MAX_PLAYERS) {   // time to start the game
	      if (currPlayer == playerID)  // this player starts
	        setStatus("Please start");
	      else    // the other player starts
	        setStatus("Player " + currPlayer + " starts the game");
	    }
	  } // end of addPlayer()


	  public void removePlayer()
	  // remove the other player
	  { numPlayers--;
	    if (numPlayers < MAX_PLAYERS)
	      disable("Player " + otherPlayer(playerID) + 
									" has left");    // disable client
	  } // end of removePlayer()


	  public void setPlayerID(int id)
	  /* This player is given a playerID. 
	     Update the window's title bar.
	     The id is also the number of current players, so
	     can be used to check whether the game can start.
	  */
	  { System.out.println("My player ID: " + id);
	    playerID = id;
	    if (playerID == PLAYER1)
	      setTitle("Player 1");
	    else   // PLAYER2
	      setTitle("Player 2");

	    numPlayers = id; 
	    if (numPlayers == MAX_PLAYERS)
	    setStatus("Player 1 starts the game");
	    else if (numPlayers < MAX_PLAYERS)
	      setStatus("Waiting for player " + otherPlayer(playerID) );
	  } // end of setPlayerID()*/
	  //toggleHasStarted();
	  public class FBFWatcherpong extends Thread
	  {
	  
	  private BufferedReader in;

	  public FBFWatcherpong(BufferedReader i)
	  {  
	    in = i;  
	  }


	  public void run()
//	   Read server messages and act on them
	  { 
	   String line;
	   try {
	     while ((line = in.readLine()) != null) {
	       if (line.startsWith("ok"))
	         extractID(line.substring(3));
	       else if (line.startsWith("full"))
	       	disable("full game");    // disable client
	       else if (line.startsWith("tooFewPlayers"))
	       	disable("other player has left");    // disable client
	       //else if (line.startsWith("otherTurn"))
	       //  extractOther(line.substring(10));
	       else if (line.startsWith("added"))    // don't use ID
	       	addPlayer();        // client adds other player
	       else if (line.startsWith("removed"))  // don't use ID
	       	removePlayer();     // client removes other player
	       else if (line.trim().equals("P1Move(-1)")) { 
	       	mainGame.setP1Move(-1);
	     } else if (line.trim().equals("P1Move(1)")) { 
		       	mainGame.setP1Move(1);
	     } else if (line.trim().equals("P2Move(-1)")) { 
	       	mainGame.setP2Move(-1);
	     } else if (line.trim().equals("P2Move(1)")) { 
	       	mainGame.setP2Move(1);
	     } else if (line.trim().equals("P1Move(0)")) { 
	       	mainGame.setP1Move(0);
	     } else if (line.trim().equals("P2Move(0)")) { 
	       	mainGame.setP2Move(0);
	     } else if (line.startsWith("space")) {  	
	       	mainGame.spaceBarPressed();
	        if(mainGame.hasStarted==true){out.println("randomize");}
	     } else if (line.startsWith("velocity")) {  	
	         xvelkaes=false; yvelkaes=false;
	         StringTokenizer st1 = new StringTokenizer(line);
	         while (st1.hasMoreTokens()) {
	             temptext=st1.nextToken();
	             //System.out.println(Integer.parseInt(temptext));        
	             if(temptext.equals("1.0") || temptext.equals("-1.0")){
	                 temp = Double.parseDouble(temptext);
	                 if(xvelkaes==false){xvel=temp; xvelkaes=true;}
	                 if(xvelkaes==true && yvelkaes==false){yvel=temp; yvelkaes=true;}
	              	if(mainGame.hasStarted==true && mainGame.paused==false ){mainGame.ball.setVelocity(xvel, yvel);}
	             }
	         }	
	     } else   // anything else
	         System.out.println("ERR: " + line + "\n");
	     }
	   }
	   catch(Exception e)    // socket closure will cause termination of while
	   { // System.out.println("Socket closed");
	     disable("server link lost");   // end game as well
	   }
	  }  // end of run()


	  private void extractID(String line)
//	   line format:  <player id>
	  {
	   StringTokenizer tokens = new StringTokenizer(line);
	   try {
	     int id = Integer.parseInt( tokens.nextToken() );
	     setPlayerID(id);     // client gets its playerID
	   }
	   catch(NumberFormatException e)
	   { System.out.println(e); } 
	  }  // end of extractID()


	  }
	public static void main(String args[])
	{
		Pong game = new Pong("Pong");
		game.setDefaultCloseOperation(EXIT_ON_CLOSE);
		game.setVisible(true);
		game.setResizable(false);
	}
}