/*******************************************************************************
 * Copyright 2018 2Fi Business Solutions Ltd.
 *
 * This code is part of the Core project.
 *
 * This code is copyrighted. Under no circumstances should any party, people,
 * or organization should redistribute any portions of this code in any form,
 * either verbatim or through electronic media, to any third parties, unless
 * under explicit written permission by 2Fi Business Solutions Ltd.
 ******************************************************************************/
package com.ffii.core.engine;

import java.io.File;
import java.util.HashMap;
import java.util.Map;
import java.util.Properties;

import javax.mail.MessagingException;
import javax.mail.internet.InternetAddress;
import javax.mail.internet.MimeMessage;

import com.ffii.core.Settings;
import com.ffii.core.setting.service.SettingsService;
import com.ffii.core.utils.SecurityUtils;
import com.ffii.tbms.user.service.SysGroupService;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.core.io.InputStreamSource;
import org.springframework.mail.javamail.JavaMailSender;
import org.springframework.mail.javamail.JavaMailSenderImpl;
import org.springframework.mail.javamail.MimeMessageHelper;
import org.springframework.stereotype.Component;
import org.springframework.web.context.support.WebApplicationObjectSupport;

/**
 * Mail Engine is a Spring Component Bean that handles E-mail operations.
 *
 * @author Patrick
 */
@Component
public class MailEngine extends WebApplicationObjectSupport {

	@Autowired
	private FreeMarkerEngine freeMarkerEngine;

	private JavaMailSender mailSender;

	@Autowired
	private SettingsService settingsService;

	@Autowired
	private SysGroupService sysGroupService;

	/**
	 * Send HTML mail message
	 *
	 * @param from
	 *                               the from address, must not be null
	 * @param replyTo
	 *                               the reply to address, may be null
	 * @param to
	 *                               the to addresses, must not be null
	 * @param cc
	 *                               the cc addresses, may be null
	 * @param bcc
	 *                               the bcc addresses, may be null
	 * @param subject
	 *                               the subject, may be null
	 * @param html
	 *                               the html message body, must not be null
	 * @param attachmentFilename
	 *                               the name of the attachment as it will appear in the mail
	 * @param file
	 *                               the File to attach
	 */

	private JavaMailSender getJavaMailSender(int sysGroupId){
		//if(mailSender == null){
			Map<String, Object> sysGroup = sysGroupService.find(sysGroupId);

			String smtp_host = "";
			int smtp_port = 0;
			String smtp_username = "";
			String smtp_password = "";
			logger.info(sysGroup);
			if(sysGroup != null){
				smtp_host = sysGroup.get("smtp_host")==null?"":sysGroup.get("smtp_host").toString();
				smtp_port = sysGroup.get("smtp_port")==null?0:Integer.parseInt(sysGroup.get("smtp_port").toString());
				smtp_username = sysGroup.get("smtp_username")==null?"":sysGroup.get("smtp_username").toString();
				smtp_password = sysGroup.get("smtp_password")==null?"":sysGroup.get("smtp_password").toString();
			}
				

			JavaMailSenderImpl jmsi = new JavaMailSenderImpl();
			jmsi.setHost(smtp_host);
			jmsi.setPort(smtp_port);
			jmsi.setUsername(smtp_username);
			jmsi.setPassword(smtp_password);

			Properties props = jmsi.getJavaMailProperties();
			props.put("mail.transport.protocol", "smtp");
			props.put("mail.smtp.auth", "true");
			props.put("mail.smtp.starttbms.enable", "true");
			props.put("mail.debug", "true");
			mailSender = jmsi;
		//}
		return mailSender;
	}

	public void sendHtmlMail(int sysGroupId, InternetAddress from, InternetAddress replyTo, InternetAddress[] to, InternetAddress[] cc, InternetAddress[] bcc,
			String subject, String html, String attachmentFilename, File file) {

		MimeMessage mimeMessage = getJavaMailSender(sysGroupId).createMimeMessage();

		try {
			MimeMessageHelper message = new MimeMessageHelper(mimeMessage, true, "UTF-8");
			message.setFrom(from);
			if (replyTo != null) message.setReplyTo(replyTo);
			message.setTo(to);
			if (cc != null) message.setCc(cc);
			if (bcc != null) message.setBcc(bcc);
			if (subject != null) message.setSubject(subject);
			message.setText(html, true);
			if (attachmentFilename != null && file != null) message.addAttachment(attachmentFilename, file);
		} catch (MessagingException e) {
			logger.error("Failed to send HTML mail", e);
		}

		getJavaMailSender(sysGroupId).send(mimeMessage);
	}
	

	/**
	 * Send HTML mail message
	 *
	 * @param from
	 *                               the from address, must not be null
	 * @param replyTo
	 *                               the reply to address, may be null
	 * @param to
	 *                               the to addresses, must not be null
	 * @param subject
	 *                               the subject, may be null
	 * @param html
	 *                               the html message body, must not be null
	 * @param attachmentFilename
	 *                               the name of the attachment as it will appear in the mail
	 * @param file
	 *                               the File to attach
	 */
	public void sendHtmlMail(int sysGroupId, InternetAddress from, InternetAddress replyTo, InternetAddress[] to,
			String subject, String html, String attachmentFilename, File file) {
		sendHtmlMail(sysGroupId, from, replyTo, to, null, null, subject, html, attachmentFilename, file);
	}

	/**
	 * Send HTML mail message
	 *
	 * @param from
	 *                    the from address, must not be null
	 * @param replyTo
	 *                    the reply to address, may be null
	 * @param to
	 *                    the to addresses, must not be null
	 * @param subject
	 *                    the subject, may be null
	 * @param html
	 *                    the html message body, must not be null
	 */
	public void sendHtmlMail(int sysGroupId,InternetAddress from, InternetAddress replyTo, InternetAddress[] to, String subject, String html) {
		sendHtmlMail(sysGroupId, from, replyTo, to, null, null, subject, html, null, null);
	}

	/**
	 * Send HTML mail message generated from FreeMarker template
	 *
	 * @param from
	 *                               the from address, must not be null
	 * @param replyTo
	 *                               the reply to address, may be null
	 * @param to
	 *                               the to addresses, must not be null
	 * @param cc
	 *                               the cc addresses, may be null
	 * @param bcc
	 *                               the bcc addresses, may be null
	 * @param subject
	 *                               the subject, may be null
	 * @param template
	 *                               the FreeMarker template name, must not be null
	 * @param model
	 *                               the model to be applied to the FreeMarker template, may be null
	 * @param attachmentFilename
	 *                               the name of the attachment as it will appear in the mail
	 * @param file
	 *                               the File to attach
	 */
	public void sendFreeMarkerHtmlMail(int sysGroupId,InternetAddress from, InternetAddress replyTo, InternetAddress[] to, InternetAddress[] cc, InternetAddress[] bcc,
			String subject, String template, Map<?, ?> model, String attachmentFilename, File file) {

		String html = freeMarkerEngine.generateFreeMarkerContent(template, model);

		sendHtmlMail(sysGroupId,from, replyTo, to, cc, bcc, subject, html, attachmentFilename, file);
	}

	/**
	 * Send HTML mail message generated from FreeMarker template
	 *
	 * @param from
	 *                     the from address, must not be null
	 * @param replyTo
	 *                     the reply to address, may be null
	 * @param to
	 *                     the to addresses, must not be null
	 * @param subject
	 *                     the subject, may be null
	 * @param template
	 *                     the FreeMarker template name, must not be null
	 * @param model
	 *                     the model to be applied to the FreeMarker template, may be null
	 */
	public void sendFreeMarkerHtmlMail(int sysGroupId, InternetAddress from, InternetAddress replyTo, InternetAddress[] to, InternetAddress[] cc, InternetAddress[] bcc,
			String subject, String template, Map<?, ?> model) {
		sendFreeMarkerHtmlMail(sysGroupId, from, replyTo, to, cc, bcc, subject, template, model, null, null);
	}

	/**
	 * Send HTML mail message generated from FreeMarker template
	 *
	 * @param from
	 *                               the from address, must not be null
	 * @param replyTo
	 *                               the reply to address, may be null
	 * @param to
	 *                               the to addresses, must not be null
	 * @param subject
	 *                               the subject, may be null
	 * @param template
	 *                               the FreeMarker template name, must not be null
	 * @param model
	 *                               the model to be applied to the FreeMarker template, may be null
	 * @param attachmentFilename
	 *                               the name of the attachment as it will appear in the mail
	 * @param file
	 *                               the File to attach
	 */
	public void sendFreeMarkerHtmlMail(int sysGroupId,InternetAddress from, InternetAddress replyTo, InternetAddress[] to,
			String subject, String template, Map<?, ?> model, String attachmentFilename, File file) {
		sendFreeMarkerHtmlMail(sysGroupId, from, replyTo, to, null, null, subject, template, model, attachmentFilename, file);
	}

	/**
	 * Send HTML mail message generated from FreeMarker template
	 *
	 * @param from
	 *                               the from address, must not be null
	 * @param replyTo
	 *                               the reply to address, may be null
	 * @param to
	 *                               the to addresses, must not be null
	 * @param subject
	 *                               the subject, may be null
	 * @param template
	 *                               the FreeMarker template name, must not be null
	 * @param model
	 *                               the model to be applied to the FreeMarker template, may be null
	 * @param attachmentFilename
	 *                               the name of the attachment as it will appear in the mail
	 * @param file
	 *                               the File to attach
	 */

	public void sendFreeMarkerHtmlMail(int sysGroupId, InternetAddress from, InternetAddress replyTo, InternetAddress[] to,
			String subject, String template, Map<?, ?> model, String attachmentFilename, InputStreamSource file) {

		String html = freeMarkerEngine.generateFreeMarkerContent(template, model);

		MimeMessage mimeMessage = getJavaMailSender(sysGroupId).createMimeMessage();
		try {
			MimeMessageHelper message = new MimeMessageHelper(mimeMessage, true, "UTF-8");
			message.setFrom(from);
			if (replyTo != null) message.setReplyTo(replyTo);
			message.setTo(to);
			if (subject != null) message.setSubject(subject);
			message.setText(html, true);
			if (attachmentFilename != null && file != null) message.addAttachment(attachmentFilename, file);
		} catch (MessagingException e) {
			logger.error("Failed to send HTML mail", e);
		}

		getJavaMailSender(sysGroupId).send(mimeMessage);
	}


	/**
	 * Send HTML mail message generated from FreeMarker template
	 *
	 * @param from
	 *                     the from address, must not be null
	 * @param replyTo
	 *                     the reply to address, may be null
	 * @param to
	 *                     the to addresses, must not be null
	 * @param subject
	 *                     the subject, may be null
	 * @param template
	 *                     the FreeMarker template name, must not be null
	 * @param model
	 *                     the model to be applied to the FreeMarker template, may be null
	 */
	public void sendFreeMarkerHtmlMail(int sysGroupId, InternetAddress from, InternetAddress replyTo, InternetAddress[] to,
			String subject, String template, Map<?, ?> model) {
		sendFreeMarkerHtmlMail(sysGroupId,from, replyTo, to, null, null, subject, template, model, null, null);
	}

}
