//******************************************************************//
//Versao 0.1 - JavaChat PCMaster						  //
//Data: Maio/1999									  //
//Autor: Luiz Antonio Siqueira Neto						  //
//e-mail: siqueira@europanet.com.br						  //
//Distribuido na edicao numero 25 da Revista PCMaster			  //
//											  //	
//Editora Europa									  //
//R. MMDC, 121 - Butanta - Sao Paulo - SP - Brasil     		  //
//CEP:05510-021									  //		
//Telefone:011-816-6767   							  //	
//											  //	
//******************************************************************//


//Este eh um programa exemplo que pretende apresentar como a linguagem Java pode
//ser utilizada para criar aplicacoes graficas e na Internet.
//JavaChat eh um chat simples que permite duas pessoas se comunicarem pela Internet.
//Na sua implementacao sao utilzados alguns recursos graficos do Java e recursos de 
//transmissao de dados pela Internet. O codigo esta comentado e junto da edicao da 
//Revita PCMaster numero 25 foi distribuido um caderninho explicando conceitos basicos
//da linguagem Java e detalhando a construcao deste Chat.

//Declaracao das classes do java que serao utilizadas no programa
import java.io.*;			//Classes de entrada e saida
import java.net.*;		//Classes para acesso aos recuros de redes de computadores
import java.awt.*;		//Classes para acesso aos recuros graficos
import java.awt.event.*;	//Classes para tratamento de eventos

//Declaracao da classe principal Chat.java
public class Chat extends Frame implements ActionListener{ 	//Extensao da classe Frame e utiliza os metodos de ActionListener
  private TextArea output;						//Area de Texto de saida
  private Button conectar,enviar,aguardar;			//Botoes da interface grafica
  private TextField servidor,usuario,mensagem;			//Campos de texto da interface
  private Panel texto,campos,botoes,msg,central;		//Paineis da interface
  private ServerSocket ServidorSocket;				//Socket servidor
  private Socket ClienteSocket;					//Socket cliente
  private PrintStream Saida;						//Stream de saida do Socket
  private DataInputStream Entrada;					//Stream de entrada do Socket
  
  public Chat() {						//Metodo construtor da classe Chat
    super("aloha");                                     //Titulo da janela do Chat
    setSize(450,490);					//Definicao do tamanho da janela
    setBackground(new Color(0xFFC0C0C0));		//Definicao da cor de fundo da janela
    
    texto= new Panel();					//Instancia do painel texto
    msg= new Panel();					//Instancia do painel msg
    central = new Panel();				//Instancia do painel central
    campos=new Panel();					//Instancia do painel campos
    botoes=new Panel();					//Instancia do painel botoes
    
    output = new TextArea(24,55);			//Instancia da Area de saida
    texto.add (output);					//Insercao da Area de saida no painel texto
    add(texto,BorderLayout.NORTH);			//Formatacao da Area de saida
    
    conectar = new Button ("Conectar");		//Instancia de cada um dos botoes	
    enviar = new Button ("Enviar");
    aguardar = new Button ("Aguardar");
    
    conectar.addActionListener(this);		//Ativando o ActionListener para ativar as funcoes quando os botoes forem pressionados
    enviar.addActionListener(this);
    aguardar.addActionListener(this);
    
    botoes.add (conectar);				//Insercao dos botoes no painel correspondente
    botoes.add (enviar);
    botoes.add (aguardar);
    
    botoes.setLayout(new GridLayout(1,1));  	//Setando o Layout do painel de botões
    add(botoes,BorderLayout.SOUTH);
    
    central.setLayout(new GridLayout(2,1));	//Setando o Layout do painel central
    add(central,BorderLayout.CENTER);		
    
    msg.setLayout(new GridLayout(1,1));		//Setando o Layout do painel msg
    central.add(msg,BorderLayout.NORTH);		
    
    campos.setLayout(new GridLayout(1,4));	//Setando o Layout do painel central
    central.add(campos,BorderLayout.SOUTH);

    usuario = new TextField(20);			//Instancia dos campos de texto
    servidor = new TextField(20);
    mensagem = new TextField(60);
    
    campos.add (new Label("   Usuario"));		//Insercao dos Labels e campos de texto no painel campos
    campos.add (servidor);
    campos.add (new Label("   Apelido"));
    campos.add (usuario);

    msg.add(new Label("   Mensagem"));			//Insercao do Label e campo de mensagem no painel msg
    msg.add(mensagem);	

    setVisible(true);
  }

//Funcao que faz a leitura do texto recebido
 private void readText() {						
    String buf;								//String com o buffer do texto recebido
    int teste;								//Inteiro para o texto do texto de chegada
    try {
    	teste=Entrada.available();					//Testa para ver se tem alguma coisa para ler
    	while(teste!=0) {							//Continua a leitura enquanto o teste nao falhar
            buf = new String(Entrada.readLine()+"\n");  	//Le o texto do Stream de Entrada
		output.appendText(buf);					//Coloca o texto na area de saida
            teste=Entrada.available(); 				//Testa novamente o arquivo
	}
    } catch (IOException e) {						//Trata o caso de um erro na leitura
      	output.appendText(e.toString()+"\n");
      	output.appendText(e.getMessage()+"\n");
      	return;
    }
   }

//Funcao que faz o tratamento do evento de fechamento da janela
 public boolean handleEvent(Event e) {
        if (e.id == Event.WINDOW_DESTROY) System.exit(0); 	//Detroi a janela e fecha imediatamente
        return super.handleEvent(e);
 }

//Funcao que faz o tratamento dos eventos de acionamento dos botoes do programa
 public void actionPerformed (ActionEvent e) {
    if(e.getSource() == conectar ) conexao();			//Chama a funcao correspondente ao botão
    if(e.getSource() == enviar) envio();
    if(e.getSource() == aguardar) aguardando();
 }

//Funcao que inicia o SocketServidor para ficar aguardando a conexao de um usuario
 public void aguardando() {
	try {
		ServidorSocket = new ServerSocket(3000); 					//Instancia o socket servidor
		ClienteSocket = ServidorSocket.accept();					//Coloca o socket para escutar a porta por uma nova conexao
		Entrada = new DataInputStream(ClienteSocket.getInputStream());	//Depois da nova conexao captura o Stream de entrada
      	Saida= new PrintStream(ClienteSocket.getOutputStream());		//Depois da nova conexao captura o Stream de saida
	} catch (Exception e) {					//Trata caso ocorra um erro
	      output.appendText(e.toString()+"\n");	
      	output.appendText(e.getMessage()+"\n");	
	      return;
      }
 }

//Funcao que envia as mensagens pelo Stream de Saida e imprime na area de texto 
 public void envio(){
	try {
	    	output.appendText(usuario.getText() + ">" + mensagem.getText() + "\n");	//Pega a mensagem e imprime na area de texto
		Saida.println(usuario.getText() + ">" + mensagem.getText());		//Pega a mensagem e manda para o stream de saida
	} catch (Exception e) {					//Trata caso ocorra um erro
      	output.appendText(e.toString()+"\n");
	      output.appendText(e.getMessage()+"\n");
      	return;
    	}
 }

//Funcao que incia uma nova conexao com outro computador
 public void conexao() {
    	try {
      	ClienteSocket = new Socket(servidor.getText(),3000);			//Inicia um novo Socket de comunicacao com outro computador na porta 3000
		Entrada = new DataInputStream(ClienteSocket.getInputStream());	//Depois da conexao captura o Stream de saida
      	Saida= new PrintStream(ClienteSocket.getOutputStream());		//Depois da conexao captura o Stream de entrada
    	} catch (Exception e) {					//Trata caso ocorra um erro
	      output.appendText(e.toString()+"\n");
      	output.appendText(e.getMessage()+"\n");
     	 	return;
    	}
 }

//Funcao principal que implementa um objeto da classe Chat e ativa o recebimento de mensagens
 public static void main(String args[]) {
       Chat fc  = new Chat();		//Instancia do novo objeto Chat
	 while(true)			//Repete infinitamente
		if(fc.Entrada!=null) 	//Somente tenta ler se o Socket de entrada exisitir
	      	fc.readText();	//Ativa a leitura das mensagens recebidas
 }
}















