/*
 * CS255: Programming Project #1
 *
 * AuthorityServer.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 AuthorityServer implements ActionListener {

    // GUI components
    private JFrame mainFrame;
    private JPanel inputPanel;
    private JPanel buttonPanel;
    private JPanel messagePanel;
    private JLabel masterpwdLabel;
    private JLabel portLabel;
    private JLabel encpasswdLabel;
    private JPasswordField masterpwdField;
    private JTextField portField;
    private JTextField encpasswdField;
    private JButton submitButton;
    private JScrollPane messageScrollPane;
    private JTextArea messageArea;
    
    // Sockets for network connection
    private ServerSocket serverSocket;
    
    //
    // Your variable declarations (if any) can go here:
    //    
    
    public AuthorityServer() {
        InitComponents();
 
        //
        // Your initialization code (if any) can go here:
        //    
    }

    /**
     * Initialize GUI components
     * 
     */
    private void InitComponents() {        
        inputPanel = new JPanel(new GridLayout(3, 2, 10, 5));
        masterpwdLabel = new JLabel("Master password");
        masterpwdField = new JPasswordField();
        portLabel = new JLabel("Server port");
        portField = new JTextField();
        encpasswdLabel = new JLabel("Read protected passwords from");
        encpasswdField = new JTextField("passwd.enc");
        buttonPanel = new JPanel();
        messagePanel = new JPanel();
        inputPanel.add(masterpwdLabel);
        inputPanel.add(masterpwdField);
        inputPanel.add(portLabel);
        inputPanel.add(portField);
        inputPanel.add(encpasswdLabel);
        inputPanel.add(encpasswdField);
        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("AuthorityServer");
        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.
    * 
    */  
    public void actionPerformed(ActionEvent event) {
        
        // Disable the input fields and the button
        masterpwdField.setEnabled(false);
        portField.setEnabled(false);
        encpasswdField.setEnabled(false);
        submitButton.setEnabled(false);
        
        // Start a thread that waits for network connections
        new Listener().start();
    }

    private class Listener extends Thread
    {
        public void run ()
        {
            // Store values provided by GUI into variables
            char[] masterpwd = masterpwdField.getPassword();
            String port = portField.getText();
            String encpasswdfile = encpasswdField.getText();
            
            // Open a socket for incoming connections 
            try {
                serverSocket = new ServerSocket(Integer.parseInt(port));
            }
            catch (NumberFormatException nfx) {
                System.out.println(nfx.getMessage());
        	nfx.printStackTrace();            
            }
            catch (IOException iox) {
                System.out.println(iox.getMessage());
                iox.printStackTrace();
            }
            
            //
            // Your code (if any) for the initialization of the AuthorityServer 
            // after the submit button is clicked can go here. This code is
            // executed only once, after the server parametars have been entered
            // and before any clients have connected.
            //  
            
        
            // Wait for clients
            Socket clientSocket = null;
            while(true) {
        	    try {
                	clientSocket = serverSocket.accept();
                    }         
                    catch (IOException iox) {
                        System.out.println(iox.getMessage());
                        iox.printStackTrace();
                    }
                    messageArea.append("Client connected: ");
                    messageArea.append(clientSocket.getInetAddress().toString());
                    messageArea.append("\n");
                    
        	    // Spawn new thread to handle the client request.
                    // Depending on your design you might want to pass more
                    // parametars to the AuthorityServerThread.
                    new AuthorityServerThread(clientSocket, masterpwd, encpasswdfile).start();
            }
        }
        
        protected void finalize ()
        {
            // Close the socket
            try {
                serverSocket.close();
            }
            catch(IOException iox) {
                System.out.println(iox.getMessage());
                iox.printStackTrace();	    
            }
        }
    }    
    
    /**
     * Create the GUI and show it. 
     */
    private static void createAndShowGUI() {
        JFrame.setDefaultLookAndFeelDecorated(true);
        AuthorityServer server = new AuthorityServer();
    }

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