/*
 * 
 */
package com.fp.mail;

import java.util.Date;
import java.util.Properties;

import javax.activation.DataHandler;
import javax.activation.FileDataSource;
import javax.mail.Authenticator;
import javax.mail.BodyPart;
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.MimeBodyPart;
import javax.mail.internet.MimeMessage;
import javax.mail.internet.MimeMultipart;
import javax.mail.util.ByteArrayDataSource;

import com.fp.common.logger.APPLogger;
import com.fp.common.properties.PropertiesHandler;

// TODO: Auto-generated Javadoc
/**
 * Class Mail encargada del envío de correos.
 * 
 * @author gfiallos
 */
public class Mail {

    /**
     * Class SMTPAuthenticator encargada de establecer los parametros de autenticación con el Servidor de Correo.
     * 
     * @author gfiallos
     */
    private class SMTPAuthenticator extends Authenticator {

        /**
         * Obtiene el valor de password authentication.
         * 
         * @return Valor de password authentication
         */
        @Override
        public PasswordAuthentication getPasswordAuthentication() {
            try {
                PropertiesHandler ph = new PropertiesHandler("mail");
                String username = ph.getStringValue("mail.smtp.user");
                String password1 = ph.getStringValue("mail.smtp.password");
                return new PasswordAuthentication(username, password1);
            } catch (Exception e) {
                APPLogger.getLogger().error(e);
            }
            return null;
        }
    }

    /** El valor de bcc. */
    private String bcc;

    /** El valor de cc. */
    private String cc;

    /** El valor de cont. */
    private String cont = null;

    /** El valor de from. */
    private String from;

    /** El valor de mailer. */
    private String mailer = "";

    /** El valor de port. */
    private int port;

    /** El valor de user. */
    private String user;

    /** El valor de password. */
    private String password;

    /** El valor de auth. */
    private boolean auth;

    /** El valor de mail data. */
    private MimeMultipart mailData;

    /** El valor de mailhost. */
    private String mailhost = null;

    /** El valor de subject. */
    private String subject = null;

    /** El valor de to. */
    private String to = null;

    /** El valor de smtps. */
    private boolean smtps;

    /** El valor de content message type. */
    private String contentMessageType = "text/html";

    /**
     * Crea una nueva instancia de mail.
     * 
     * @param pSubject the subject
     * @param pMessage the message
     * @param pTo the to
     * @throws Exception la exception
     */
    public Mail(String pSubject, String pMessage, String pTo) throws Exception {
        this(pSubject, pMessage, pTo, null, null, true);
    }

    /**
     * Crea una nueva instancia de mail.
     * 
     * @param pSubject the subject
     * @param pMessage the message
     * @param pTo the to
     * @param pCopy the copy
     * @throws Exception la exception
     */
    public Mail(String pSubject, String pMessage, String pTo, String pCopy) throws Exception {
        this(pSubject, pMessage, pTo, pCopy, null, true);
    }

    /**
     * Crea una nueva instancia de mail.
     * 
     * @param pSubject the subject
     * @param pMessage the message
     * @param pTo the to
     * @param pCopy the copy
     * @param pBcc the bcc
     * @param pInit the init
     * @throws Exception la exception
     */
    public Mail(String pSubject, String pMessage, String pTo, String pCopy, String pBcc, boolean pInit) throws Exception {
        if (pInit) {
            this.init();
        }
        this.to = pTo;
        this.subject = pSubject;
        this.cc = pCopy;
        this.bcc = pBcc;

        this.cont = pMessage;
        if (this.cont != null) {
            this.manageContent();
        }

    }
    
    /** 
     * Permite poner una plantilla de descripcion al mail
     * @param pMessage
     * @throws Exception
     */
    public void setCuerpoMail(String pMessage) throws Exception {
         this.cont = pMessage;
        if (this.cont != null) {
            this.manageContent();
        }
    }

    /**
     * Método que implementa la construcción del contenido del mail.
     * 
     * @throws Exception la exception
     */
    private void manageContent() throws Exception {
        BodyPart content = new MimeBodyPart();
        ByteArrayDataSource bad = new ByteArrayDataSource(this.cont.getBytes(), this.contentMessageType);
        DataHandler dh = new DataHandler(bad);
        content.setDataHandler(dh);

        this.mailData = new MimeMultipart();
        this.mailData.addBodyPart(content);
    }

    /**
     * Entrega el valor de contentMessageType.
     * 
     * @return Valor de contentMessageType
     */
    public String getContentMessageType() {
        return this.contentMessageType;
    }

    /**
     * Fija un nuevo valor en contentMessageType.
     * 
     * @param pContentMessageType nuevo valor para contentMessageType
     */
    public void setContentMessageType(String pContentMessageType) {
        this.contentMessageType = pContentMessageType;
    }

    /**
     * Inicia los datos básicos para el envío del Correo.
     * 
     * @throws Exception la exception
     */
    protected void init() throws Exception {
        PropertiesHandler ph = new PropertiesHandler("mail");
        this.from = ph.getValue("mail.from");
        this.mailhost = ph.getValue("mail.smtp.server");
        this.port = ph.getIntValue("mail.smtp.port");
        this.user = ph.getStringValue("mail.smtp.user");
        this.password = ph.getStringValue("mail.smtp.password");
        this.auth = ph.getBooleanValue("mail.smtp.auth");
        this.smtps = ph.getBooleanValue("mail.smtps");
    }

    /**
     * Configura el envío de Correos.
     * 
     * @param pFrom Remitente
     * @param pMailhost Servidor SMTP
     * @param pPort Puerto SMTP
     * @param pUser Usuario de ingreso al servidor SMTP
     * @param pPassword Password de ingreso al servidor SMTP
     * @param pAuth Indicador si se requiere autenticación con el Servidor
     * @param pSMTPS Indicador si el servidor maneja protocolo seguro
     * @throws Exception la exception
     */
    public void config(String pFrom, String pMailhost, int pPort, String pUser, String pPassword, boolean pAuth, boolean pSMTPS) throws Exception {
        this.from = pFrom;
        this.mailhost = pMailhost;
        this.port = pPort;
        this.user = pUser;
        this.password = pPassword;
        this.auth = pAuth;
        this.smtps = pSMTPS;
    }

    /**
     * Adiciona un attachment.
     * 
     * @param pName the name
     * @param pPath the path
     * @throws Exception la exception
     */
    public void addAttachment(String pName, String pPath) throws Exception {
    	try{
	        BodyPart attach = new MimeBodyPart();
	        attach.setDataHandler(new DataHandler(new FileDataSource(pPath)));
	        attach.setFileName(pName);
	        if(mailData==null){
	        	this.mailData = new MimeMultipart();
	        }
	        this.mailData.addBodyPart(attach);
    	}catch(Exception err){
    		APPLogger.getLogger().error(err);
    	}
    }

    /**
     * Adiciona un attachment.
     * 
     * @param pName the name
     * @param bytesAttachment the bytes attachment
     * @param contentType the content type
     * @throws Exception la exception
     */
    public void addAttachment(String pName, byte[] bytesAttachment, String contentType) throws Exception {
    	try{
	        BodyPart attach = new MimeBodyPart();
	        ByteArrayDataSource bad = new ByteArrayDataSource(bytesAttachment, contentType);
	        DataHandler dh = new DataHandler(bad);
	        attach.setDataHandler(dh);
	        attach.setFileName(pName);
	        if(mailData==null){
	        	this.mailData = new MimeMultipart();
	        }
	        this.mailData.addBodyPart(attach);
	    }catch(Exception err){
			APPLogger.getLogger().error(err);
		}
    }

    /**
     * Envía el Correo.
     * 
     * @throws Exception la exception
     */
    public void send() throws Exception {
        if (this.mailData == null) {
            this.manageContent();
        }
        Properties props = System.getProperties();
        props.put("mail.smtp.localhost", "mail.google.com");
        if (this.mailhost != null) {
            props.put("mail.smtp.host", this.mailhost);
            props.setProperty("mail.smtp.port", "" + this.port);
            if (this.smtps) {
                props.put("mail.smtp.ssl", "true");
                props.put("mail.smtp.starttls.enable", "true");
                props.put("mail.smtp.socketFactory.class", "javax.net.ssl.SSLSocketFactory");
                props.put("mail.smtp.socketFactory.fallback", "false");
            }
            props.setProperty("mail.smtp.auth", "" + this.auth);

        }

        Session session = null;
        if (this.smtps) {
            @SuppressWarnings("synthetic-access")
            Authenticator auth1 = new SMTPAuthenticator();
            session = Session.getDefaultInstance(props, auth1);
        } else {
            session = Session.getDefaultInstance(props, null);
        }
        Message msg = new MimeMessage(session);

        msg.setFrom(new InternetAddress(this.from));
        msg.setRecipients(Message.RecipientType.TO, InternetAddress.parse(this.to, false));

        if (this.cc != null) {
            msg.setRecipients(Message.RecipientType.CC, InternetAddress.parse(this.cc, false));
        }

        if (this.bcc != null) {
            msg.setRecipients(Message.RecipientType.BCC, InternetAddress.parse(this.bcc, false));
        }

        msg.setSubject(this.subject);

        msg.setContent(this.mailData);
        msg.setHeader("X-Mailer", this.mailer);
        msg.setSentDate(new Date());
        Transport t = null;
        if (this.smtps || !this.auth) {
            Transport.send(msg);
        }
        else {
            t = session.getTransport("smtp");
            t.connect(this.mailhost, this.port, this.user, this.password);
            t.sendMessage(msg, msg.getAllRecipients());
            t.close();
        }

    }

    /**
     * Entrega el valor de bcc.
     * 
     * @return Valor de bcc
     */
    public String getBcc() {
        return this.bcc;
    }

    /**
     * Fija un nuevo valor en bcc.
     * 
     * @param pBcc nuevo valor para bcc
     */
    public void setBcc(String pBcc) {
        this.bcc = pBcc;
    }

    /**
     * Entrega el valor de cc.
     * 
     * @return Valor de cc
     */
    public String getCc() {
        return this.cc;
    }

    /**
     * Fija un nuevo valor en cc.
     * 
     * @param pCc nuevo valor para cc
     */
    public void setCc(String pCc) {
        this.cc = pCc;
    }

    /**
     * Entrega el valor de cont.
     * 
     * @return Valor de cont
     */
    public String getCont() {
        return this.cont;
    }

    /**
     * Fija un nuevo valor en cont.
     * 
     * @param pCont nuevo valor para cont
     */
    public void setCont(String pCont) {
        this.cont = pCont;
    }

    /**
     * Entrega el valor de from.
     * 
     * @return Valor de from
     */
    public String getFrom() {
        return this.from;
    }

    /**
     * Fija un nuevo valor en from.
     * 
     * @param pFrom nuevo valor para from
     */
    public void setFrom(String pFrom) {
        this.from = pFrom;
    }

    /**
     * Entrega el valor de mailer.
     * 
     * @return Valor de mailer
     */
    public String getMailer() {
        return this.mailer;
    }

    /**
     * Fija un nuevo valor en mailer.
     * 
     * @param pMailer nuevo valor para mailer
     */
    public void setMailer(String pMailer) {
        this.mailer = pMailer;
    }

    /**
     * Entrega el valor de subject.
     * 
     * @return Valor de subject
     */
    public String getSubject() {
        return this.subject;
    }

    /**
     * Fija un nuevo valor en subject.
     * 
     * @param pSubject nuevo valor para subject
     */
    public void setSubject(String pSubject) {
        this.subject = pSubject;
    }

    /**
     * Entrega el valor de to.
     * 
     * @return Valor de to
     */
    public String getTo() {
        return this.to;
    }

    /**
     * Fija un nuevo valor en to.
     * 
     * @param pTo nuevo valor para to
     */
    public void setTo(String pTo) {
        this.to = pTo;
    }

    public Mail() {
    }
    public static void main(String[] args) {
        try {
            Mail  m = new Mail();
            m.config("notificacion@sbs.gob.ec", "5.9.144.187", 26, null, null, false, false);
            m.setTo("pruebas@sbs.gob.ec");
            m.setSubject("Prueba mail maia");
            m.setCont("texto de prueba de correo");
            m.send();
        } catch (Exception e) {
            APPLogger.getLogger().error(e);
        }

    }
}
