/*
 * 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.service;

import java.io.File;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import java.util.Properties;
import java.util.Queue;
import java.util.UUID;
import java.util.concurrent.ConcurrentLinkedQueue;
import java.util.regex.Pattern;

import javax.activation.DataHandler;
import javax.activation.FileDataSource;
import javax.mail.Authenticator;
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.MimeBodyPart;
import javax.mail.internet.MimeMessage;
import javax.mail.internet.MimeMultipart;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import com.gitblit.IStoredSettings;
import com.gitblit.Keys;
import com.gitblit.models.Mailing;
import com.gitblit.utils.StringUtils;

/**
 * The mail service handles sending email messages asynchronously from a queue.
 *
 * @author James Moger
 *
 */
public class MailService implements Runnable {

	private final Logger logger = LoggerFactory.getLogger(MailService.class);

	private final Queue<Message> queue = new ConcurrentLinkedQueue<Message>();

	private final Session session;

	private final IStoredSettings settings;

	public MailService(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);
		final boolean starttls = settings.getBoolean(Keys.mail.starttls, 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));
		props.setProperty("mail.smtp.starttls.enable", String.valueOf(starttls));

		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() {
				@Override
				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 mailing
	 * @return a message
	 */
	public Message createMessage(Mailing mailing) {
		if (mailing.subject == null) {
			mailing.subject = "";
		}

		if (mailing.content == null) {
			mailing.content = "";
		}

		Message message = new MailMessageImpl(session, mailing.id);
		try {
			String fromAddress = settings.getString(Keys.mail.fromAddress, null);
			if (StringUtils.isEmpty(fromAddress)) {
				fromAddress = "gitblit@gitblit.com";
			}
			InternetAddress from = new InternetAddress(fromAddress, mailing.from == null ? "Gitblit" : mailing.from);
			message.setFrom(from);

			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})(\\]?)$");

			// validate & add TO recipients
			List<InternetAddress> to = new ArrayList<InternetAddress>();
			for (String address : mailing.toAddresses) {
				if (StringUtils.isEmpty(address)) {
					continue;
				}
				if (validEmail.matcher(address).find()) {
					try {
						to.add(new InternetAddress(address));
					} catch (Throwable t) {
					}
				}
			}

			// validate & add CC recipients
			List<InternetAddress> cc = new ArrayList<InternetAddress>();
			for (String address : mailing.ccAddresses) {
				if (StringUtils.isEmpty(address)) {
					continue;
				}
				if (validEmail.matcher(address).find()) {
					try {
						cc.add(new InternetAddress(address));
					} catch (Throwable t) {
					}
				}
			}

			if (settings.getBoolean(Keys.web.showEmailAddresses, true)) {
				// full disclosure of recipients
				if (to.size() > 0) {
					message.setRecipients(Message.RecipientType.TO,
							to.toArray(new InternetAddress[to.size()]));
				}
				if (cc.size() > 0) {
					message.setRecipients(Message.RecipientType.CC,
							cc.toArray(new InternetAddress[cc.size()]));
				}
			} else {
				// everyone is bcc'd
				List<InternetAddress> bcc = new ArrayList<InternetAddress>();
				bcc.addAll(to);
				bcc.addAll(cc);
				message.setRecipients(Message.RecipientType.BCC,
						bcc.toArray(new InternetAddress[bcc.size()]));
			}

			message.setSentDate(new Date());
			message.setSubject(mailing.subject);

			MimeBodyPart messagePart = new MimeBodyPart();
			messagePart.setText(mailing.content, "utf-8");
			//messagePart.setHeader("Content-Transfer-Encoding", "quoted-printable");

			if (Mailing.Type.html == mailing.type) {
				messagePart.setHeader("Content-Type", "text/html; charset=\"utf-8\"");
			} else {
				messagePart.setHeader("Content-Type", "text/plain; charset=\"utf-8\"");
			}

			MimeMultipart multiPart = new MimeMultipart();
			multiPart.addBodyPart(messagePart);

			// handle attachments
			if (mailing.hasAttachments()) {
				for (File file : mailing.attachments) {
					if (file.exists()) {
						MimeBodyPart filePart = new MimeBodyPart();
						FileDataSource fds = new FileDataSource(file);
						filePart.setDataHandler(new DataHandler(fds));
						filePart.setFileName(fds.getName());
						multiPart.addBodyPart(filePart);
					}
				}
			}

			message.setContent(multiPart);

		} 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);
	}

	private static class MailMessageImpl extends MimeMessage {

		final String id;

		MailMessageImpl(Session session, String id) {
			super(session);
			this.id = id;
		}

		@Override
		protected void updateMessageID() throws MessagingException {
			if (!StringUtils.isEmpty(id)) {
				String hostname = "gitblit.com";
				String refid = "<" + id + "@" + hostname + ">";
				String mid = "<" + UUID.randomUUID().toString() + "@" + hostname + ">";
				setHeader("References", refid);
				setHeader("In-Reply-To", refid);
				setHeader("Message-Id", mid);
			}
		}
	}
}
