/*
 * Copyright 2011 gitblit.com.
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
package com.gitblit;

import java.util.ArrayList;
import java.util.Arrays;
import java.util.Date;
import java.util.HashSet;
import java.util.List;
import java.util.Properties;
import java.util.Queue;
import java.util.Set;
import java.util.concurrent.ConcurrentLinkedQueue;
import java.util.regex.Pattern;

import javax.mail.Authenticator;
import javax.mail.Message;
import javax.mail.PasswordAuthentication;
import javax.mail.Session;
import javax.mail.Transport;
import javax.mail.internet.InternetAddress;
import javax.mail.internet.MimeMessage;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import com.gitblit.utils.StringUtils;

/**
 * The mail executor handles sending email messages asynchronously from queue.
 * 
 * @author James Moger
 * 
 */
public class MailExecutor implements Runnable {

	private final Logger logger = LoggerFactory.getLogger(MailExecutor.class);

	private final Queue<Message> queue = new ConcurrentLinkedQueue<Message>();

	private final Session session;

	private final IStoredSettings settings;

	public MailExecutor(IStoredSettings settings) {
		this.settings = settings;

		final String mailUser = settings.getString(Keys.mail.username, null);
		final String mailPassword = settings.getString(Keys.mail.password, null);
		final boolean smtps = settings.getBoolean(Keys.mail.smtps, false);
		boolean authenticate = !StringUtils.isEmpty(mailUser) && !StringUtils.isEmpty(mailPassword);
		String server = settings.getString(Keys.mail.server, "");
		if (StringUtils.isEmpty(server)) {
			session = null;
			return;
		}
		int port = settings.getInteger(Keys.mail.port, 25);
		boolean isGMail = false;
		if (server.equals("smtp.gmail.com")) {
			port = 465;
			isGMail = true;
		}

		Properties props = new Properties();
		props.setProperty("mail.smtp.host", server);
		props.setProperty("mail.smtp.port", String.valueOf(port));
		props.setProperty("mail.smtp.auth", String.valueOf(authenticate));
		props.setProperty("mail.smtp.auths", String.valueOf(authenticate));

		if (isGMail || smtps) {
			props.setProperty("mail.smtp.starttls.enable", "true");
			props.put("mail.smtp.socketFactory.port", String.valueOf(port));
			props.put("mail.smtp.socketFactory.class", "javax.net.ssl.SSLSocketFactory");
			props.put("mail.smtp.socketFactory.fallback", "false");
		}

		if (!StringUtils.isEmpty(mailUser) && !StringUtils.isEmpty(mailPassword)) {
			// SMTP requires authentication
			session = Session.getInstance(props, new Authenticator() {
				protected PasswordAuthentication getPasswordAuthentication() {
					PasswordAuthentication passwordAuthentication = new PasswordAuthentication(
							mailUser, mailPassword);
					return passwordAuthentication;
				}
			});
		} else {
			// SMTP does not require authentication
			session = Session.getInstance(props);
		}
	}

	/**
	 * Indicates if the mail executor can send emails.
	 * 
	 * @return true if the mail executor is ready to send emails
	 */
	public boolean isReady() {
		return session != null;
	}


	/**
	 * Create a message.
	 * 
	 * @param toAddresses
	 * @return a message
	 */
	public Message createMessage(String... toAddresses) {
		return createMessage(Arrays.asList(toAddresses));
	}

	/**
	 * Create a message.
	 * 
	 * @param toAddresses
	 * @return a message
	 */
	public Message createMessage(List<String> toAddresses) {
		MimeMessage message = new MimeMessage(session);
		try {
			String fromAddress = settings.getString(Keys.mail.fromAddress, null);
			if (StringUtils.isEmpty(fromAddress)) {
				fromAddress = "gitblit@gitblit.com";
			}
			InternetAddress from = new InternetAddress(fromAddress, "Gitblit");
			message.setFrom(from);

			// determine unique set of addresses
			Set<String> uniques = new HashSet<String>();
			for (String address : toAddresses) {
				uniques.add(address.toLowerCase());
			}
			
			Pattern validEmail = Pattern
					.compile("^([a-zA-Z0-9_\\-\\.]+)@((\\[[0-9]{1,3}\\.[0-9]{1,3}\\.[0-9]{1,3}\\.)|(([a-zA-Z0-9\\-]+\\.)+))([a-zA-Z]{2,4}|[0-9]{1,3})(\\]?)$");
			List<InternetAddress> tos = new ArrayList<InternetAddress>();
			for (String address : uniques) {
				if (StringUtils.isEmpty(address)) {
					continue;
				}
				if (validEmail.matcher(address).find()) {
					try {
						tos.add(new InternetAddress(address));
					} catch (Throwable t) {
					}
				}
			}			
			message.setRecipients(Message.RecipientType.BCC,
					tos.toArray(new InternetAddress[tos.size()]));
			message.setSentDate(new Date());
		} catch (Exception e) {
			logger.error("Failed to properly create message", e);
		}
		return message;
	}

	/**
	 * Returns the status of the mail queue.
	 * 
	 * @return true, if the queue is empty
	 */
	public boolean hasEmptyQueue() {
		return queue.isEmpty();
	}

	/**
	 * Queue's an email message to be sent.
	 * 
	 * @param message
	 * @return true if the message was queued
	 */
	public boolean queue(Message message) {
		if (!isReady()) {
			return false;
		}
		try {
			message.saveChanges();
		} catch (Throwable t) {
			logger.error("Failed to save changes to message!", t);
		}
		queue.add(message);
		return true;
	}

	@Override
	public void run() {
		if (!queue.isEmpty()) {
			if (session != null) {
				// send message via mail server
				List<Message> failures = new ArrayList<Message>();
				Message message = null;
				while ((message = queue.poll()) != null) {
					try {
						if (settings.getBoolean(Keys.mail.debug, false)) {
							logger.info("send: " + StringUtils.trimString(message.getSubject(), 60));
						}
						Transport.send(message);
					} catch (Throwable e) {
						logger.error("Failed to send message", e);
						failures.add(message);
					}
				}
				
				// push the failures back onto the queue for the next cycle
				queue.addAll(failures);
			}
		}
	}
	
	public void sendNow(Message message) throws Exception {
		Transport.send(message);
	}
}
