//: SeatClient.java
import java.awt.*;
import java.awt.event.*;
import java.io.*;
import java.net.*;

/** Assignment
* Client for the Concert Seat Reservation System
* @author Eric Kon Yin Liang
* E-mail: [email protected]
* @version 1.0
*/
public class SeatClient extends Frame
{
	private static final int port = 1000;
	private static final String serverName = "localhost";
	private Socket concertSocket = null;
	private BufferedReader fromServer = null;
	private PrintWriter toServer = null;
	private String operatorName = null;
	private Concert clientConcert;
	private Block[] clientBlock;
	private Button[] seatButtonArray; 
	private ConcertSeat[] seatArray;
	private Button allocate;
	private int totalSeats;
	private int totalRows;


	/** Sole entry point to SeatClient class & application
	* @param args array of string arguments, arg[0]-operator name
	* @return No return value
	* @exception with throws exceptions
	*/
	public static void main(String[] args) throws IOException  
	{
		Frame myWindow = new SeatClient(args[0]);
		myWindow.setSize(260,350); //size of the window
		myWindow.setVisible(true); 
		
		myWindow.addWindowListener (new WindowAdapter() 
		{
			public void windowClosing (WindowEvent e) 
			{
				System.exit(0);
			}
		});
	}


	// SeatClient Constructor
	public SeatClient(String operator) 
	{	//display the operator name on title frame
		super("SeatClient " + operator);
		
		String serverMessage;
		operatorName=operator;

		serverMessage = connectServer();
		// If server reply with message
		if (serverMessage != null)
		{
			System.out.println(serverMessage);
			getConcertInfo();
			calcTotalRowsSeats();
			clientInterface();
			refreshSeatClient();
		}
	}


	/** This method is use to contact the SeatServer
	* @param No parameter
	* @return return the message that send by the server
	* @exception without throws exceptions
	*/
	protected String connectServer () {
		String serverWelcome =null;

		try {
			concertSocket = new Socket(serverName,port);
			toServer = new PrintWriter(concertSocket.getOutputStream(), true);
			fromServer = new BufferedReader(new InputStreamReader(concertSocket.getInputStream()));
			serverWelcome = fromServer.readLine();
		}   
		catch (UnknownHostException e) {
			System.out.println("Unknown host:" + serverName);
		} 
		catch (IOException e) {
			System.out.println("Fail Connect to Server:" + serverName);
		}

		return serverWelcome;
	}


	/** This method is use to get the concert seat layout and create the client concert object (dynamic layout)
	* @param No parameter
	* @return No return
	* @exception without throws exceptions
	*/
	protected void getConcertInfo ()
	{
		String word;
		int count = 0, blockLength = 0, rows = 0, across = 0;
		
		toServer.println("BlockInfo");

		try	{
			word = fromServer.readLine();
			blockLength = Integer.parseInt(word);
			clientBlock = new Block[blockLength];
			while (count< blockLength) {
				word = fromServer.readLine();
				rows = Integer.parseInt(word);
				word = fromServer.readLine();
				across = Integer.parseInt(word);
				clientBlock[count] = new Block(rows,across,0);
				count++;
			}
		}
		catch (IOException ex) {
      		System.out.println("Client receive failed:");
   		}

		clientConcert = new Concert (clientBlock);
	}


	/** This method is use to compute the total number of seats for concert
	* @param No parameter
	* @return int - total number of seats
	* @exception without throws exceptions
	*/
	public int calcTotalRowsSeats ()
	{
		int seatsInBlock = 0;

		for(int count = 0; count< clientBlock.length; count++){
			seatsInBlock = (clientBlock[count].getRows()) * (clientBlock[count].getAcross());
			totalRows += clientBlock[count].getRows();
			totalSeats += seatsInBlock;
		}

		return totalSeats;
	}


	/** This method is use to get the latest seat status from server
	* @param No parameter
	* @return No return
	* @exception without throws exceptions
	*/
	public void refreshSeatClient ()
	{
		String status;
	
		for (int count = 0; count< seatArray.length; count++)
		{
			
			try {
				toServer.println("Check");
				toServer.println(seatArray[count].seatNumber());
				status = fromServer.readLine();

				if (status.compareTo("0")==0)
					//set the button color to grey
					seatButtonArray[count].setBackground(Color.lightGray);
				else if (status.compareTo("1")==0)
					//set the button color to green
					seatButtonArray[count].setBackground(Color.green);
				else if (status.compareTo("2")==0)
					//set the button color to red
					seatButtonArray[count].setBackground(Color.red);
			}
			catch (IOException ex) {
   				System.out.println("Client receive failed:");
   			}
		}
	}


	/** This method is use to construct the frame layout
	* @param No parameter
	* @return No return
	* @exception without throws exceptions
	*/
	protected void clientInterface ()
	{
		int blockIndex, seatIndex, rowIndex, rowNo=0, messageNo=0, seatCount = 0;
		String word, seatNumber;
		
		seatButtonArray = new Button[totalSeats];
		seatArray = new ConcertSeat[totalSeats];
		GridLayout view = new GridLayout(totalRows+5,1);
		setLayout(view);
		Panel[] myPanel = new Panel[totalRows+5];

		// For seat button part
		for(blockIndex = 0; blockIndex < clientBlock.length; blockIndex++) {
			for(rowIndex = 0; rowIndex < clientBlock[blockIndex].getRows(); rowIndex ++) {
				rowNo++;
				myPanel[rowNo-1]= new Panel();
				myPanel[rowNo-1].setLayout(new GridLayout(1,clientBlock[blockIndex].getAcross()));
				add(myPanel[rowNo-1]);

				for(seatIndex = 1; seatIndex <= clientBlock[blockIndex].getAcross(); seatIndex++){
					seatNumber = new ConcertSeat(rowNo, seatIndex-1).seatNumber();
					seatButtonArray[seatCount] = new Button (seatNumber);
					seatArray[seatCount] = new ConcertSeat(rowNo, seatIndex-1);
					seatButtonArray[seatCount].addActionListener(new Seat());
					myPanel[rowNo-1].add(seatButtonArray[seatCount]);
					seatCount++;
				}
			}
		}

		// For message part
		for(messageNo=rowNo; messageNo < myPanel.length; messageNo++){
			Label message = new Label();
			allocate = new Button("Allocate");
			allocate.addActionListener(new Allocate());

			int messageCount=messageNo-rowNo;

			myPanel[messageNo]= new Panel();
			myPanel[messageNo].setLayout(new GridLayout(1,1));
			add(myPanel[messageNo]);

			switch (messageCount){
				case 0: message.setText("Grey=Free, Click seat to reserve."); break;
				case 1: message.setText("Green=Reserve, Click seat to free."); break;
				case 2: message.setText("Red=Allocated"); break;
				case 4: message.setText("Allocate button allocates reserved seats"); break;
			}

			if (messageCount != 3)	 
				myPanel[messageNo].add(message);
			else
				myPanel[messageNo].add(allocate);
		}
	}

	//when client click on allocate button, this will send a message to server
	class Allocate implements ActionListener {
		String setResult;

		public void actionPerformed(ActionEvent e) {
			toServer.println("Allocate");
			toServer.println(operatorName);
			try {
           		setResult = fromServer.readLine();
				refreshSeatClient();
			} 
			catch (IOException ex) {
      	    	System.out.println("Client receive failed:");
        	}
		}
	}


	class Seat implements ActionListener 
	{
		String setResult;

		public void actionPerformed (ActionEvent e)
		{
			String seatNumber = e.getActionCommand();
			Button button = (Button) e.getSource ();
			
			if ( button.getBackground() != Color.red ) {
				if ( button.getBackground() == Color.lightGray)
					toServer.println("Reserve");
				else if ( button.getBackground() == Color.green )
					toServer.println("Free");

				toServer.println(operatorName);
				toServer.println(seatNumber);

				try {
           			setResult = fromServer.readLine();
					System.out.println("Status: " + setResult);
					refreshSeatClient();
				} 
				catch (IOException ex) {
      	      		System.out.println("Client receive failed:");
        		}
			}
		}
	}
} ///:~