/*
 * CS255: Programming Project #1
 *
 * ClientGUI.java 
 */

//package eLecture;

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

import java.security.*;
import java.security.spec.*;
import java.security.interfaces.*;

import javax.crypto.*;
import javax.crypto.spec.*;
import javax.crypto.interfaces.*;

public class ClientGUI implements ActionListener {

    // GUI components
    private JFrame mainFrame;
    private JPanel inputPanel;
    private JPanel buttonPanel;
    private JPanel messagePanel;
    private JLabel usernameLabel;
    private JLabel userpasswdLabel;
    private JLabel hostLabel;
    private JLabel portLabel;
    private JLabel enccontentLabel;
    private JTextField usernameField;
    private JPasswordField userpasswdField;
    private JTextField hostField;
    private JTextField portField;
    private JTextField enccontentField;
    private JButton submitButton;
    private JScrollPane messageScrollPane;
    private JTextArea messageArea;
    
    // Sockets for network connection
    private Socket clientSocket = null; 
    private DataOutputStream toServer = null;
    private DataInputStream fromServer = null;
    
    //
    // Your variable declarations (if any) can go here:
    //    
    
    public ClientGUI() {
        InitComponents();
 
        //
        // Your initialization code (if any) can go here:
        //    
    }

    /**
     * Initialize GUI components
     * 
     */
    private void InitComponents() {        
        inputPanel = new JPanel(new GridLayout(3, 4, 10, 5));
        usernameLabel = new JLabel("Client username");
        usernameField = new JTextField();
        userpasswdLabel = new JLabel("Client password");
        userpasswdField = new JPasswordField();
        hostLabel = new JLabel("Server host");
        hostField = new JTextField("localhost");
        portLabel = new JLabel("Server port");
        portField = new JTextField();
        enccontentLabel = new JLabel("Read protected content from");
        enccontentField = new JTextField("lecture.enc");
        buttonPanel = new JPanel();
        messagePanel = new JPanel();
        inputPanel.add(usernameLabel);
        inputPanel.add(usernameField);
        inputPanel.add(userpasswdLabel);
        inputPanel.add(userpasswdField);
        inputPanel.add(hostLabel);
        inputPanel.add(hostField);
        inputPanel.add(portLabel);
        inputPanel.add(portField);
        inputPanel.add(enccontentLabel);
        inputPanel.add(enccontentField);
        inputPanel.setBorder(BorderFactory.createEmptyBorder(5, 5, 5, 5));
  
        buttonPanel = new JPanel();
        submitButton = new JButton("Submit");
        submitButton.addActionListener(this);
        buttonPanel.add(submitButton);
  
        messagePanel = new JPanel(new BorderLayout());
        messagePanel.setBorder(BorderFactory.createEtchedBorder());
        messageArea = new JTextArea("Hello\n");
        messageArea.setEditable(false);
        messageScrollPane = new JScrollPane(messageArea);
        messagePanel.add(messageScrollPane);
        
        mainFrame = new JFrame("ClientGUI");
        mainFrame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        mainFrame.getRootPane().setDefaultButton(submitButton);
        mainFrame.getContentPane().setLayout(new GridLayout(3, 0, 10, 10));
        mainFrame.getContentPane().add(inputPanel);
        mainFrame.getContentPane().add(buttonPanel);
        mainFrame.getContentPane().add(messagePanel);        
        mainFrame.pack();
        mainFrame.setVisible(true);
    }

    /**
    * Handle submit button event.
    * 
    */
    private String username;
    private final int RANDOM_NUM_SIZE = 10;
    public void actionPerformed(ActionEvent event) {
        
        // Store values provided by GUI into variables
	    username = usernameField.getText();
        char[] userpasswd = userpasswdField.getPassword();
        String host = hostField.getText();
        String port = portField.getText();
        String enccontentfile = enccontentField.getText();
    
        // Connect to the server
        try {
            clientSocket = new Socket(host, Integer.parseInt(port));
            toServer = new DataOutputStream(clientSocket.getOutputStream());
            fromServer = new DataInputStream(clientSocket.getInputStream());
	}
        catch (NumberFormatException nfx) {
            System.out.println(nfx.getMessage());
	    nfx.printStackTrace();            
        }
        catch (UnknownHostException uhx) {
            System.out.println(uhx.getMessage());
	    uhx.printStackTrace();
        }
        catch (IOException iox) {
	    System.out.println(iox.getMessage());
	    iox.printStackTrace();
        }        
        
        //
        // Most of your code can go here, right now we send the username
        // to the server in the clear and display the reply. Your code should
        // authenticate to the server, obtain the key, and finally decrypt 
        // and display the protected content.
        // 
        // Code Added by Rashmi
        byte[] authToken = null;
        try {
        	SecureRandom prng = SecureRandom.getInstance("SHA1PRNG");
            byte[] randomNumber = new byte[RANDOM_NUM_SIZE];
            prng.nextBytes(randomNumber);
	        prng.setSeed(userpasswd.toString().getBytes());
            // Generate block cipher key
	        KeyGenerator encKeygenBC = KeyGenerator.getInstance("AES");
	        encKeygenBC.init(prng);
	        SecretKey KBC = encKeygenBC.generateKey();
	        
	        // Generate MAC Key
	        KeyGenerator encKeygenMAC = KeyGenerator.getInstance("HmacMD5");
	        encKeygenMAC.init(prng);
	        SecretKey KMAC = encKeygenMAC.generateKey();

            authToken = genAuthToken(KMAC,randomNumber);

        }
        catch(NoSuchAlgorithmException exc){

        }

        String status = null;
        String content = "Don't know yet!\n";

        // Send a message to the server
        try{
            toServer.write(authToken);
        }
        catch(Exception e){
            e.printStackTrace();
        }
        // Receive a message from the server and display it
        String reply = null;
        try {
            reply = fromServer.readLine();
            messageArea.append("Server says: " + reply + "\n");
	}	
	catch(IOException iox) {
            System.out.println(iox.getMessage());
            iox.printStackTrace();
	}
        
        // Close the connection 
	try { 
	    toServer.close();
	    fromServer.close();	    
	    clientSocket.close();
	}
	catch(IOException iox) {
	    System.out.println(iox.getMessage());
	    iox.printStackTrace();
	}	

        // Display the result        
        messageArea.append("The content is: \n" + content);
        mainFrame.repaint();
    }
    private byte[] genAuthToken(SecretKey KMAC, byte[] randomNumber){

        byte[] macRandomNumber = MacMessage.doMac(randomNumber,KMAC);
        byte[] authToken = new byte[randomNumber.length + username.getBytes().length + macRandomNumber.length];
        int k = 0;
        for (int i = 0 ; i < randomNumber.length; i++){
            authToken[k++] = randomNumber[i];
        }
        for (int i = 0; i < username.getBytes().length; i++){
            authToken[k++] = username.getBytes()[i];
        }
        for (int i = 0; i < macRandomNumber.length; i++){
            authToken[k++] = macRandomNumber[i];
        }
        return authToken;

    }

    /**
     * Create the GUI and show it. 
     */
    private static void createAndShowGUI() {
        JFrame.setDefaultLookAndFeelDecorated(true);
        ClientGUI client = new ClientGUI();
    }

    public static void main(String[] args) {
        Runnable GUI = new Runnable() {
            public void run() {
                createAndShowGUI();
            }
        };
        javax.swing.SwingUtilities.invokeLater(GUI);
    }
}
