import java.awt.*; 
import java.awt.event.*;
import javax.swing.*; 
import javax.swing.event.*; 

public class JChat extends JApplet
{	
   private JPanel contentPane;  
   private JLabel lblMessage;
   private JLabel lblUsers; 
   private JTextField txtMessage; 
   private JTextArea txtChat; 
   private JScrollPane jScrollPane3; 
   private JList lstUsers; 
   private JScrollPane jScrollPane4; 
   private JButton buttonSend; 
   private JPanel jPanel1; 
   private JLabel lblEnter; 
   private JTextField txtNick; 
   private JButton buttonEnter; 
   private JPanel jPanel3; 
   private DefaultListModel listModel;
   private JChatClient client;
   private boolean isClientConnected;
	
   public void init()
   {
      try
      {
         javax.swing.SwingUtilities.invokeAndWait(new Runnable()
            {
               public void run()
               {
                  createGUI();
                  initializeBehaviors();
               }
             });
	    }
      catch (Exception e)
      {
         System.err.println("Errore nella creazione della interfaccia grafica");
      }
   }	


   public void destroy()
   {
      if (client == null)
         return;
      disconnect();
   }

   private void createGUI()
   {	
      try 
      {
         UIManager.setLookAndFeel(
            "com.sun.java.swing.plaf.windows.WindowsLookAndFeel") ; 
      } 
      catch (Exception ex) 
      { 
         System.out.println("Errore durante il caricamento del Look & Feel: "); 
         System.out.println(ex); 
      } 

      createGUIControls();
      setContentPane();
      setJPanel1();
      setJPanel3(); 

      this.setLocation(new Point(0, 0)); 
      this.setSize(new Dimension(520, 390)); 		 		
   }


   private void createGUIControls()
   {
      contentPane = (JPanel)this.getContentPane(); 
      lblMessage = new JLabel();
      lblUsers = new JLabel();
      txtMessage = new JTextField(); 
      txtChat = new JTextArea();
      jScrollPane3 = new JScrollPane();
      listModel = new DefaultListModel();
      lstUsers = new JList(listModel);
      jScrollPane4 = new JScrollPane(); 
      buttonSend = new JButton();
      jPanel1 = new JPanel();
      lblEnter = new JLabel(); 
      txtNick = new JTextField(); 
      buttonEnter = new JButton(); 
      jPanel3 = new JPanel();		
   }


   private void setContentPane()
   {
      contentPane.setLayout(null); 
      addComponent(contentPane, jPanel1, 0,0,520,340); 
      addComponent(contentPane, jPanel3, 0,333,520,56);
   }

   private void setJPanel1()
   {
      lblMessage.setText("Il tuo messaggio:"); 
      lblUsers.setText("Utenti connessi");
      txtChat.setEditable(false); 
      txtChat.setLineWrap(true); 		
      jScrollPane3.setViewportView(txtChat);
      jScrollPane4.setViewportView(lstUsers);
      buttonSend.setText("Invia");
      buttonSend.setEnabled(false);
      jPanel1.setLayout(null); 

      addComponent(jPanel1, lblMessage, 2,277,86,18); 
      addComponent(jPanel1, lblUsers, 394,4,82,18); 
      addComponent(jPanel1, txtMessage, 89,276,278,22); 
      addComponent(jPanel1, jScrollPane3, 4,6,364,241); 
      addComponent(jPanel1, jScrollPane4, 383,26,105,223); 
      addComponent(jPanel1, buttonSend, 393,273,83,28);
   }

   private void setJPanel3()
   {
      lblEnter.setText("Scegli un nickname e premi il pulsante Entra in Chat!:");
      buttonEnter.setText("Entra in Chat!");
      jPanel3.setLayout(null); 
      addComponent(jPanel3, lblEnter, 3,16,253,18); 
      addComponent(jPanel3, txtNick, 258,13,122,22); 
      addComponent(jPanel3, buttonEnter, 390,11,102,28);
   }

   private void initializeBehaviors()
   {
      buttonSend.addActionListener(new ActionListener()
      { 
         public void actionPerformed(ActionEvent e) 
         { 
            buttonSend_actionPerformed(e); 
         } 
      });

      buttonEnter.addActionListener(new ActionListener()
      { 
         public void actionPerformed(ActionEvent e) 
         { 
            buttonEnter_actionPerformed(e); 
         }  
      });
   }


   private void addComponent(Container container, Component c, int x, int y,
         int width,int height) 
   { 
      c.setBounds(x,y,width,height); 
      container.add(c); 
   } 

   private void buttonSend_actionPerformed(ActionEvent e) 
   {
      // Se non e' stato inserito alcun messaggio, nulla da fare
      if (txtMessage.equals("")) return;

      try
      {
         // Il client invia il messaggio al Server e ripulisce il campo txtMessage
         client.sendMessage(txtNick.getText()  + ": " + txtMessage.getText());
         txtMessage.setText("");
      }
      catch (Exception ex)
      {
         ex.printStackTrace() ;
      }  
   }

   private void joinToChat()
   {
      // Verifica che sia stato inserito un Nick
      if (txtNick.getText().equals("")) return;

      // Crea un client di tipo JChatClient
      client = new JChatClient();

      try
      {
         // Il client instaura una connessione con il Server (JChatServer)
         client.start();

         // Il client richiede al Server di aggiungere alla lista dei Client
         //  connessi, il nuovo utente (ovvero il suo IP)
         client.sendMessage("~" + txtNick.getText());

         // Si legge il messaggio ricevuto dal server
         String strReceived = client.receiveMessage();
         System.out.println(strReceived);

         // Se il server risponde dicendo che il Nick inserito è gia' presente
         // allora si mostra un messaggio di errore, si cancella il nick
         // scelto e si chiude la connessione con il server
         if(strReceived.startsWith("NOGOODUSER"))
         {
            // Inserire qui una eventuale JDialog che avvisi l"utente che
            // si è scelto un nick gia' in uso da qualcun altro
            //.....
            
 
            txtNick.setText("");
            disconnect();
            return;
         }

         // Se il Server risponde al Client OK allora è possibile caricare
         // la lista degli utenti, inserire il nickname in tale lista e
         // iniziare ad utilizzare la Chat
         if(strReceived.startsWith("OKNEWUSER"))
         {
            strReceived  = strReceived.substring(9); // Ricava la lista utenti

            if(! strReceived.equals("") )
            {
               String[] users = strReceived.split("~"); 
               for (int i = 0; i < users.length ; i++)
               {
                  listModel.insertElementAt(users[i],listModel.getSize());
               }
            }
            else
            {
               listModel.insertElementAt(txtNick.getText(),listModel.getSize());
            }

            txtMessage.setEnabled(true);
            buttonSend.setEnabled(true);
            buttonEnter.setText("Esci");
            txtNick.setEnabled(false);

            // Parte il thread per restare in ascolto
           isClientConnected = true;
           startReceiveThread(); 
         } 
      }
      catch (Exception exc)
      {
         System.out.println("Eccezione durante la creazione del client");
         exc.printStackTrace() ;
      }
   }

   private void disconnect()
   {
      try
      {
         client.sendMessage("^" + txtNick.getText());
         txtNick.setText("");
         txtNick.setEnabled(true);
         buttonEnter.setText("Entra in Chat!");
         listModel.removeAllElements() ;
         txtChat.setText("");
         txtMessage.setText("");
         txtMessage.setEnabled(false);
         buttonSend.setEnabled(false);
         isClientConnected = false;
         client.close();
      }
      catch (Exception ex)
      {
         ex.printStackTrace();
      }
   }


   private void buttonEnter_actionPerformed(ActionEvent e) 
   {
      if (buttonEnter.getText().equals("Entra in Chat!") )
         joinToChat();
      else
         disconnect();
   }	


   private void startReceiveThread()
   {
      ParallelClient toRun = new ParallelClient();
      Thread rcvThread = new Thread(toRun);
      rcvThread.start();
   }


   public class ParallelClient implements Runnable 
   {
      public void run()
      {
         String strLastText;
         String strReceived;
         while(isClientConnected)
         {
            try
            {
               strReceived = client.receiveMessage();

               // Se la stringa ricevuta è null, probabilmente
               // il client e' stato disconnesso. Alla successiva iterazione
               // verrà concluso il ciclo while.
               if (strReceived == null)
                  continue;
		 			
               // E' possibile che nel frattempo sia giunto un nuovo utente
               // In tal caso il server inviera' una stringa che inizia con
               // NEWUSER. Altrimenti bastera' inserire il messaggio del server
               // nella TextArea e ripulire il campo txtMessage
               if(strReceived.startsWith("NEWUSER"))
               {
                  // In tal caso bisognera' inserire un nuovo utente
                  // nella lista degli utenti.
                  listModel.insertElementAt(strReceived.substring(7),
                        listModel.getSize());
                  strLastText=txtChat.getText().equals("")?""
                         : txtChat.getText() + "\n";
                  txtChat.setText(strLastText + strReceived.substring(7) + 
                     " è entrato in chat\n");	
               }
               else if (strReceived.startsWith("REMOVEUSER"))
               {
                  // In tal caso bisognera' rimuovere l'utente disconnesso
                  // dalla lista degli utenti.
                  listModel.removeElement(strReceived.substring(10));
               }
               else
               {
                  strLastText =  txtChat.getText().equals("") ? ""
                        : txtChat.getText() + "\n";
                  txtChat.setText(strLastText + strReceived);
               }
            }
            catch (Exception exc)
            {
               exc.printStackTrace();
            }				
         }
      }
   }
}