/********************************************************
* Speaker Verification Implemented Security             *
* CA4 Project                                           *
* Written by: Ronan Crowley (97084603)                  *
*        and  Paul Connolly (97307599)                  *
********************************************************/

import java.io.*;
import java.net.*;
import java.awt.*;
import java.awt.event.*;
import javax.swing.*;
import java.util.*;

public class Server extends JFrame {
  private String username;
  private JTextArea display;
  private String message="";
  private String resetValue="";
  private String resetValue1="";
  private double threshold;
  ObjectOutputStream output;    //Stream for writing data
  ObjectInputStream input;      //Stream for reading data

  /** The constructor which initialises the GUI **/
  public Server()
  {
    super("Server");

    Container c = getContentPane();

    display=new JTextArea();
    c.add(new JScrollPane(display), BorderLayout.CENTER);
    setIconImage(Toolkit.getDefaultToolkit().createImage(Server.class.getResource("sv.gif")));
    setSize(300,250);
    show();
  }

  //=========================================================================================================

  /** Initial Server configuration and Client Connection **/  
  public void runServer()
  {
    ServerSocket server;
    Socket connection;
    int counter=1;

    try {
      //Socket connection = new Socket (port, max number of connections);
      server = new ServerSocket (5000,100);

      while (true) {
        display.setText("waiting for connection \n");

        //Listen for a conection from a client. waits here till client connects
        connection=server.accept();

        display.append("Connection "+counter+" received from "+
        connection.getInetAddress().getHostName());

        output = new ObjectOutputStream(
        connection.getOutputStream());

        //This method sends stream header
        output.flush();
        input= new ObjectInputStream(connection.getInputStream() );
        display.append("\nGot I/O streams \n");

        do{
          try{
            message= (String) input.readObject();

            //System.out.println(message);
            String username = message.substring(1,message.length());

            if (message.charAt(0)=='#') {
                //Logon Process......
                display.append("\nUser "+username+" logging in !");
                display.setCaretPosition(display.getText().length());
                logonProcess(username);
            }

            else if (message.charAt(0)=='*')    {
                //New User Process......
                //username = message.substring(1,message.length());
                display.append("\nUser "+username+" being created !");
                display.setCaretPosition(display.getText().length());
                newUserProcess(username);                         
            }

            else if (message.charAt(0)=='!')    {
                //Threshold Process......
                display.append("\nUser "+username+" setting threshold !");
                display.setCaretPosition(display.getText().length());
                thresholdProcess(username);
            }
          
          }
          catch (ClassNotFoundException cnfex){
            display.append ("\nUnknown object type received");
          }
        } while (!message.equals("TERMINATE") );

        display.append("\nUser terminated connection");
        output.close();
        input.close();
        connection.close();

        ++counter;
        }
    }
    catch (EOFException eof){
      System.out.println("Client terminated connection");
    }
    catch (IOException io){
      io.printStackTrace();
    }
  }

  //***************************************logonProcess*****************************************************

  public void logonProcess(String username){

    /** This method is called when a User attempts to Logon **/
    Receivefile r = new Receivefile();
    File userDir = new File("users\\"+username);
    File t = new File("users\\"+username+"\\t.txt"); // Will contain threshold.

    if ((userDir.exists()) && (t.exists()))
    {
        display.append("User: "+username+" logging in.\n");

        generateText testString = new generateText();
        String text = testString.generate();
    
        display.append("Query text sent to "+username+" = "+text+"\n");
        try{
            output.writeObject(text);
        }catch(IOException iol) {
            System.out.println("IO Error in Logon Process");
            iol.printStackTrace();
        }
    
        r.rec("ver.wav");         
        
        Process p;
        char c;
        String holder = new String("");

        try
        {
            p = Runtime.getRuntime().exec("perl verify.pl "+username);
            InputStream o = p.getInputStream();
 
            c = (char)o.read();
 
            while(c != (char)-1)
            {
                holder += c;
                c = (char)o.read();
            }

            //Send the result from the verify perl file
            output.writeObject(holder);
        }
        catch(IOException e)
        {
            System.err.println("Error : " + e.toString());
        }

        //Read t.txt and send threshold !
        try
        {
            BufferedReader thresFile = new BufferedReader(new FileReader("users\\"+username+"\\t.txt"));
            String firstLine = thresFile.readLine();
            output.writeObject(firstLine);
        }
        catch (IOException e) {
           System.err.println("IOException: " + e);
        }

    }
    else if (!userDir.exists())
    {
        display.append("INVALID USER :"+username+"\n");
        try{
            output.writeObject("X");
        }catch(IOException iol) {
            System.out.println("IO Error in Logon Process");
            iol.printStackTrace();
        }
    }
    else
    {
        display.append("NO THRESHOLD FOR :"+username+"\n");
        try{
            output.writeObject("NO_T");
        }catch(IOException iol) {
            System.out.println("IO Error in Logon Process");
            iol.printStackTrace();
        }

    }
  }

  //*************************************newUserProcess*****************************************************

  public void newUserProcess (String username) {

    Receivefile r = new Receivefile();
    //Create the directory to store a new user in
    File newDir = new File("users\\"+username);

    try
    {
        if(newDir.mkdir()) {
            display.append("Adding new user "+username+"\n");
            try{
                output.writeObject("OK");
            }catch(IOException iol) {
                System.out.println("IO Error in New User Process");
                iol.printStackTrace();
            }
            Runtime.getRuntime().exec("perl newUserSetup.pl "+username);

            String name = new String ("");

            //For loop to recieve 17 wav's.....
            for (int i=0; i<17; i++) {
                if (i<9){
                    name = "S000"+(i+1)+".wav";
                }
                else {
                    name = "S00"+(i+1)+".wav";
                }
                r.rec(name);
            }

            File seventeen = new File("S0017.wav");
            if (seventeen.exists())
            {

                //Move 17 WAV's into correct location....
                try {
                    Runtime.getRuntime().exec("perl moveWAVs.pl "+username);
                }catch(Exception ex){
                    ex.printStackTrace();
                }

                Process p1;
                char c1;
                String done = new String ("");

                //Build model.......
                try {
                    display.append("Building Model for: "+username+"\n");
                    p1 = Runtime.getRuntime().exec("perl build.pl "+username);
                    InputStream o1 = p1.getInputStream();

                    c1 = (char)o1.read();

                    while(c1 != (char)-1) {
                        c1 = (char)o1.read();
                        done += c1;
                    }

                    

                    System.out.println("\tModel built !");
                }catch(Exception ex){
                    ex.printStackTrace();
                }

            } // End of .exists()
        
        
        } // End of "if can make directory"
        

        else
        {
            display.append("INVALID USER :"+username+"\n");
            try{
            output.writeObject("Y");
        }catch(IOException iol) {
            System.out.println("IO Error in New User Process");
            iol.printStackTrace();
        }
        }

    }
    catch (Exception ex){
        ex.printStackTrace();
    }
  }

  //************************************thresholdProcess****************************************************

  public void thresholdProcess (String username) {
    Receivefile r = new Receivefile();
    File userDir = new File("users\\"+username);
    File th = new File("users\\"+username+"\\t.txt"); // Will contain threshold.
    
    if ((userDir.exists()) && (th.exists()))
    {
        display.append("Threshold already set for :"+username+"\n");
        try{
            output.writeObject("TH_AL");  //Threshold already set !!
        }catch(IOException iol) {
            System.out.println("IO Error in Threshold Calculation Process");
            iol.printStackTrace();
        }
    }
    else if (!userDir.exists())
    {
        display.append("No such user:"+username+"\n");
        try{
            output.writeObject("NTH");  //Threshold already set !!
        }catch(IOException iol) {
            System.out.println("IO Error in Threshold Calculation Process");
            iol.printStackTrace();
        }
    }
    else 
    {
        //Indicate no error...
        try{
            output.writeObject("OK");
        }catch(IOException iol) {
            System.out.println("IO Error in Threshold Calculation Process");
            iol.printStackTrace();
        }

        String name = new String ("");

        //For loop to recieve 5 wav's.....
        for (int i=0; i<5; i++) {
            name = "T000"+(i+1)+".wav";
            r.rec(name);
        }

            File five = new File("T0005.wav");
            if (five.exists())
            {
                //Move 5 WAV's into correct location....
                try {
                    Runtime.getRuntime().exec("perl moveThWAVs.pl "+username);
                }catch(Exception ex){
                    ex.printStackTrace();
                }

                //5 Verification perl scripts !
                Process p2;
                char c2;
                String done = new String ("");

                //Build threshold.......
                try {
                    p2 = Runtime.getRuntime().exec("perl threshold.pl "+username);
                    InputStream o2 = p2.getInputStream();

                    c2 = (char)o2.read();

                    while(c2 != (char)-1) {
                        c2 = (char)o2.read();
                        done += c2;
                    }

                }catch(Exception ex){
                    ex.printStackTrace();
                }

                //Call calcThreshold.java to calculate threshold......
                calcThreshold thresholdobject = new calcThreshold();
                threshold = thresholdobject.getThreshold(username, 1.2817);  //1.2817 indicates 10% chance of accepting wrong user.
                display.append("Threshold for user: "+username+" set to: "+threshold);

                //Send 2 values from t.txt
                String lineThree = new String("");
                String lineFour = new String("");
                String temp;
                try
                {
                    BufferedReader thresFile = new BufferedReader(new FileReader("users\\"+username+"\\t.txt"));
                    int j=0;

                    while ((temp = thresFile.readLine()) != null) {
                        //Get Values from Line 3 and 4 !
                        if (j==2) {
                            lineThree = temp;
                        }
                        if (j==3)
                        {
                            lineFour = temp;
                        }
                        j++;
                    }
                    output.writeObject(lineThree+";"+lineFour);
                }
                catch (IOException e) {
                   System.err.println("IOException: " + e);
                }

                String passedName;
                double newVal = 0.0;

                // Now recieve summat and set the line 2 in the threshold !
                try{
                    message=(String) input.readObject();
                    System.out.println("1: "+message);

                    int k=0;
                    while (message.charAt(k) != ';'){
                        k++;
                    }
                    passedName = (message.substring(0, k));
                    System.out.println("2: "+passedName);

                    newVal = Double.valueOf(message.substring(k+1, message.length()).trim()).doubleValue();
                    System.out.println("3: "+message.substring(k+1, message.length()));
                    System.out.println("4: "+newVal);

                    calcThreshold myNewThresholdObject = new calcThreshold();
                    double threshold = myNewThresholdObject.getThreshold(passedName, newVal);
                    System.out.println("5: "+threshold);
                }
                catch (ClassNotFoundException cnfex){
                    System.out.println("Unknown object type received");
                }
                catch (EOFException eof) {
                 System.out.println("Server terminated connection");
                }
                catch ( IOException io)
                {
                  io.printStackTrace();
                }
                catch ( NumberFormatException n) {
                    System.out.println("Line 516: "+n);
                }

            }
    }
	th.close();
  }

  //***************************************main*******************************************************

  /** This is the 'main' method in the Server class,
      it runs the Server, by calling the constructor and 
      a listener added so when the window closed, 
      the server is shut down. 
  **/
  public static void main(String args[])
  {
    Server app = new Server();

    app.addWindowListener(
      new WindowAdapter() {
        public void windowClosing (WindowEvent e)
        {
          System.exit(0);
        }
      }
    );

    app.runServer();
  }
}