//   Course Number: COSC 645 Applied Cryptography
//    Program Name: GetSharesClient.java
//         Authors: Brian Hoffman
//                  Derek Waby
//                  Kypros Ioannou
//                  Harsha V. Reddy
//     Description: This class implements a network client whose task is to 
//                  contact a ShamirServer and obtain a secret share. The program 
//                  provides a simple GUI where the user can enter the address
//                  and port number of the server and hit a request share 
//                  button to transmit a request for a single share to the 
//                  server. When received back from the server, the share is
//                  conveniently displayed in a set of text fields. The share
//                  can then be saved using a save button at the bottom of the
//                  GUI. Finally, the GUI can be cleared by hitting the clear
//                  button. 

// Java Core Packages
import java.awt.*;
import java.awt.event.*;
import java.io.*;
import java.net.*;
import java.util.ArrayList;
import java.math.BigInteger;

// Jave Extension Packages 
import javax.swing.*;
import javax.swing.border.*;

public class GetSharesClient extends JFrame
{ 
    // private class variables
    public final static int DEFAULT_PORT = 4567;
    private File saveDir = new File(".");
    
    // gui components
    private Container container;
    private GriddedPanel requestPanel;
    private GriddedPanel inputPanel;
    private JLabel serverAddLabel;
    private JTextField serverAddField;
    private JLabel serverPortLabel;
    private JTextField serverPortField;
    private JLabel shareXLabel;
    private JTextField shareXField;
    private JLabel shareYLabel;
    private JTextArea shareYArea;
    private JLabel primeLabel;
    private JTextArea primeArea;
    private JPanel buttonPanel;
    private JButton requestButton;
    private JButton clearButton;
    private JButton saveButton;
    
    // ------------------------------------------------------------------------
    // constructor - sets up the GUI
    //-------------------------------------------------------------------------
    public GetSharesClient()
    {
        // title the window 
        super("Request Shamir Secret Shares");
        
        // get content pane and set layout
        container = getContentPane();
        container.setLayout(new BorderLayout());
        
        // create components for the request panel
        serverAddLabel = new JLabel("Enter Server's Address");
        serverAddField = new JTextField(20);
        serverPortLabel = new JLabel("Enter Port Number");
        serverPortField = new JTextField(5);
        serverPortField.setText(Integer.toString(DEFAULT_PORT));
        shareXLabel = new JLabel("X:");
        shareXField = new JTextField(20);
        shareYLabel = new JLabel("Y:");
        shareYArea = new JTextArea(5,20);
        primeLabel = new JLabel("Prime:");
        primeArea = new JTextArea(5,20);
        requestButton = new JButton("Request Share");
        requestButton.addActionListener(new RequestButtonHandler());
        clearButton = new JButton("Clear");
        clearButton.addActionListener(new ClearButtonHandler());
        saveButton = new JButton ("Save");
        saveButton.addActionListener(new SaveButtonHandler(this));

        // add components to the requestPanel
        requestPanel = new GriddedPanel();
        requestPanel.setBorder(BorderFactory.createTitledBorder(
                               BorderFactory.createEtchedBorder(), "The Share",
                               TitledBorder.CENTER, TitledBorder.TOP ));           
        requestPanel.addComponent(shareXLabel, 1, 1);
        requestPanel.addFilledComponent(shareXField, 1, 2, 2, 1,
                                       GridBagConstraints.HORIZONTAL);
        requestPanel.addComponent(shareYLabel, 2, 1);
        requestPanel.addFilledComponent(new JScrollPane(shareYArea), 2, 2, 2, 2,
                                       GridBagConstraints.BOTH);
        requestPanel.addComponent(primeLabel, 4, 1);
        requestPanel.addFilledComponent(new JScrollPane(primeArea), 4, 2, 2, 2,
                                       GridBagConstraints.BOTH);

        // add components to the inputPanel
        inputPanel = new GriddedPanel();
        inputPanel.addComponent(serverAddLabel, 1, 1, 3, 1);
        inputPanel.addFilledComponent(serverAddField, 2, 2, 2, 1,
                                       GridBagConstraints.HORIZONTAL);
        inputPanel.addComponent(serverPortLabel, 3, 1, 3, 1);
        inputPanel.addFilledComponent(serverPortField, 4, 2, 2, 1,
                                       GridBagConstraints.HORIZONTAL);
        inputPanel.addFilledComponent(requestPanel, 5, 2, 2, 1,
                                       GridBagConstraints.BOTH);
        container.add(inputPanel, BorderLayout.CENTER);
        
        // build the button panel and add it 
        buttonPanel = new JPanel(new GridLayout(1,3));
        buttonPanel.add(requestButton);
        buttonPanel.add(clearButton);
        buttonPanel.add(saveButton);
        container.add(buttonPanel, BorderLayout.SOUTH);
        
        // display the initial GUI
        pack();
        setVisible(true);   
    }
    
    // ------------------------------------------------------------------------
    // RequestButtonHandler
    //-------------------------------------------------------------------------
    private class RequestButtonHandler implements ActionListener
    {
        public void actionPerformed(ActionEvent event)
        {
            ClientConnection connection = new ClientConnection(serverAddField.getText(),
                                            Integer.parseInt(serverPortField.getText()));
            ShamirMsg shareRequest;
            ShamirMsg shareReturned;
            
            // check if the connection was successful
            if (!connection.connect())
            {
                JOptionPane.showMessageDialog(null, "Error connecting to server!", 
                                  "Connection Error", JOptionPane.ERROR_MESSAGE);
                return;
            }
      
            // send a request for share message
            try
            {
                // send request
                shareRequest = new ShamirMsg("requestShare");
                connection.sendObject(shareRequest);
                
                // read reply
                shareReturned = (ShamirMsg) connection.readObject();
            
                // display reply
                shareXField.setText(shareReturned.getX().toString());
                shareYArea.setText(shareReturned.getY().toString());
                primeArea.setText(shareReturned.getPrime().toString());
                
                // send termination message
                connection.sendObject(new ShamirMsg("terminate"));
            }
            catch(Exception e)
            {
                JOptionPane.showMessageDialog(null, "Error requesting share!", 
                                  "Share Request Error", JOptionPane.ERROR_MESSAGE);
                e.printStackTrace();
            }
            finally
            {
                connection.close();
            }
        }
    } 
    
    // ------------------------------------------------------------------------
    // ClearButtonHandler
    //-------------------------------------------------------------------------
    private class ClearButtonHandler implements ActionListener
    {
        public void actionPerformed(ActionEvent event)
        {
            serverAddField.setText("");
            serverPortField.setText(Integer.toString(DEFAULT_PORT));
            shareXField.setText("");
            shareYArea.setText("");
            primeArea.setText("");
        }
    }
    // ------------------------------------------------------------------------
    // SaveButtonHandler
    //-------------------------------------------------------------------------
    private class SaveButtonHandler implements ActionListener
    {
        private JFrame parent;
        
        public SaveButtonHandler(JFrame inFrame)
        {
            parent = inFrame;
        }
        
        public void actionPerformed(ActionEvent event)
        {
            // open a file chooser dialog and get the input file
            JFileChooser chooser = new JFileChooser();
            chooser.setFileSelectionMode(JFileChooser.FILES_ONLY);
            chooser.setCurrentDirectory(saveDir);
            if(chooser.showSaveDialog(parent) != JFileChooser.APPROVE_OPTION)
                return;
            File fileName = chooser.getSelectedFile();
            saveDir = new File(fileName.getParent());
            
            // check that the file name is valid
            if (fileName == null || fileName.getName().equals(""))
            {
                JOptionPane.showMessageDialog(parent, "Invalid File Name",  
                       "Invalid File Name", JOptionPane.ERROR_MESSAGE);
                return;
            }
            
            // setup file variables
            FileWriter theFile;
            PrintWriter outFile = null;
            
            try
            {
                theFile = new FileWriter(fileName);
                outFile = new PrintWriter(theFile);
                outFile.println(shareXField.getText());
                outFile.println(shareYArea.getText());
                outFile.println(primeArea.getText());
            }
            
            // deal with any io problems
            catch (IOException ioException)
            {
                JOptionPane.showMessageDialog(null, "Error writing to file!", 
                                  "File Read Error", JOptionPane.ERROR_MESSAGE);
                ioException.printStackTrace();
            }
            
             // close the file stream
            finally 
            {
               if (outFile != null) outFile.close();                  
            } // end finally           
        } // end ActionPerformed
    } // end SaveButtonHandler
    
    // ------------------------------------------------------------------------
    // main - executes application
    //------------------------------------------------------------------------- 
    public static void main (String args[])
    {
        GetSharesClient application = new GetSharesClient();
        application.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
    }       
}
