import java.net.*;
import java.awt.*;
import java.awt.event.*;
import javax.swing.*;
import java.io.*;

class Client implements ActionListener {
	String WINDOW_NAME = "Client Chat Window";
	String HOST = "localhost";
	int PORT = 2380;
	
	ServerSocket serverSocket = null;
	Socket clientSocket = null;
	Socket clientSocket2 = null;
	String errorMsg = null;
	
	JFrame mainFrame;
	JPanel labelPanel;
	JPanel historyPanel;
	JPanel textPanel;
	JPanel actionPanel;
	JLabel status;
	JTextArea history;
	JTextField input;
	JButton send, exit;
	
	String Received[] = {"\n","\n","\n","\n","\n","\n","\n","\n","\n","\n"};
	String in = "";
	String messages = "\n";
	
	int count=0;
	
	boolean error = false, mError = false;
	boolean action = false;
	boolean fileIn = false;
	boolean S = true;
	
	public Client()
	throws IOException {
		try {
			String HOST_A = JOptionPane.showInputDialog("Enter server (leave blank for default): ");
			if(HOST_A.equals("")) ;
			else HOST = HOST_A;
		} catch (NullPointerException e) {
			System.exit(0);
		}
		int index =  HOST.indexOf(':');
		if(index != -1) {
			PORT = Integer.parseInt(HOST.substring(index+1));
			HOST = HOST.substring(0,index);
		}
		
		start();
		mainFrame = new JFrame(WINDOW_NAME);
		Container content = mainFrame.getContentPane();
		content.setLayout(new BoxLayout(content, BoxLayout.Y_AXIS));
		labelPanel = new JPanel();
		historyPanel = new JPanel();
		textPanel = new JPanel();
		actionPanel = new JPanel();
		
		mainFrame.setSize(600, 100);
		mainFrame.setLocation(200, 200);
		
		history = new JTextArea(10,50);
		
		inPanels();
		addPanels();
		
		content.add(labelPanel);
		content.add(historyPanel);
		content.add(textPanel);
		content.add(actionPanel);
		
		mainFrame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
		mainFrame.pack();
		mainFrame.setVisible(true);
		input.grabFocus();
		Received[0] = "Welcome to " + WINDOW_NAME + ". (Type \"\\help\" of \"\\h\" for help.)\n";
		dispMsg();
		msgIn();
	}
	
	public void inPanels() {
		status = new JLabel(errorMsg);
		labelPanel.add(status);
		messages = "";
		for(int i=9; i>=0; i--) messages = messages + Received[i];
		history.setText(messages);
		history.setEditable(false);
		historyPanel.add(history);
	}
	
	public void addPanels() {
		input = new JTextField(in,50);
		input.addActionListener(this);		
		textPanel.add(input);
		
		send = new JButton("Send");
		exit = new JButton("Exit");
		send.addActionListener(this);
		exit.addActionListener(this);
		
		actionPanel.add(send);
		actionPanel.add(exit);
	}
	
	public void start() {
		error = false;
		try {
			clientSocket2 = new Socket(HOST, PORT);
		} catch (UnknownHostException e) {
			errorMsg = "Can't find " + HOST + ":" + PORT;
			error = true;
		} catch (IOException e) {
			errorMsg = "Could not connect to " + HOST + ":" + PORT;
			error = true;
		}
		try {
			serverSocket = new ServerSocket(PORT+1);
		} catch (IOException e) {
			errorMsg = "Another window is open or port " + (PORT+1) + " is inuse";
			error = true;
		}
		if(!error) {
			errorMsg = "Connected to " + HOST + ":" + PORT;
			try {
				PrintWriter out = new PrintWriter(clientSocket2.getOutputStream(), true);
				out.println("User is online...");
				clientSocket2.close();
			} catch (IOException e) {
				errorMsg = "Unable to Send Online Message!";
			}
		}
	}
	
	public void dispMsg() {
		labelPanel.removeAll();
		historyPanel.removeAll();
		
		inPanels();
		if(action) {
			textPanel.removeAll();
			actionPanel.removeAll();
			addPanels();
		}
		action = false;
		
		mainFrame.getContentPane().add(labelPanel, BorderLayout.CENTER);
		mainFrame.getContentPane().add(historyPanel, BorderLayout.CENTER);
		mainFrame.getContentPane().add(textPanel, BorderLayout.CENTER);
		mainFrame.getContentPane().add(actionPanel, BorderLayout.CENTER);
		labelPanel.repaint();
		historyPanel.repaint();
		textPanel.repaint();
		actionPanel.repaint();
		mainFrame.setVisible(true);
		input.grabFocus();
	}
	
	public void msgIn() 
	throws IOException {
		for(int j=0; j<1; ) {
			try {
				clientSocket = serverSocket.accept();
				InetAddress address = clientSocket.getInetAddress();
				String address2 = address.toString().substring(1);
				if(count >= 9) count=0;
				BufferedReader incoming = new BufferedReader(new InputStreamReader(clientSocket.getInputStream()));
				for(int i=9; i>0; i--) Received[i] = Received[i-1];
				Received[0] = incoming.readLine();
				try {
					if(Received[0].substring(0,17).equals(" is sending you: ")) {
						fileIn = true;
						Received[0] = address2 + Received[0];
					}
				} catch (StringIndexOutOfBoundsException e) {
				}
				if(Received[0].equals("Error Sending File!")) {
					Socket socket = new Socket(address2,PORT);
					PrintWriter out = new PrintWriter(socket.getOutputStream(),true);
					out.println("Error Sending File!");
					socket.close();
					fileIn = false;
				} else if(Received[0].equals("File Complete!")) {
					Socket socket = new Socket(address2,PORT);
					PrintWriter out = new PrintWriter(socket.getOutputStream(),true);
					out.println("File Transfer Successful!");
					socket.close();
				}
				Received[0] += "\n";
				count++;
				if(Received[0].length() > 100) {
					for(int i=9; i>0; i--) Received[i] = Received[i-1];
					Received[1] = Received[0].substring(0,100) + "\n";
					Received[0] = Received[0].substring(100);
					if(Received[0].length() > 100) {
						for(int i=9; i>0; i--) Received[i] = Received[i-1];
						Received[1] = Received[0].substring(0,100) + "\n";
						Received[0] = Received[0].substring(100);
					}
				}
				dispMsg();
				clientSocket.close();
				input.grabFocus();
			} catch (SocketException e) {
			} catch (NullPointerException e) {
			}
		}
	}
	
	public void msgOut() {
		try {
			if(in.equals("\\h") || in.equals("\\help")) {
				help();
			}
			else if(in.equals("\\exit")) {
				if(error != true) {
					in = "User Signed off...";
					msgOut();
				}
				System.exit(0);
			}
			else if(in.equals("\\about")) {
				about();
			}
			else if(in.equals("\\y") && fileIn || in.equals("\\yes") && fileIn) {
				fileIN();
			}
			else if((in.substring(0,3)).equals("\\w ") && (in.charAt(3) != '-')) {
				S = false;
				whisper();
			}
			else if((in.substring(0,4)).equals("\\ip ")) {
				IP();
			}
			else if((in.substring(0,6)).equals("\\w -s ")) {
				S=true;
				whisper();
			}
			else if((in.substring(0,8)).equals("\\server ")) {
				serverAddr();
			}
			else if((in.substring(0,6)).equals("\\port ")) {
				port();
			}
			else if((in.substring(0,6)).equals("\\file ") && (in.charAt(6) != '-')) {
				S = false;
				file();
			}
			else if((in.substring(0,9)).equals("\\file -s ")) {
				S = true;
				file();
			}
			else send();
		} catch (StringIndexOutOfBoundsException e) {
			send();
		}
		in="";
		action = true;
		dispMsg();
	}
	
	public void send() {
		if(!in.equals("")) {
			try {
				clientSocket2 = new Socket(HOST, PORT);
				PrintWriter out = new PrintWriter(clientSocket2.getOutputStream(), true);
				out.println(in);
				clientSocket2.close();
			} catch (UnknownHostException err) {
				errorMsg = "Error Sending Message!";
			} catch (IOException err) {
				errorMsg = "Error Sending Message!";
			}
		}
	}
	
	public void help() {
		for(int i=9; i>8; i--) Received[i] = Received[i-9];
		Received[8] = "Help for " + WINDOW_NAME + ".\n";
		Received[7] = "\\server <Server Address> - Connect to a Different Server.\n";
		Received[6] = "\\port <Port Number> - Changes the port.\n";
		Received[5] = "\\ip <Host Name> - Finds an IP address(User must be in the chat).\n";
		Received[4] = "\\users - lists all users.\n";
		Received[3] = "\\file -s <IP of Host> - Sends file to a user.(if sending file to server, put the -s in)\n";
		Received[2] = "\\w -s <IP or Host> <Message> - Whispers a message to a user.(use -s if whispering to a server)\n";
		Received[1] = "\\about - about - Program Info\n";
		Received[0] = "\\exit - exits the program.\n";
	}
	
	public void serverAddr() {
		try {
			serverSocket.close();
		} catch (IOException e) {
		}
		String inT = in;
		in="User Signed off...";
		send();
		HOST = inT.substring(8);
		start();
		if(!error) {
			for(int i=9; i>0; i--) Received[i] = Received[i-1];
			Received[0] = "Connected to " + HOST + "\n";
		} else {
			for(int i=9; i>0; i--) Received[i] = Received[i-1];
			Received[0] = "Unable to connect to " + HOST + "\n";
		}
	}
	
	public void port() {
		try {
			serverSocket.close();
		} catch (IOException e) {
		}
		String inT = in;
		in="User Signed off...";
		send();
		PORT = Integer.parseInt(inT.substring(6));
		start();
		if(!error) {
			for(int i=9; i>0; i--) Received[i] = Received[i-1];
			Received[0] = "Connected to port " + PORT + "\n";
		} else {
			for(int i=9; i>0; i--) Received[i] = Received[i-1];
			Received[0] = "Unable to connect to port " + PORT + "\n";
		}
	}
	
	public void IP() {
		try {
			for(int i=9; i>0; i--) Received[i] = Received[i-1];
			clientSocket2 = new Socket(in.substring(4),PORT+1);
			InetAddress address = clientSocket.getInetAddress();
			Received[0] = address.toString() + "\n";
			clientSocket2.close();
		} catch (UnknownHostException e) {
			Received[0] = "Couldn't Resolve IP\n";
		} catch (IOException e) {
			Received[0] = "Couldn't Resolve IP\n";
		}
	}
	
	public void file() {
		for(int i=9; i>0; i--) Received[i] = Received[i-1];
		String addr = in.substring(6);
		if(S) addr = in.substring(9);
		Received[0] = "Sending file to " + addr + ", Please wait\n";
		FileTrans filetrans = new FileTrans(addr,(PORT+2),S);
	}
	
	public void fileIN() {
		for(int i=9; i>0; i--) Received[i] = Received[i-1];
		Received[0] = "Receiving file, Please wait\n";
		FileTrans filetrans = new FileTrans(PORT+2);
		fileIn = false;
	}
	
	public void whisper() {
		int port = PORT+1;
		int t = 3;
		if(S) {
			t=6;
			port = PORT;
		}
		int line = in.substring(t).indexOf(' ');
		String ipAddr = in.substring(t,t+line);
		for(int i=9; i>0; i--) Received[i] = Received[i-1];
		try {
			Socket whisp = new Socket(ipAddr, port);
			PrintWriter out = new PrintWriter(whisp.getOutputStream(), true);
			out.println(whisp.getLocalAddress().toString().substring(1) + " whispers: " + in.substring(t+line));
			whisp.close();
			Received[0] = "Whispering to " + ipAddr + ": " + in.substring(t+line) + "\n";
		} catch (UnknownHostException e) {
			Received[0] = "Couldn't Whisper to " + ipAddr + "!\n";
		} catch (IOException e) {
			Received[0] = "Couldn't Whisper to " + ipAddr + "!\n";
		}
	}
	
	public void about() {
		JOptionPane.showMessageDialog(null,"About " + WINDOW_NAME + ":\nVersion 1.0b\nWritten by Benjamin Zastovnik\nMarch 9, 2004", "About " + WINDOW_NAME, JOptionPane.PLAIN_MESSAGE);
	}
	
	public void actionPerformed(ActionEvent e) {
		if(e.getSource() == exit) {
			if(error != true) {
				in = "User Signed off...";
				msgOut();
			}
			System.exit(0);
		}
		if(e.getSource() == send) {
			in = input.getText();
			if(in.equals(""));
			else msgOut();
		}
		if(e.getSource() == input) {
			in = input.getText();
			if(in.equals(""));
			else msgOut();
		}
	}
	public static void main(String args[])
	throws IOException {
		Client window = new Client();
	}
}