package gov.onc.decrypt;

import gov.onc.startup.ConfigInfo;

import java.io.IOException;
import java.io.OutputStream;
import java.io.PrintStream;
import java.util.Properties;

import javax.mail.Message;
import javax.mail.MessagingException;
import javax.mail.PasswordAuthentication;
import javax.mail.Session;
import javax.mail.Transport;
import javax.mail.internet.InternetAddress;
import javax.mail.internet.MimeMessage;

import org.apache.log4j.Logger;


public class EmailMessageHandler implements DecryptDirectHandler{

	private static final String SMTP_HOST_NAME = ConfigInfo.getConfigProperty("smtpHostName");
	private static final String SMTP_PORT = ConfigInfo.getConfigProperty("smtpPort");
	private static final String SSL_FACTORY = "javax.net.ssl.SSLSocketFactory";
	
	private Logger log = Logger.getLogger("emailMessageLogger");
	
	public EmailBean execute(EmailBean emailInfo) throws Exception {
		
		final String TO_ADDR = getReturnMessage(emailInfo.getFromAddress());
		if (TO_ADDR == null) {
			throw new IllegalArgumentException("No results email address found for sender " +
					emailInfo.getFromAddress());
		}
		final String FROM_ADDR = ConfigInfo.getConfigProperty("emailAddress");
		final String PASSWORD = ConfigInfo.getConfigProperty("emailPassword");
		final String SUBJECT = "Results for Direct Certificate Discovery Test (Do not Reply)";
		
		StringBuffer body = new StringBuffer("Test case " + emailInfo.getThisTest().getTestCaseName() + " results:");
		
		if(emailInfo.getPasses())
			body.append(" passes.\nCongratulations!");
		else
			body.append(" fails.\nTry Again.");
		
		body.append("\nDetails: " + emailInfo.getResults());
		
		logMailInfo(TO_ADDR, FROM_ADDR, SUBJECT, body.toString());
		
		try {
			sendSSLMessage(TO_ADDR, FROM_ADDR,
					SUBJECT, body.toString(), PASSWORD);
		} catch (Exception ex) {
			log.error(ex.getMessage() + " caused by: " + ex.getCause()
					+ ex.getStackTrace());
			throw ex;
		}
		
		return emailInfo;
	}
	
	private String getReturnMessage(String key){
		return ConfigInfo.getEmailProperty(key);
	}
	
	// JML: Says it throws, but catches all exceptions.
	private void sendSSLMessage(final String toAddr, final String fromAddr, final String subjectTxt,
			final String msgContent, final String password) throws MessagingException{
		boolean debug = true;

		Properties props = new Properties();
		props.put("mail.smtp.host", SMTP_HOST_NAME);
		props.put("mail.smtp.auth", "true");
		props.put("mail.debug", "true");
		props.put("mail.smtp.port", SMTP_PORT);
		props.put("mail.smtp.starttls.enable","true");
		props.put("mail.smtp.socketFactory.port", SMTP_PORT);
		props.put("mail.smtp.socketFactory.class", SSL_FACTORY);
		props.put("mail.smtp.socketFactory.fallback", "false");

		Session session = Session.getInstance(props,
				new javax.mail.Authenticator() {
					protected PasswordAuthentication getPasswordAuthentication() {
						return new PasswordAuthentication(fromAddr,
								password);
					}
				});
		
		session.setDebug(debug);
		
		MailOutputStream mos = new MailOutputStream();

		session.setDebugOut(new PrintStream(mos));
		
		Message msg = new MimeMessage(session);
		InternetAddress internetFrom = new InternetAddress(fromAddr);
		msg.setFrom(internetFrom);
		
		InternetAddress[] addressTo = { new InternetAddress(toAddr) };
		msg.setRecipients(Message.RecipientType.TO, addressTo);

		msg.setSubject(subjectTxt);
		msg.setContent(msgContent, "text/plain");
		Transport.send(msg);
	}
	
	private void logMailInfo(String to, String from, String subject, String body){
		log.info("SMTP_HOST_NAME: " + SMTP_HOST_NAME);
		log.info("SMTP_PORT: "+ SMTP_PORT);
		log.info("TO:  " + to);
		log.info("FROM:  " + from);
		log.info("SUBJECT:  " + subject);
		log.info("Body:  " + body);
	}
	
	class MailOutputStream extends OutputStream{

		String mem;
		
		@Override
		public void write(int b) throws IOException {
			byte[] bytes = new byte[1];
	        bytes[0] = (byte) (b & 0xff);
	        mem = mem + new String(bytes);

	        if (mem.endsWith ("\n")) {
	            mem = mem.substring (0, mem.length () - 1);
	            flush ();
	        }
		}
		
		@Override
		public void flush(){
			log.info(mem);
			mem = "";
		}
	}
}

@@ -1478,16 +1478,87 @@
 :%22);%0A%09%09%0A
+//%09%09add test case name header information here - %22X-test_case_name%22%0A%09%09%0A
 %09%09if(ema
@@ -1627,111 +1627,276 @@
 %22);%0A
-%09%09else%0A%09%09%09body.append(%22 fails.%5CnTry Again.%22);%0A%09%09%0A%09%09body.append(%22%5CnDetails: %22 + emailInfo.getResults());
+//%09%09add pass header information here - use %22X-result%22%0A%09%09else%0A%09%09%09body.append(%22 fails.%5CnTry Again.%22);%0A//%09%09add fail header information here - use %22X-result%22%0A%09%09%0A%09%09body.append(%22%5CnDetails: %22 + emailInfo.getResults());%0A//%09%09add details header information here - %22X-details%22%0A%09%09
 %0A%09%09%0A

Add test case information to results email headers prep work.