import java.util.*;
import java.lang.*;
import java.net.*;
import java.io.*;

public class JMPFServer extends Thread
{
   ServerSocket  server_socket;
   InetAddress Address;
   Hashtable jobids = new Hashtable();
   String hostname;
   public static void main(String argv[])
   {
      new JMPFServer();
   }

   public JMPFServer()
   {
      try
      {
         server_socket = new ServerSocket(4578); 
      }
      catch(IOException e)
      {
         System.out.println("Cannot start the Server" + e);
         System.exit(1);
      }
      System.out.println("Server started...");

      try
      {
         Address = InetAddress.getLocalHost();
      }
      catch(UnknownHostException e)
      {
         System.out.println("host : " + e);
      }
      hostname = Address.getHostName();
      System.out.println("hostname is : " + hostname);
      System.out.println("port no is : " + server_socket.getLocalPort());
      InetAddress Address;
      Address = server_socket.getInetAddress();
      System.out.println("address = " + Address);
      this.start();
   }

   public void run()
   {
      try
      {
         while(true)
         {
            Socket client = server_socket.accept();
            connection con = new connection(client,jobids);
         }
      }
      catch(IOException e)
      {
         System.out.println("Not listening" + e);
         System.exit(1);
      }
   }
}

class connection extends Thread
{
   protected Socket net_client;
   protected DataInputStream from_client;
   protected PrintStream to_client;
   Hashtable job_ids;

   static String hostname;
   static InetAddress Address;

   public connection(Socket client, Hashtable jb)
   {
      net_client = client;
      job_ids = jb;

      try
      {
         from_client = new DataInputStream(net_client.getInputStream());
         to_client = new PrintStream(net_client.getOutputStream());
      }
      catch(IOException e)
      {
         try
         {
            System.out.println("Closing net");
            net_client.close();
         }
         catch(IOException e1)
         {
			   System.out.println("Cannot close the client" + e1);
				System.exit(1);
         }
         System.out.println("Unable to set up Streams" + e);
         return;
      }
      this.start();
   }

   public void run()
   {
      String str = null;
      String request;
      String name = null;
      String msg = null;
      int job_id = 0;
      String host_name = "";
      int host_id = 0;
      Enumeration names;
      jobs j_object;
      int j_id;

      try
      {
         request = from_client.readLine();
         j_id = Integer.parseInt(from_client.readLine());
         j_object = get_job_object(j_id);

         if ("hostname".equals(request))
         {
            host_name = from_client.readLine();
            host_id = Integer.parseInt(from_client.readLine());
//            System.out.println("... in server ... hostid is " + host_id);

            String type = from_client.readLine();
            if ("add".equals(type))
            {
               to_client.flush();
               int status = j_object.addtask(host_name, host_id);
//             msg = "The connecting hostname is " + host_name;
            }
            else if ("remove".equals(type))
            {
               int status = j_object.removetask(host_name, host_id);
//             msg = "The disconnecting host is : "+host_name+" id " + host_id;
               to_client.println(host_id);
            }
//            System.out.println(msg);
         }

         else if ("createport_group".equals(request))
         {
            host_name = from_client.readLine();
            host_id = Integer.parseInt(from_client.readLine());
            name = from_client.readLine();
            int group_id = Integer.parseInt(from_client.readLine());

            int status = j_object.createport_group(host_name, host_id, 
                                                               name, group_id);
            to_client.println(status);
//          msg = "The request is to Create a group by name " + name;
         }

         else if ("createport".equals(request))
         {
            host_name = from_client.readLine();
            host_id = Integer.parseInt(from_client.readLine());
            name = from_client.readLine();
            int port_id = Integer.parseInt(from_client.readLine());

            int status = j_object.createport(host_name, host_id, 
                                                            name, port_id);
            to_client.println(status);
//          msg = "The request is to Create a port by name " + name;
         }

         else if ("add_member".equals(request))
         {
            String gp_name = from_client.readLine();
            int pno = Integer.parseInt(from_client.readLine());

            int status = j_object.add_member(gp_name, pno);
            to_client.println(status);
//          msg = "The request is to add member to group " + gp_name;
         }

         else if ("locateport_group".equals(request))
         {
            name = from_client.readLine();

            int group_id = j_object.locateport_group(name);
            host_name = j_object.j_host_name;
            host_id = j_object.j_host_id;

            to_client.println(host_name);
            to_client.println(host_id); 
            to_client.println(group_id);
//          msg = "The request is to Locate a port by name " + name;
         }

         else if ("locateport".equals(request))
         {
            name = from_client.readLine();

            int port_id = j_object.locateport(name);;
            host_name = j_object.j_host_name;
            host_id = j_object.j_host_id;

            to_client.println(host_name);
            to_client.println(host_id);
            to_client.println(port_id);
//          msg = "The request is to Locate a port by name " + name;
         }

         else if ("show_status".equals(request))
         {
            Enumeration vEnum;
            name = from_client.readLine();

            Vector vector = j_object.show_status(name);
            vEnum = vector.elements();

            while (vEnum.hasMoreElements())
            {
               int port_no = ((Integer)(vEnum.nextElement())).intValue();
               to_client.println(port_no);
/*
               if (port_no == 0)
               {
//                msg = "The Hash table is empty... ";
                  to_client.println(port_no);
               }
               else if (port_no == -1)
               {
//                msg = "There is no port group found by the name : " + name;
                  to_client.println(port_no);
               }
               else
               {
                  to_client.println(port_no);
//                msg = "The request is to show status of : " + name;
               }
*/
            }
            to_client.println(-3);
//          System.out.println(msg);
         }

/*
         else if ("names_of_hosts".equals(request))
         {
            Enumeration vEnum;
            name = from_client.readLine();
            to_client.flush();
 
            Vector vector = j_object.names_of_hosts(name);
//            System.out.println("The hosts are ... " + vector);
            vEnum = vector.elements();
 
            while (vEnum.hasMoreElements())
            {
               String ht_name = (String)(vEnum.nextElement());
//               System.out.println("sending hostname ... " + ht_name);
               to_client.println(ht_name);
               msg = "The request is to store the hostnames of : " + name;
            }   
            to_client.println(-3);
//            System.out.println(msg);
         }
*/
         else if ("deleteport_group".equals(request))
         {
            name = from_client.readLine();
            int port_no = j_object.deleteport_group(name);
            to_client.println(port_no);
/*
            if (port_no == 0)
            {
//             msg = "The Hash table is empty... can not Delete " + name;
               to_client.println(port_no);
            }
            else if (port_no == -1)
            {
//             msg = "There is no port group found by the name : " + name;
               to_client.println(port_no);
            }
            else
            {
               to_client.println(port_no);
               msg = "The request is to Remove a port by name " + name;
            }
*/
//            System.out.println(msg);
         }

         else if ("deleteport".equals(request))
         {
            name = from_client.readLine();
            to_client.flush();
            int port_no = j_object.deleteport(name);
            to_client.println(port_no);
//            System.out.println("In server deleting .... : " + port_no);
/*
            if (port_no == 0)
            {
               msg = "The Hash table is empty... can not Delete " + name;
               to_client.println(port_no);
            }
            else if (port_no == -1)
            {
               msg = "There is no port found by the name : " + name;
               to_client.println(port_no);
            }
            else
            {
               to_client.println(port_no);
               msg = "The request is to Remove a port by name " + name;
            }
*/
         }

         else if ("remove_member".equals(request))
         {
            String gp_name = from_client.readLine();
            int pno = Integer.parseInt(from_client.readLine());

            to_client.flush();
            int port_no = j_object.remove_member(gp_name, pno);
            to_client.println(port_no);
/*
            if (port_no == -1)
            {
               msg = "The port not there in the table by name : " + name;
               to_client.println(port_no);
            }
            else
            {
               to_client.println(port_no);
               msg = "The request is to remove member to group " + gp_name;
            }
*/
         }

         else if ("where_to_send".equals(request))
         {
            int pt_id = Integer.parseInt(from_client.readLine());
            String ht_name = j_object.where_to_send(pt_id); 

//          msg = "sending to ......" + ht_name;
            to_client.println(ht_name);
         }
         else
         {
            name = from_client.readLine();
            name = "Request is unknown to the server...";
            to_client.println(name);
//            System.out.println("The request is : " + request);
//            msg = "The request is UNKNOWN to the server...";
         }
//         System.out.println(msg);
      }
      catch(IOException e)
      {
         System.out.println("Cannot change the string" + e);
	      System.exit(1);
      }
      finally
      {
         try 
         {
            net_client.close();
         }
         catch(IOException e)
         {
            System.out.println("The error in closing connection " + e);
         }
      }
   }

   public jobs get_job_object(int job_id)
   {
      Enumeration names;
      jobs object = null;
      boolean found = job_ids.containsKey(new Integer(job_id));
      if (found == false)
      {
         object = new jobs(job_id);

//         System.out.println("The object is ... " + object);
         job_ids.put(new Integer(job_id), object);
      }
      else if (found == true)
      {
         object = (jobs)job_ids.get(new Integer(job_id));
      }

/*
      names = job_ids.keys();
      while(names.hasMoreElements())
      {
         Integer jb_no = (Integer) names.nextElement();
         System.out.println(jb_no + ": " + job_ids.get(jb_no));
      }
*/
      return(object);
   }
}

class jobs
{
   Hashtable task_ids = new Hashtable();
   Hashtable group_ids = new Hashtable();
   Hashtable port_ids = new Hashtable();

   Vector h_vector = new Vector(1,1);

   int job_id;
   String j_host_name;
   int j_host_id;

//   Enumeration names;

   public jobs(int j_id)
   {
      job_id = j_id;
   }

   public int addtask(String host_name, int host_id)
   {
      tasks obj;
      obj = new tasks(host_name, host_id);
//      System.out.println("The object is ... " + obj);
      task_ids.put(new Integer(host_id), obj);

/*
      names = task_ids.keys();
      while(names.hasMoreElements())
      {
         Integer tk_no = (Integer) names.nextElement();
//         System.out.println(tk_no + ": " + task_ids.get(tk_no));
      }
*/
      return(host_id);
   }

   public int removetask(String host_name, int host_id)
   {
      task_ids.remove(new Integer(host_id));
/*
      names = task_ids.keys();
      while(names.hasMoreElements())
      {
         Integer tk_no = (Integer) names.nextElement();
//         System.out.println(tk_no + ": " + task_ids.get(tk_no));
      }
*/
      return(host_id);
   }

   public int createport_group(String host_name,int host_id,
                                              String name,int group_id)
   {
      groups obj = null;
      obj = new groups(host_name, host_id, name, group_id);
      group_ids.put(name, obj);
/*
      names = group_ids.keys();
      while(names.hasMoreElements())
      {
         String str = (String) names.nextElement();
//         System.out.println(str + ": " + group_ids.get(str));
      }
*/
      return(group_id);
   }

   public int createport(String host_name, int host_id, 
                                           String name, int port_id)
   {
      ports obj = null;
      obj = new ports(host_name, host_id, name, port_id);
      port_ids.put(name, obj);
/*
      names = port_ids.keys();
      while(names.hasMoreElements())
      {
         String str = (String) names.nextElement();
//         System.out.println(str + ": " + port_ids.get(str));
      }
*/
      return(port_id);
   }

   public int add_member(String gp_name, int portno)
   {
      Enumeration names;
      String str;
      boolean notfound = false;
      names = port_ids.keys();
      boolean pt_not_found = true;
      int ptno;
      String pt_name = null;

      while(names.hasMoreElements())
      {
         str = (String) names.nextElement();
         ports obj = (ports)port_ids.get(str);
         ptno = obj.port_id;
//         ptno = (Integer)port_ids.get(str);

         if (ptno ==  portno)
         {
            pt_name = str;
            pt_not_found = false;
         }
      }
      if (pt_not_found == true)
         return(-2);

      groups object = (groups)group_ids.get(gp_name);
      names = object.portids.keys();

      boolean not_found = true;

      while(names.hasMoreElements())
      {
         str = (String) names.nextElement();

         if (str.equals(pt_name))
            not_found = false;
      }

      if (not_found == false)
         return(-3);

      int status = object.addportid(pt_name, portno);

      return(status);
   }

   public int locateport_group(String name)
   {
      int group_id;
      Enumeration names = group_ids.keys();

      boolean is_it_empty = group_ids.isEmpty();
      if (is_it_empty == true)
      {
         group_id = 0;
      }

      boolean found = group_ids.containsKey(name);
      if (found == false)
      {
         group_id = -1;
      }
      else
      {
         groups object = (groups)group_ids.get(name);
         group_id = object.Group_id;
         j_host_name = object.host_name;
         j_host_id = object.host_id;
      }
      return(group_id);
   }


   public int locateport(String name)
   {
      int port_id;
      Enumeration names = port_ids.keys();

      boolean is_it_empty = port_ids.isEmpty();
      if (is_it_empty == true)
      {
         port_id = 0;
      }

      boolean found = port_ids.containsKey(name);
      if (found == false)
      {
         port_id = -1;
      }
      else
      {
         ports object = (ports)port_ids.get(name);
         port_id = object.port_id;
         j_host_name = object.host_name;
         j_host_id = object.host_id;
      }
      return(port_id);
   }

   public Vector show_status(String gp_name)
   {
      Enumeration names;
      String str;
      int ptno;
      Vector vector = new Vector(1, 1);
      boolean is_it_empty = group_ids.isEmpty();
 
      if (is_it_empty == true)
      {
         vector.addElement(new Integer(-1));
         return(vector);
      }
      boolean found = group_ids.containsKey(gp_name);
 
      if (found == false)
      {
         vector.addElement(new Integer(-2));
         return(vector);
      }
      else
      {
         groups obj = (groups)group_ids.get(gp_name);
         names = obj.portids.keys();
         while (names.hasMoreElements())
         {
            str = (String) names.nextElement();
            ports object = (ports)port_ids.get(str);
            ptno = object.port_id;
            vector.addElement(new Integer(ptno));
         }
         return(vector);
      }
   }

/*
   public Vector names_of_hosts(String gp_name)
   {
      Enumeration names;
      String ht_name;
      String str;
      Vector vector = new Vector(1, 1);
      boolean is_it_empty = group_ids.isEmpty();

      if (is_it_empty == true)
      {
         vector.addElement(new Integer(-1));
         return(vector);
      }
      boolean found = group_ids.containsKey(gp_name);

      if (found == false)
      {
         vector.addElement(new Integer(-2));
         return(vector);
      }
      else
      {
         groups obj = (groups)group_ids.get(gp_name);
         names = obj.portids.keys();
         while (names.hasMoreElements())
         {
            str = (String) names.nextElement();
            ports object = (ports)port_ids.get(str);
            ht_name = object.host_name;
            vector.addElement(ht_name);
         }
         return(vector);
      }
   }
*/
   public int deleteport_group(String gp_name)
   {
      boolean is_it_empty = group_ids.isEmpty();
      if (is_it_empty == true)
         return(0);
      boolean found = group_ids.containsKey(gp_name);

      if (found == false)
         return(-1);
      else
      {
         groups obj = (groups)group_ids.remove(gp_name);
         if (obj == null)
            return(-1);
         else
            return(1);
      }
   }

   public int deleteport(String s)
   {
      boolean is_it_empty = port_ids.isEmpty();
      if (is_it_empty == true)
         return(0);
      boolean found = port_ids.containsKey(s);

      if (found == false)
         return(-1);
      else
      {
         ports obj = (ports)port_ids.remove(s);
         if (obj == null)
            return(-1);
         else
            return(1);
      }
   }

   public int remove_member(String gp_name, int portno)
   {
      Enumeration names;
      String str;
      boolean found = false;
      boolean not_found = true;
      names = group_ids.keys();
      boolean is_it_empty = group_ids.isEmpty();
      if (is_it_empty == true)
         return(0);
      else
      {
         found = group_ids.containsKey(gp_name);
         if (found == false)
         {
            return(-1);
         }
      }

      names = port_ids.keys();
      boolean pt_not_found = true;
      int ptno;
      String pt_name = null;

      while(names.hasMoreElements())
      {
         str = (String) names.nextElement();
         ports object = (ports)port_ids.get(str);
         ptno = object.port_id;

         if (ptno ==  portno)
         {
            pt_name = str;
            pt_not_found = false;
         }
      }

      if (pt_not_found == true)
         return(-2);

      groups object = (groups)group_ids.get(gp_name);
      names = object.portids.keys();

      while(names.hasMoreElements())
      {
         str = (String) names.nextElement();

         if (str.equals(pt_name))
            not_found = false;
      }

      if (not_found == true)
         return(-3);

      int status = object.removeportid(pt_name);

      return(status);
   }

   public String where_to_send(int portno)
   {
      Enumeration names = port_ids.keys();
      String str;
      int ptno;
      String ht_name = "";

      while(names.hasMoreElements())
      {
         str = (String) names.nextElement();
         ports object = (ports)port_ids.get(str);
         ptno = object.port_id;

         if (ptno ==  portno)
         {
            ht_name = object.host_name;
         }
      }  
      return(ht_name); 
   }
}

class tasks
{
   String task_name;
   int task_id;

   public tasks(String name, int id)
   {
      task_name = name;
      task_id = id;
   }
}

class groups
{
   Hashtable portids = new Hashtable();

   String host_name;
   int host_id;
   String Group_name;
   int Group_id;

   public groups(String hostname, int hostid, String name, int gp_no)
   {
      host_name = hostname;
      host_id = hostid;
      Group_name = name;
      Group_id = gp_no;

//      System.out.println("The group name  is " + Group_name);
//      System.out.println("The group id is " + Group_id);
   }

   public int addportid(String pt_name, int portno)
   {
//      String str;
//      Enumeration names;
//      names = portids.keys();
      portids.put(pt_name, new Integer(portno));
/*
      while(names.hasMoreElements())
      {
         str = (String) names.nextElement();
//         System.out.println(str + ": " + portids.get(str));
      }
*/
      return(portno);
   }

   public int removeportid(String pt_name)
   {
      Integer portno = (Integer) portids.remove(pt_name);

      return(portno.intValue());
   }
}

class ports 
{
   String port_name;
   int port_id;
   String host_name;
   int host_id;

   public ports(String hostname, int hostid, String name, int portno)
   {
      port_name = name;
      port_id = portno;
      host_name = hostname;
      host_id = hostid;
   }
}

