/********************************************************
* 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.*;   

public class Client extends JFrame {
  BorderLayout Layout1;
  Socket client;
  private static String IPAddress;
  ObjectOutputStream output;
  ObjectInputStream input;
  String message;
  private JTextField jTextField1 = new JTextField();
  private JTextField jTextField2 = new JTextField();
  private JTextField jTextField3 = new JTextField();
  private JButton jLogonButton = new JButton();
  private JButton jNewButton = new JButton();
  private JButton jThresButton = new JButton();
  private JButton jQuitButton = new JButton();
  Icon sv = new ImageIcon("sv.gif");

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

  /** Client constructor -> Sets up GUI **/  
  public Client()
  {
        super ("Client ");

        //Menu Bar......
        JMenuBar jMenuBar1 = new JMenuBar();
        
        //File Menu.......
        JMenu jMenuFile = new JMenu();
        jMenuFile.setText("File");      
        JMenuItem jMenuFileExit = new JMenuItem();
        jMenuFileExit.setText("Exit");
        jMenuFileExit.addActionListener(new ActionListener()  {
            public void actionPerformed(ActionEvent e) {
            jMenuFileExit_actionPerformed(e);
            }
        });
                
        //Help Menu.......
        JMenu jMenuHelp = new JMenu();
        jMenuHelp.setText("Help");
        JMenuItem jMenuHelpAbout = new JMenuItem();
        jMenuHelpAbout.setText("About");
        jMenuHelpAbout.addActionListener(new ActionListener()  {
            public void actionPerformed(ActionEvent e) {
            jMenuHelpAbout_actionPerformed(e);
            }
        });

        //Setup pane
        Container myC = getContentPane();
        GridLayout gridLayout1;
        gridLayout1 = new GridLayout( 4, 3 );
        myC.setLayout(gridLayout1);
        
        //Replace the JavaCup icon in upper-left with our image.
        setIconImage(Toolkit.getDefaultToolkit().createImage(Client.class.getResource("sv.gif")));

        //Setup Window Menu Bar and Menu Items
        jMenuBar1.add(jMenuFile);
        jMenuBar1.add(jMenuHelp);
        jMenuFile.add(jMenuFileExit);
        jMenuHelp.add(jMenuHelpAbout);
        setJMenuBar(jMenuBar1);
                    
        //Add UserName field......
        jTextField1.setBorder(BorderFactory.createRaisedBevelBorder());
        jTextField1.setText("Enter User Name Here");
        jTextField1.setEnabled(true);
        jTextField1.select(0, 20);
        myC.add(jTextField1);

        //Add Logon button !
        jLogonButton.setText("Logon");
        jLogonButton.setEnabled(false);
        jLogonButton.setToolTipText("Logon once User has been created and Threshold set.");
        myC.add(jLogonButton);
        jLogonButton.setMnemonic('l');
        jLogonButton.addActionListener(new ActionListener()  {
            public void actionPerformed(ActionEvent e) {
            jLogonButton_actionPerformed(e);
            }
        });

        //Add UserName field......
        jTextField2.setBorder(BorderFactory.createRaisedBevelBorder());
        jTextField2.setText("Enter User Name Here");
        jTextField2.setEnabled(true);
        jTextField2.select(0, 20);
        myC.add(jTextField2);

        //Add New User button !
        jNewButton.setText("New User");
        jNewButton.setEnabled(false);
        jNewButton.setToolTipText("Create a New User in the System");
        myC.add(jNewButton);
        jNewButton.setMnemonic('n');
        jNewButton.addActionListener(new ActionListener()  {
            public void actionPerformed(ActionEvent e) {
            jNewButton_actionPerformed(e);
            }
        });

        //Add UserName field......
        jTextField3.setBorder(BorderFactory.createRaisedBevelBorder());
        jTextField3.setText("Enter User Name Here");
        jTextField3.setEnabled(true);
        jTextField3.select(0, 20);
        myC.add(jTextField3);

        //Add New User button !
        jThresButton.setText("Set Threshold");
        jThresButton.setEnabled(false);
        jThresButton.setToolTipText("Once New User Added, press here to set threshold of acceptance.");
        myC.add(jThresButton);
        jThresButton.setMnemonic('s');
        jThresButton.addActionListener(new ActionListener()  {
            public void actionPerformed(ActionEvent e) {
            jThresButton_actionPerformed(e);
            }
        });

        //Add Quit button !
        jQuitButton.setText("QUIT");
        jQuitButton.setEnabled(false);
        jQuitButton.setToolTipText("Exit Speaker Verification System.");
        myC.add(jQuitButton);
        jQuitButton.setMnemonic('q');
        jQuitButton.addActionListener(new ActionListener()  {
            public void actionPerformed(ActionEvent e) {
            jQuitButton_actionPerformed(e);
            }
        });

        setTitle("Speaker Verification Implemented Security");
        setLocation(150, 150);
        setSize(400, 200);
        show();
  }

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

  /** Initial Client configuration and Server Connection **/  
  public void runClient()
  {

    try {
      System.out.println("Attempting connection\n");
      client = new Socket(InetAddress.getByName(IPAddress),5000);

      System.out.println("Connected to : "+ client.getInetAddress().getHostName());
      output = new ObjectOutputStream(client.getOutputStream());
      output.flush();
      input= new ObjectInputStream(client.getInputStream() );
      System.out.println("\nGot I/O streams\n");
      jLogonButton.setEnabled(true);
      jNewButton.setEnabled(true);
      jThresButton.setEnabled(true);
      jQuitButton.setEnabled(true);
    }
    catch (EOFException eof) {
      System.out.println("Server terminated connection");
    }
    catch ( IOException e)
    {
      e.printStackTrace();
    }
  }

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

  /** Kills Server Connection **/  
  public void stopClient()
  {
    try {
        output.close();
        client.close();
    }
    catch (EOFException eof) {
      System.out.println("Server terminated connection");
    }
    catch ( IOException e)
    {
      e.printStackTrace();
    }
  }

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

  /** Method for Sending a String to the Server
      @param s The String to Send
  **/  
  private void sendString(String s)
  {
    try {
      output.writeObject(s);
      output.flush();
    }
    catch (EOFException eof) {
      System.out.println("Server terminated connection");
    }
    catch ( IOException e ) {
      e.printStackTrace();
    }
  }

  
    // ******** Menu Commands ********* //
    /** File -> Exit (Stops the Client and Shuts down the Application) **/
    public void jMenuFileExit_actionPerformed(ActionEvent e) {
        stopClient();
        System.exit(0);
    }

    /** Help -> About (Shows the Project About* Box)    *=Aboot Box in Canada **/
    public void jMenuHelpAbout_actionPerformed(ActionEvent e) {
        AboutBox abt = new AboutBox(this);
        Dimension boxSize = abt.getPreferredSize();
        Dimension frmSize = getSize();
        Point loc = getLocation();
        abt.setLocation((frmSize.width - boxSize.width) / 2 + loc.x, (frmSize.height - boxSize.height) / 2 + loc.y);
        abt.setModal(true);
        abt.show();
    }

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

    /** Logon Button -> Ensures user exists, recieves randomly generated test case and presents a test window. **/
    public void jLogonButton_actionPerformed(ActionEvent e) {
        
        if (!jTextField1.getText().equals("Enter User Name Here"))// && (t.exists()))
        {
          sendString("#"+jTextField1.getText());    // The leading # indicates that this is a logon Process.
        }
        
        try{
            //Recieve Random Text / No user message
            message=(String) input.readObject();

            if (message.equals("X")){               // "X" message from Server indicates user does not exist.

                //Error Message - No such user
                JOptionPane.showMessageDialog(this, 
                    "Invalid Username.\n\nPlease check your details and re-try.", 
                    "Invalid Username", 1, sv);

            }
            else if (message.equals("NO_T"))
            {
                //Error Message - No Threshold set
                JOptionPane.showMessageDialog(this, 
                    "Threshold for user: "+jTextField1.getText()+
                    " has not been set.\n\nPlease select the \"Set Threshold\" option before logging in.", 
                    "No Threshold Set", 1, sv);
            }
            else //message = "X"
            {
                System.out.println("Randomly Generated text = "+message);

                //Show the Logon Process Dialoude
                Record rec = new Record(input, output, message, this, IPAddress, jTextField1.getText());
                rec.setLocation(100, 100);
                rec.show();
            }
        }
        catch (ClassNotFoundException cnfex){
            System.out.println("Unknown object type received");
        }
        catch (EOFException eof) {
         System.out.println("Server terminated connection");
        }
        catch ( IOException io)
        {
          io.printStackTrace();
        }

    }

    /** New User Button -> Ensures user does not exist already and then presents a new user training window. **/
    public void jNewButton_actionPerformed(ActionEvent e) {
        boolean nospace = true;
        for (int c=0; c<jTextField2.getText().length(); c++)
        {
            if (jTextField2.getText().charAt(c)==' ')
            {
                nospace= false;
            }
        }
        
        if (!nospace)
        {
            //Error Message
            JOptionPane.showMessageDialog(this, 
            "Username cannot contain spaces.\n\nPlease try another.", 
            "Space's not allowed", 1, sv);
        }
        else if ((!jTextField2.getText().equals("Enter User Name Here")) && (nospace) )
        {
          sendString("*"+jTextField2.getText());    // The leading * indicates that this is a create new user Process.

            try {

                message=(String) input.readObject();
                if (!message.equals("Y")){          // "Y" message from Server indicates user already exists.
                    
                    //Present the New User Screen
                    NewUser nu = new NewUser(jTextField2.getText(), this);
                    nu.show();
                }
                else 
                {
                    //Error Message
                    JOptionPane.showMessageDialog(this, 
                    "Username already exists.\n\nPlease try another.", 
                    "User already Exists", 1, sv);
                }                   
            }
            catch (ClassNotFoundException cnfex){
                System.out.println("Unknown object type received");
            }
            catch (EOFException eof) {
                 System.out.println("Server terminated connection");
            }
            catch ( IOException io)
            {
              io.printStackTrace();
            }
        }
    }

    /** Threshold Button -> Ensures user exists already and then presents a new user threshold creation window. **/
    public void jThresButton_actionPerformed(ActionEvent e) {
        if (!jTextField3.getText().equals("Enter User Name Here"))
        {
            // ! indicates Threshold setting for user.
            sendString("!"+jTextField3.getText());
            
            try {

                message=(String) input.readObject();

                if (message.equals("NTH")){
                    
                    //Error message
                    System.out.println("User "+jTextField3.getText()+" does not exist in the system.");
                    JOptionPane.showMessageDialog(this, 
                    "Threshold cannot be set at this time.\n\nUser: "+jTextField3.getText()+
                    " does not exist in the system !\nPlease create a new user (if necessary).",
                    "Threshold cannot be set", 1, sv);
                }
                else if (message.equals("TH_AL"))
                {
                    //Error message
                    System.out.println("User "+jTextField3.getText()+" has already set threshold.");
                    JOptionPane.showMessageDialog(this, 
                    "Threshold cannot be set at this time.\n\nUser: "+jTextField3.getText()+
                    " has already set a threshold !",
                    "Threshold cannot be set", 1, sv);
                }                   
                else    //message.equals("Z")
                {
                    //Present the create threshold screen
                    Threshold th = new Threshold(input, output, jTextField3.getText(), this);
                    th.show();
                }
            }
            catch (ClassNotFoundException cnfex){
                System.out.println("Unknown object type received");
            }
            catch (EOFException eof) {
                 System.out.println("Server terminated connection");
            }
            catch ( IOException io)
            {
              io.printStackTrace();
            }
        }
    }

    /** Quit Button-> Sends the "TERMINATE" String which closes the Client/Server connection. **/
    public void jQuitButton_actionPerformed(ActionEvent e) {
        //SEND: "TERMINATE" String to kill connection !
        sendString("TERMINATE");
        dispose();
        System.exit(0);
    }

  /** Main method. Calls the Client constructor and listens for the window closing, upon which it shuts down the application. **/
  public static void main(String args[])
  {
    //Constructor !
    Client app = new Client();

    if (args.length==0){
        System.out.println("\nUSAGE: java Client IPAddress\n");
        System.out.println("Assuming Default Server Address");
        IPAddress = "136.206.18.129";
    }
    else {
        IPAddress = args[0];
    }

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

    app.runClient();
  }
}