package br.mp.mprj.portal.portlet.gestaomensagens.email;

import java.io.UnsupportedEncodingException;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import javax.mail.internet.AddressException;
import javax.mail.internet.InternetAddress;

import br.mp.mprj.portal.portlet.gestaomensagens.service.model.AnexoMensagem;
import br.mp.mprj.portal.portlet.gestaomensagens.service.model.EmailDestinatario;
import br.mp.mprj.portal.portlet.gestaomensagens.service.model.GrupoDestinatario;
import br.mp.mprj.portal.portlet.gestaomensagens.service.model.Mensagem;
import br.mp.mprj.portal.portlet.gestaomensagens.service.service.AnexoMensagemLocalServiceUtil;
import br.mp.mprj.portal.portlet.gestaomensagens.service.service.EmailDestinatarioLocalServiceUtil;
import br.mp.mprj.portal.portlet.gestaomensagens.service.service.GrupoDestinatarioLocalServiceUtil;
import br.mp.mprj.portal.portlet.gestaomensagens.util.EmailUtil;
import br.mp.mprj.portal.portlet.gestaomensagens.util.VelocityUtil;
import br.mp.mprj.portal.portlet.gestaomensagens.workflow.StatusWorkflowEnum;
import br.mp.mprj.portal.portlet.gestaomensagens.workflow.WorkflowUtil;

import com.liferay.portal.kernel.exception.PortalException;
import com.liferay.portal.kernel.exception.SystemException;
import com.liferay.portal.kernel.util.GetterUtil;
import com.liferay.portal.kernel.util.StringBundler;
import com.liferay.portal.kernel.util.StringPool;
import com.liferay.portal.model.User;
import com.liferay.portal.service.UserLocalServiceUtil;
import com.liferay.util.portlet.PortletProps;

/**
 * Classe respons&aacute;vel por enviar e-mail para todos os envolvidos no processo de workflow, 
 * inclusive o criador da mensagem.
 * @author Henrique Simoes
 *
 */
public class EnvioEmailWorkflow extends EnvioEmailMensagem {
	
	private static final String CAMINHO_TEMPLATE = GetterUtil.getString(PortletProps.get("email.template.alerta-workflow"));
	
	private static final String PLACEHOLDER_GROUPID = "_GROUPID_";
	
	private static final String PLACEHOLDER_MENSAGEMID = "_MENSAGEMID_";
	
	/**
	 * URL da p&aacute;gina na administra&ccedil;&atilde;o do portal para avalia&ccedil;&atilde;o do workflow.
	 */
	private final String mvcPathPaginaWorkflow = "/group/control_panel/manage?p_p_id=portletgestaomensagens_WAR_portletgestaomensagens"
													+ "&p_p_lifecycle=0&p_p_state=maximized&p_p_mode=view"
													+ "&doAsGroupId=" + PLACEHOLDER_GROUPID + "&controlPanelCategory=current_site.content"
													+ "&_portletgestaomensagens_WAR_portletgestaomensagens_navigation=template"
													+ "&_portletgestaomensagens_WAR_portletgestaomensagens_mvcPath=%2Fjsp%2Fadmin%2Fmensagem%2Fpainel-aprovacao.jsp"
													+ "&_portletgestaomensagens_WAR_portletgestaomensagens_mensagemId=" + PLACEHOLDER_MENSAGEMID;

	private final String templateEmail;
	private boolean enviarCriador = false;
	private final GrupoDestinatario remetente;
	private final List<GrupoDestinatario> destinatarios;
	private String nomesDestinatarios;
	private String nomeRemetente;
	private InternetAddress emailRemetente;
	private final String urlServidor;
	
	public EnvioEmailWorkflow(Mensagem mensagem) {
		super(mensagem);
		try {
			templateEmail = VelocityUtil.carregarTemplate(CAMINHO_TEMPLATE);
			
			remetente = GrupoDestinatarioLocalServiceUtil.getGrupoDestinatario(mensagem.getContaSaidaId());

			long[] destIds = GetterUtil.getLongValues(mensagem.getGrupoDestinatarioIds().split("\\s"));
			destinatarios = new ArrayList<>(destIds.length);
			
			for (long id : destIds) {
				destinatarios.add(GrupoDestinatarioLocalServiceUtil.getGrupoDestinatario(id));
			}
			
			urlServidor = EmailUtil.getURLServidor(mensagem.getCompanyId(), mensagem.getGroupId());
		}
		catch (Exception ex) {
			throw new RuntimeException(ex);
		}
	}
	
	@Override
	public void enviarEmail(int  tipoEnvio) throws PortalException, SystemException, AddressException, UnsupportedEncodingException {
		definirNomeContaEnvio();
		
		definirNomesDestinatarios();
		
		definirRemetente();
		
		enviarCriador = true;
		super.enviarEmail(tipoEnvio);
		
		//enviar para aprovadores somente se estiver com o status adequado
		if (mensagem.getStatusWorkflow() == StatusWorkflowEnum.PENDENTE_APROVACAO.getStatus()) {
			enviarCriador =  false;
			super.enviarEmail(tipoEnvio);			
		}
	}

	@Override
	protected InternetAddress getRemetente() throws PortalException, SystemException, AddressException, UnsupportedEncodingException {
		return emailRemetente;
	}

	@Override
	protected InternetAddress[] getDestinatarios() throws PortalException, SystemException, AddressException {
		//envia a copia para quem criou a mensagem
		if (enviarCriador) {
			return new InternetAddress[]{new InternetAddress(getUserCriador().getEmailAddress())};
		}
		
		//obter todos os usuarios associados ao papel de aprovadores.
		long roleId = WorkflowUtil.getWorkflowRoleId(mensagem.getCompanyId());
		List<User> aprovadores = UserLocalServiceUtil.getRoleUsers(roleId);
		
		if (aprovadores.size() > 0) {
			InternetAddress[] emails = new InternetAddress[aprovadores.size()];
			
			for(int i = 0; i < aprovadores.size(); i++) {
				emails[i] = new InternetAddress(aprovadores.get(i).getEmailAddress());
			}
			
			return emails;
		}
		else {
			throw new PortalException("Nenhum usuário associado ao papel de aprovadores!");
		}
	}
	
	@Override
	protected String getHtmlCompleto() {
		Map<String, Object> mapDetalhes = new HashMap<>();
		
		mapDetalhes.put("ordemServico", GetterUtil.getString(mensagem.getCodigoMensagem()));
		mapDetalhes.put("solicitante", mensagem.getNomeSolicitante());
		mapDetalhes.put("destinatarios", nomesDestinatarios);
		mapDetalhes.put("contaEnvio", nomeRemetente);
		mapDetalhes.put("assunto", mensagem.getAssunto());
		mapDetalhes.put("statusWorkflow", mensagem.getStatusWorkflow());
		mapDetalhes.put("descricaoWorkflow", StatusWorkflowEnum.getDescricao(mensagem.getStatusWorkflow()));
		mapDetalhes.put("comentarioWorkflow", mensagem.getComentarioWorkflow());
		//define se o estilo do e-mail eh para o criador (true) ou para os aprovadores (false)
		mapDetalhes.put("estiloCriador", enviarCriador);
		mapDetalhes.put("urlPaginaWorkflow", getUrlAvaliarWorkflow());
		mapDetalhes.put("literalAgendamento", mensagem.getLiteralAgendamento());

		mapDetalhes.put("htmlMensagem", super.getHtmlCompleto());
		
		return VelocityUtil.processarTemplate(mapDetalhes, templateEmail);
	}

	/**
	 * Retorna o nome das listas de destinatarios.
	 * @return String
	 */
	private void definirNomesDestinatarios() {
		StringBundler sb = new StringBundler(destinatarios.size() * 2);
		
		for (int i = 0; i < destinatarios.size(); i++) {
			GrupoDestinatario dest = destinatarios.get(i);
			if (i > 0) {
				sb.append(StringPool.COMMA + StringPool.SPACE);				
			}
			sb.append(dest.getNome());
		}
		
		nomesDestinatarios = sb.toString();
	}
	
	/**
	 * Retorna o nome da conta de envio.
	 * @return String
	 */
	private void definirNomeContaEnvio() {
		nomeRemetente = remetente.getNome();
	}
	
	private void definirRemetente() throws SystemException, PortalException, AddressException, UnsupportedEncodingException {
		
		final List<EmailDestinatario> emails = EmailDestinatarioLocalServiceUtil.findByGrupoDestinatarioId(mensagem.getContaSaidaId());
		
		if (emails != null  && emails.size() > 0) {
			emailRemetente = new InternetAddress(emails.get(0).getEmail(), nomeRemetente);
		}
	}
	

	/**
	 * Retorna a URL completa (incluindo servidor) da p&aacute;gina para o aprovador avaliar o workflow.
	 * @return String
	 */
	private String getUrlAvaliarWorkflow() {
		String urlPagina = mvcPathPaginaWorkflow
								.replace(PLACEHOLDER_GROUPID, String.valueOf(mensagem.getGroupId()))
								.replace(PLACEHOLDER_MENSAGEMID, String.valueOf(mensagem.getMensagemId()));
		
		return urlServidor + urlPagina;
	}

	@Override
	protected List<AnexoMensagem> getAnexos(long mensagemId) throws SystemException {
		return AnexoMensagemLocalServiceUtil.recuperaAnexosPorMensagem(mensagemId);
	}

	
}
