import java.net.*;
import java.io.*;
/*
 *@auther Alwyn Zardac Nixon-Lloyd
 *@date finished on 15/5/2002
 *@copyright it probably belongs to me...
 * JavaTerm -a address_to_connect_to -p portnumer_to_connect_to
 * JavaTerm is a very dodgy telnet client. It ignores all of the smart stuff that is supposed to go on in the background
 * if you use this you will see this as strange characters being displayed.
 * however.. i may add it later.. but this was primerlity a test to see how sockets work --Zardac
 */

public class JavaTerm{

	Socket netSocket;
	InputStream input;
	OutputStream output;
	Boolean cont;
	InetAddress remoteAddress;
	ExternalInput keyboard;
	OpenThread opener;

	JavaTerm(InetAddress remadd, int port ) throws Exception{

		remoteAddress = remadd;
		System.out.println( " this will connect to port :" +port +"   at :");
		System.out.println( remoteAddress.toString() );

		netSocket = new Socket(remoteAddress , port);
		System.out.println( " local port number is: " + netSocket.getLocalPort() );

		input = netSocket.getInputStream();
		output = netSocket.getOutputStream();

		opener = new OpenThread(input);     //creates an thread to deal with the displaying stuff
		opener.start();                                 //starts the thread:hopefully will not block
		System.out.println("the output stream has started");
		keyboard = new ExternalInput( output );

		System.out.println("now waiting to see if it works :) ");
	}

	public static void main(String[] args){

		InetAddress temp;
		int portnum;
		char change;
		Integer basic = new Integer( 23);
		boolean assignedAnAdress = false;
		String blarg = "127.0.0.1";

		if(args.length ==0||args.length==1||args.length ==3){  //quits if incorect number of args is given
			System.out.println(" JavaTerm -a address -p port ");
			System.exit(1);
		}

		for(int i =0; i <args.length; i=i+2){
			//loops through getting the arguments from the command
			if(args[i].charAt(0) == '-'){
				change = args[i].charAt(1);

				switch(change){

					case 'a':
						blarg = args[i+1];
						assignedAnAdress = true;
						break;

					case 'p':
						basic = Integer.decode(args[i+1]);
						break;

					default:   //quit if the tags arn't correct
						System.out.println(" JavaTerm -a address -p port ");
						System.exit(1);
						break;
				}
			}
			else{                    //quit if the args arn't the start of a tag
				System.out.println("JavaTerm -a address -p port");
				System.exit(1);
			}
		}
		if(!assignedAnAdress){                     //if no address had been assigned with the -a tag... quit
			System.out.println("you need to assign at least an address to connect to");
			System.out.println("JavaTerm -a address -p port");
			System.exit(1);
		}

		portnum = basic.intValue();
		try{
			temp = InetAddress.getByName(blarg);
			new JavaTerm(temp, portnum);
		}catch(Exception e){
			System.out.println("error!!! something went wrong somewhere!!  ");
			System.out.println("possibly host not found/known");
			System.out.println( e.getLocalizedMessage() );
			System.out.println("JavaTerm -a address -p port");
			System.exit(1);
		}
	}
}

class ExternalDisplay{
/* the ExternalDisplay constructor takes an input stream and writes it to the std Output
 *  which is normaly the terminal prompt;  Once started it blocks.
*/

	ExternalDisplay(InputStream in){
		int data =1;
		while(true){
			try{
				data = in.read();
			}catch(Exception e){
				System.out.println("error:lots! :");
				System.out.println( e.getMessage() );
				System.exit(1);
			}
			if(data == -1){   //if the stream has been closed its meant to return -1.. not quite sure about other junk
				try{
					in.close();
				}catch(IOException e){
					System.out.println("error : "+e.getMessage() + " has occured whilse trying to close the stream");
				}
				System.out.println("ok.. connection Closed");
				System.exit(1);
			}
			System.out.write(data);
			System.out.flush();
		}
	}
}

class ExternalInput{
/*  The ExternalInput constructor gets an OutputStream and writes to it from StdInput.
 *   Which is normaly linked to the terminal
 *   The constructor also blocks like ExternalOutput....
 */
	ExternalInput( OutputStream out){
		int data = 1;
		System.out.println("started the keyboard reading");
		while (true) {
			try {
				data = System.in.read();
			        out.write(data);
			} catch (Exception e) {
				System.out.println("error :");
				System.out.println( e.getMessage() );
				System.exit(1);
			}
		}
	}
}

class OpenThread extends Thread{
/*  OpenThread is a new thread that runs to create the ExternalDisplay ;
 *   The constructer is passed the reference to the InputStream it is to read from the socket
 *   yeah.. thats about it
 */
	ExternalDisplay display;
	InputStream incoming;
	
	public void run(){
		display = new ExternalDisplay(incoming);
	}

	OpenThread( InputStream i ){
		incoming = i;
	}
}

