import ListaCurso;
import PanelCurso;
import ReceptorEventos;
import Oyente;
import InfoTertulia;

import java.awt.*;
import java.net.*;
import java.io.*;
import java.util.*;

public class ServidorAteneo extends Frame implements Runnable,ReceptorEventos
{
  public static int TAMX = 400;
  public static int TAMY = 300;
  public static int puerto = 4321;

  protected ListaCurso lisMensajes;
  protected Label etqEstado;
  Thread hilo = null;
  protected Vector lisConexiones;
  protected Hashtable lisClientes, lisTertulias;
  
  public static void main( String args[] )
  {
     new ServidorAteneo();
  }

  public ServidorAteneo( )
  {
     super("Servidor de Tertulias");

     creaControles();
     inicializar();
     resize(TAMX,TAMY);
     show();
  }

  public void creaControles()
  {
     etqEstado = new Label(" Linea de estado");

     lisMensajes = new ListaCurso(true);
     lisMensajes.setBackground( Color.white );
     lisMensajes.setFont( new Font("Dialog",Font.BOLD,12) );

     Panel panelSup = new PanelCurso(PanelCurso.BORDE_HUNDIDO,5);
     panelSup.setLayout( new BorderLayout() );
     panelSup.add("Center",lisMensajes);

     Panel panelInf = new PanelCurso(PanelCurso.BORDE_RESALTADO,3);
     panelInf.setLayout( new BorderLayout() );
     panelInf.add("Center",etqEstado);
     panelInf.add("East", new Button("Cerrar") );

     setLayout( new BorderLayout() );
     add("Center", panelSup);
     add("South", panelInf);
  }                                   

  public void inicializar( ) {
     lisConexiones = new Vector();
     lisClientes = new Hashtable();
     lisTertulias = new Hashtable();
     hilo = new Thread(this);
     hilo.start();
  }

  public void finalizar( ) {
     if((hilo!=null) && hilo.isAlive()) hilo.stop();
  }

  public void run( ) {
     etqEstado.setText(" Instalando el servidor...");
     try {
       ServerSocket ss = new ServerSocket(Oyente.puerto);
       etqEstado.setText(" Servidor instalado en puerto "+puerto+".");
       while(true) {
          Socket s = ss.accept();
          lisMensajes.addItem("Nueva Conexion: "+s);
          Oyente o = new Oyente(this);
          if(o.conectar(s))
            lisConexiones.addElement(o);
          else
            lisMensajes.addItem("Conexion anterior erronea.");
       }
     } catch(IOException e) {
       etqEstado.setText(""+e);
     }
  }

  public synchronized void nuevoEvento( Object fuente, int idEvt, String[] args ) {
     switch( idEvt ) {

        case EXT_ALTA :
           if( lisClientes.containsKey(args[0]) ) {
             String[] a = {"Ya existe un cliente usando el nombre ["+args[0]+"]."};
             ((Oyente) fuente).enviarEvento(EXT_AVISO,a);
           } else {
             lisMensajes.addItem("Alta del cliente ["+args[0]+"].");
             lisClientes.put(args[0],fuente);
             lisConexiones.removeElement(fuente);
             String[] a = {args[0]};
             ((Oyente) fuente).enviarEvento(EXT_ALTA,a);
             Enumeration e = lisTertulias.keys();
             while(e.hasMoreElements()) {
                a[0] = (String) (e.nextElement());
                ((Oyente) fuente).enviarEvento(EXT_ALTATER,a);
             }              
           }
           break;

        case EXT_BAJA :
           lisMensajes.addItem("Baja del cliente ["+args[0]+"].");
           lisConexiones.addElement(fuente);
           lisClientes.remove(args[0]);
           break;

        case EXT_PROTER : {
           if(lisTertulias.containsKey(args[1])) {
              String[] a = {"Ya existe una tertulia llamada ["+args[1]+"]"};
              ((Oyente) fuente).enviarEvento(EXT_AVISO,a);
           } else {
              lisTertulias.put(args[1],new InfoTertulia(args[1]));
              String[] a = {args[1]};
              Enumeration e = lisClientes.elements();
              while(e.hasMoreElements())
                 ((Oyente) (e.nextElement())).enviarEvento(EXT_ALTATER,a);
           }
        }  break;

        case EXT_CLITER : {
           InfoTertulia ter = (InfoTertulia) (lisTertulias.get(args[1]));
           if(ter.votando) {
             String[] a = {"La tertulia no puede atenderle en este momento,"+
                           " intentelo dentro de un rato."};
             ((Oyente) fuente).enviarEvento(EXT_AVISO,a);
             
           } else {
             ter.nuevaVotacion((Oyente) fuente, args[0] );
           }
        }  break;

        case EXT_VOTO : {
           InfoTertulia ter = (InfoTertulia) (lisTertulias.get(args[0]));
           ter.nuevoVoto(args[1]);
        }  break;

        case EXT_LINEA : {
           InfoTertulia ter = (InfoTertulia) (lisTertulias.get(args[1]));
           ter.nuevaLinea(args[0],args[2]);
        }  break;

        case EXT_FINTER : {
           InfoTertulia ter = (InfoTertulia) (lisTertulias.get(args[1]));
           if(ter.votando) {
              String[] a = {"Debe esperar a que finalize la votacion."};
              ((Oyente) fuente).enviarEvento(EXT_AVISO,a);
           } else {
              ter.lisClientes.remove(args[0]);
              String[] a = {"El cliente <"+args[0]+"> abandona la tertulia."};
              ((Oyente) fuente).enviarEvento(EXT_FINTER,null);
              Enumeration e = ter.lisClientes.elements();
              while(e.hasMoreElements())
                 ((Oyente) (e.nextElement())).enviarEvento(EXT_AVISO,a);
           }          
        } break;

        case EXT_PROVOT : {
           InfoTertulia ter = (InfoTertulia) (lisTertulias.get(args[1]));
           if(ter.votando) {
              String[] a = {"Espere a que termine la votacion actual."};
              ((Oyente) fuente).enviarEvento(EXT_AVISO,a);
           } else {
              ter.nuevaVotacion(args[2]);
           }
        }  break;

        case EVT_CORTE : 
           if(lisConexiones.contains(fuente)) {
              lisConexiones.removeElement(fuente);
              lisMensajes.addItem("Corte de la conexion: "+fuente);
           } else {
              Enumeration e1 = lisClientes.keys();
              Enumeration e2 = lisClientes.elements();
              while( e2.nextElement() != fuente ) e1.nextElement();
              String clave = (String) e1.nextElement();
              lisClientes.remove(clave);

              Enumeration e3 = lisTertulias.elements();
              while( e3.hasMoreElements() ) {
                 Hashtable h = (Hashtable) e3.nextElement();
                 if(h.containsKey(clave)) {
                    h.remove(clave);
                    String[] a = {"El cliente <"+clave+"> abandona la tertulia."};
                    Enumeration e4 = h.elements();
                    for( ;  e4.hasMoreElements() ; )
                      ((Oyente) (e4.nextElement())).enviarEvento(EXT_AVISO,a);
                    break;
                 }
              }
              lisMensajes.addItem("Corte de la conexion del cliente <"+clave+">");
           }
           break;

        default:
          etqEstado.setText("Mensaje no soportado: "+idEvt);
     }
  }

  public boolean handleEvent( Event evt )
  {
     if (evt.id == Event.WINDOW_DESTROY) {
        finalizar();
        System.exit(0);
     } else
     if ((evt.target instanceof Button) && (evt.arg.equals("Cerrar")))
     {
       finalizar();
       System.exit(0);
     }

     return( super.handleEvent(evt) );
  }
}


