//package IM;

import javax.crypto.Cipher;
import javax.crypto.KeyGenerator;
import javax.crypto.SealedObject;
import javax.crypto.SecretKey;
import javax.crypto.spec.SecretKeySpec;
import javax.crypto.spec.IvParameterSpec;
import java.io.*;
import java.net.Socket;
import java.security.PrivateKey;
import java.security.PublicKey;
import java.security.Signature;
import java.security.SignedObject;
import java.util.Calendar;
import java.math.BigInteger;

class Send {

   
    public static void main(String args[]) {
        try {
            if (args.length < 3) {
                System.out.println("Usage: send <sender> <receiver> <chat>");
                return;
            }

            String receiveaddress = "localhost";
            int receiveport;
            String CAaddress = "localhost";

            FileReader fr = new FileReader("config");
            BufferedReader in = new BufferedReader(fr);
            in.readLine();
            receiveport = Integer.parseInt(in.readLine());
            in.close();
            fr.close();

            if (args.length > 3) {
                receiveport = Integer.parseInt(args[3]);
            }



            //message.set(args[0], args[1], args[2]);

            //The sender's private key file is: message.sender + ".priv"
            //The receiver's public key file is: message.receiver + ".pub"

            //TODO:
            //1. Read sender's private key (e.g. "alice.priv").
            //2. Read receiver's public key and certificate (e.g. "bob.pub").
            //   If the certificate doesn't verify then abort.
            //3. Verify CA signature on revocation list.
            //   before testing if receiver is on list.
            //4. Timestamp, encrypt and sign chat.

            String sender = args[0];
            String receiver = args[1];
            String chat = args[2];

            Message message = new Message(sender, receiver, chat, Calendar.getInstance());

            //read sender's private key;
            PrivateKey sender_PrivateKey = Helper.readPrivateKey(sender);


            //read receiver's public key and certificate
            PublicKey receiver_PublicKey = Helper.readPublicKey(receiver);

            boolean is_revoked = Helper.isUserRevoked(receiver);


            if (!is_revoked) {

                //timestamp, encrypt and sign

                //Sign ("Bob",chat)
                Signature signature = Signature.getInstance(Helper.RSA_SIGN);
                SignedObject signedMsg = new SignedObject(message, sender_PrivateKey, signature);


                //Generate AES Key and RSA key
                KeyGenerator keyGen = KeyGenerator.getInstance("AES");
                keyGen.init(128);
                SecretKey skey = keyGen.generateKey();
                SecretKeySpec AESKeySpec = new SecretKeySpec(skey.getEncoded(), "AES");

                IvParameterSpec ivSpec = new IvParameterSpec(Helper.iv);
                Cipher cipherAES = Cipher.getInstance(Helper.AES_A);
                cipherAES.init(Cipher.ENCRYPT_MODE, AESKeySpec,ivSpec);

                Cipher cipherRSA = Cipher.getInstance(Helper.RSA_A);
                cipherRSA.init(Cipher.ENCRYPT_MODE, receiver_PublicKey);


                //Encrypt AES Key using RSA Key
                byte[] encryptedAESKey = cipherRSA.doFinal(skey.getEncoded());

                //Encrypt Message and Signature using AES Key
                //Serializable msg_sig = new MessageAndSignature(message, innerSignedObj);
                SealedObject sealedMsgSig = new SealedObject(signedMsg, cipherAES);

                //Open Socket
                Socket skt = new Socket(receiveaddress, receiveport);
                ObjectOutputStream objout = new ObjectOutputStream(skt.getOutputStream());

                //Write encrypted AES Key and sealed (Message,Signature)
                objout.write(encryptedAESKey);
                objout.writeObject(sealedMsgSig);
                objout.flush();
                objout.close();
            } else {
                System.out.println("[not sending, receiver is revoked]");
            }
        } catch (BadCertificateException e) {
            System.out.println(e);
            System.out.print("Receiver's UserKeyPair is bad\n");
            System.exit(0);
        } catch (Exception e) {
            System.out.println(e);
            e.printStackTrace();
            //System.out.print("Error\n");
        }
    }

}
