/*
 * Version 1.1
 * CeCILL Copyright (c) 2006-2007, AtolCD, ADULLACT-projet
 * Initiated by AtolCD S.A. & ADULLACT-projet S.A.
 * Developped by AtolCD
 * 
 * contact@atolcd.com
 * contact@adullact-projet.coop
 * 
 * Ce logiciel est un programme informatique servant à faire circuler des 
 * documents au travers d'un circuit de validation, où chaque acteur vise 
 * le dossier, jusqu'à l'étape finale de signature.
 * 
 * Ce logiciel est régi par la licence CeCILL soumise au droit français et
 * respectant les principes de diffusion des logiciels libres. Vous pouvez
 * utiliser, modifier et/ou redistribuer ce programme sous les conditions
 * de la licence CeCILL telle que diffusée par le CEA, le CNRS et l'INRIA 
 * sur le site "http://www.cecill.info".
 * 
 * En contrepartie de l'accessibilité au code source et des droits de copie,
 * de modification et de redistribution accordés par cette licence, il n'est
 * offert aux utilisateurs qu'une garantie limitée.  Pour les mêmes raisons,
 * seule une responsabilité restreinte pèse sur l'auteur du programme,  le
 * titulaire des droits patrimoniaux et les concédants successifs.
 * 
 * A cet égard  l'attention de l'utilisateur est attirée sur les risques
 * associés au chargement,  à l'utilisation,  à la modification et/ou au
 * développement et à la reproduction du logiciel par l'utilisateur étant 
 * donné sa spécificité de logiciel libre, qui peut le rendre complexe à 
 * manipuler et qui le réserve donc à des développeurs et des professionnels
 * avertis possédant  des  connaissances  informatiques approfondies.  Les
 * utilisateurs sont donc invités à charger  et  tester  l'adéquation  du
 * logiciel à leurs besoins dans des conditions permettant d'assurer la
 * sécurité de leurs systèmes et ou de leurs données et, plus généralement, 
 * à l'utiliser et l'exploiter dans les mêmes conditions de sécurité. 
 * 
 * Le fait que vous puissiez accéder à cet en-tête signifie que vous avez 
 * pris connaissance de la licence CeCILL, et que vous en avez accepté les
 * termes.
 *  
 */

package com.atolcd.parapheur.repo.action.executer;

import java.util.ArrayList;
import java.util.HashSet;
import java.util.List;
import java.util.Properties;
import java.util.Set;

import org.alfresco.model.ContentModel;
import org.alfresco.repo.action.ParameterDefinitionImpl;
import org.alfresco.repo.action.executer.MailActionExecuter;
import org.alfresco.repo.security.permissions.AccessDeniedException;
import org.alfresco.service.cmr.action.Action;
import org.alfresco.service.cmr.action.ParameterDefinition;
import org.alfresco.service.cmr.dictionary.DataTypeDefinition;
import org.alfresco.service.cmr.repository.ChildAssociationRef;
import org.alfresco.service.cmr.repository.NodeRef;
import org.alfresco.service.cmr.repository.NodeService;
import org.alfresco.service.cmr.repository.StoreRef;
import org.alfresco.service.cmr.search.SearchService;
import org.alfresco.service.namespace.NamespaceService;
import org.alfresco.service.namespace.RegexQNamePattern;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.springframework.util.Assert;

import com.atolcd.parapheur.model.ParapheurModel;
import com.atolcd.parapheur.repo.EtapeCircuit;
import com.atolcd.parapheur.repo.ParapheurService;

public class ParapheurMailActionExecuter extends MailActionExecuter
{
   private static Log logger = LogFactory.getLog(ParapheurMailActionExecuter.class);
   
   private static final String PARAM_DEST = "dest";
   private static final String PARAM_TEMPLATE = "template";
   
   private static final String DEST_OWNER = "owner";
   private static final String DEST_CURRENT = "current";
   private static final String DEST_DIFF = "diff";
   private static final String DEST_SECRETARIAT = "secretariat";
   private static final String DEST_TIERS = "tiers";
   
   public static final String NAME = "parapheur-mail";
   
   /**
    * The Node Service
    */
   private NodeService nodeService;
   private ParapheurService parapheurService;
   private NamespaceService namespaceService;
   private SearchService searchService;
   
   private Properties configuration;
   
   /**
    * @param namespaceService The namespaceService to set.
    */
   public void setNamespaceService(NamespaceService namespaceService)
   {
      this.namespaceService = namespaceService;
   }
   
   /**
    * @param searchService The searchService to set.
    */
   public void setSearchService(SearchService searchService)
   {
      this.searchService = searchService;
   }
   
   /**
    * @param nodeService       the NodeService to set.
    */
   public void setNodeService(NodeService nodeService)
   {
      this.nodeService = nodeService;
      super.setNodeService(nodeService);
   }
   
   /**
    * @param parapheurService The parapheurService to set.
    */
   public void setParapheurService(ParapheurService parapheurService)
   {
      this.parapheurService = parapheurService;
   }
   
   /**
    * @param configuration The configuration to set.
    */
   public void setConfiguration(Properties configuration)
   {
      this.configuration = configuration;
   }
   
   
   /**
    * Execute the rule action
    */
   @Override
   protected void executeImpl(Action ruleAction, NodeRef actionedUponNodeRef) 
   {
      Assert.isTrue(parapheurService.isDossier(actionedUponNodeRef), "Cette action ne peut être déclenchée que par un noeud de type ph:dossier");
      ruleAction.setParameterValue(MailActionExecuter.PARAM_TO,null);
      ruleAction.setParameterValue(MailActionExecuter.PARAM_TEXT," ");
      ArrayList<String> lstDestinataires = new ArrayList<String>();
      NodeRef templateRef = null;

      String mailFrom = this.configuration.getProperty("Parametre.From");
      if (null != mailFrom)
	  ruleAction.setParameterValue(MailActionExecuter.PARAM_FROM,mailFrom);
      else
	  ruleAction.setParameterValue(MailActionExecuter.PARAM_FROM,"Ne-Pas-Repondre@adullact-projet.coop");
      
      // Récupération du répertoire de templates mail
      String xpath = this.configuration.getProperty("spaces.company_home.childname") + "/" + 
      	this.configuration.getProperty("spaces.dictionary.childname") + "/" +
      	this.configuration.getProperty("spaces.templates.email.childname");
      
      List<NodeRef> results = null;
      try
      {
         results = searchService.selectNodes(
               nodeService.getRootNode(new StoreRef(this.configuration.getProperty("spaces.store"))),
                       xpath, null, namespaceService, false);
      }
      catch (AccessDeniedException e)
      {
         if (logger.isWarnEnabled())
            logger.warn("Impossible d'accéder au répertoire de templates.");
         return;
      }
      if (results == null || results.size()!=1)
      {
         if (logger.isWarnEnabled())
            logger.warn("Le chemin d'accès au répertoire de templates est incorrect.");
         return;
      }
      
      // Récupération du template correspondant au paramètre passé
      List<ChildAssociationRef> lstEnfants = nodeService.getChildAssocs(results.get(0),ContentModel.ASSOC_CONTAINS, RegexQNamePattern.MATCH_ALL);
      for (ChildAssociationRef tmpChildAssoc : lstEnfants)
      {
         NodeRef tmp = tmpChildAssoc.getChildRef();
         if (ruleAction.getParameterValue(PARAM_TEMPLATE).equals(nodeService.getProperty(tmp,ContentModel.PROP_NAME)))
         {
            templateRef = tmp;
            break;
         }
      }
      
      // Mail à l'émetteur du dossier
      if (DEST_OWNER.equals(ruleAction.getParameterValue(PARAM_DEST)))
      {
         String emetteur = parapheurService.getParapheurOwner(parapheurService.getEmetteur(actionedUponNodeRef));
         if (emetteur != null && !emetteur.equals(""))
         {
            lstDestinataires.add(emetteur);
            ruleAction.setParameterValue(MailActionExecuter.PARAM_SUBJECT,"Votre dossier: \""+nodeService.getProperty(actionedUponNodeRef,ContentModel.PROP_NAME)+"\"");
         }
         else
         {
            if (logger.isWarnEnabled())
               logger.warn("Emetteur du dossier non trouvé: id = "+actionedUponNodeRef);
            return;
         }
      }
      // Mail à l'acteur courant du circuit de validation
      else if (DEST_CURRENT.equals(ruleAction.getParameterValue(PARAM_DEST)))
      {
         String courant = parapheurService.getActeurCourant(actionedUponNodeRef);
         if (courant != null)
         {
            lstDestinataires.add(courant);
            ruleAction.setParameterValue(MailActionExecuter.PARAM_SUBJECT,"Dossier à traiter: \""+nodeService.getProperty(actionedUponNodeRef,ContentModel.PROP_NAME)+"\"");
         }
         else
         {
            if (logger.isWarnEnabled())
               logger.warn("Acteur courant du dossier non trouvé: id = "+actionedUponNodeRef);
            return;
         }
      }
      // Mail à la liste de diffusion
      else if (DEST_DIFF.equals(ruleAction.getParameterValue(PARAM_DEST)))
      {
         HashSet<String> setDest = new HashSet<String>();
         
         Set<NodeRef> setParapheurs = parapheurService.getDiffusion(actionedUponNodeRef);
         if (setParapheurs != null)
         {
            for (NodeRef paraphNodeRef : setParapheurs)
            {
               if (parapheurService.getParapheurOwner(paraphNodeRef) != null && !parapheurService.getParapheurOwner(paraphNodeRef).equals(""))
                  setDest.add(parapheurService.getParapheurOwner(paraphNodeRef));
            }
         }
         
         List<EtapeCircuit> lstEtapes = parapheurService.getCircuit(actionedUponNodeRef);
         String emetteur = parapheurService.getParapheurOwner(lstEtapes.get(0).getParapheur());
         String acteurCourant = parapheurService.getActeurCourant(actionedUponNodeRef);
         if (lstEtapes != null)
         {
            for (EtapeCircuit etape : lstEtapes)
            {
               String user = parapheurService.getParapheurOwner(etape.getParapheur());
               if (acteurCourant != null)
                  if (!acteurCourant.equals(user) && !emetteur.equals(user))
                  {
                     setDest.add(user);
                  }
            }
         }
         
         if (!setDest.isEmpty())
         {
            for (String destinataire : setDest)
               lstDestinataires.add(destinataire);
            ruleAction.setParameterValue(MailActionExecuter.PARAM_SUBJECT,"Dossier en cours: \""+nodeService.getProperty(actionedUponNodeRef,ContentModel.PROP_NAME)+"\"");
         }
         else
         {
            if (logger.isWarnEnabled())
               logger.warn("Liste de diffusion vide pour le dossier: id = "+actionedUponNodeRef);
            return;
         }
      }
      // Mail au secrétariat de l'acteur courant (impression pour signature)
      else if(DEST_SECRETARIAT.equals(ruleAction.getParameterValue(PARAM_DEST)))
      {
         NodeRef parapheurRef = parapheurService.getParentParapheur(actionedUponNodeRef);
         List<String> secretaires = parapheurService.getSecretariatParapheur(parapheurRef);
         if (secretaires.isEmpty())
         {
            if (logger.isWarnEnabled())
               logger.warn("Secrétariat responsable du dossier non trouvé: id = "+actionedUponNodeRef);
            return;
         }
         
         for (String secretaire : secretaires)
         {
            if (secretaire != null)
               lstDestinataires.add(secretaire);
         }
         ruleAction.setParameterValue(MailActionExecuter.PARAM_SUBJECT,"Dossier à imprimer: \""+nodeService.getProperty(actionedUponNodeRef,ContentModel.PROP_NAME)+"\"");
      }
      // Mail externe (utilisé par les émetteurs de dossiers WebServices notamment)
      else if(DEST_TIERS.equals(ruleAction.getParameterValue(PARAM_DEST)))
      {
	  String wsEmetteur = nodeService.getProperty(actionedUponNodeRef, ParapheurModel.PROP_WS_EMETTEUR).toString();
	  if (wsEmetteur != null && !wsEmetteur.equals(""))
	  {
	      lstDestinataires.add(wsEmetteur);
	      ruleAction.setParameterValue(MailActionExecuter.PARAM_SUBJECT,"Votre dossier: \""+nodeService.getProperty(actionedUponNodeRef,ContentModel.PROP_NAME)+"\"");
	  }
	  else
	  {
	      if (logger.isWarnEnabled())
		  logger.warn("ws-Emetteur du dossier non trouvé: id = "+actionedUponNodeRef);
	      return;
	  }
      }
      
      // Passage de paramètres et envoi du mail
      if (templateRef != null)
      {
         ruleAction.setParameterValue(MailActionExecuter.PARAM_TO_MANY,lstDestinataires);
         ruleAction.setParameterValue(MailActionExecuter.PARAM_TEMPLATE,templateRef);
         
         super.executeImpl(ruleAction,actionedUponNodeRef);
      }
      else
      {
         if (logger.isWarnEnabled())
            logger.warn("Template non trouvé: "+ruleAction.getParameterValue(PARAM_TEMPLATE));
      }
   }
   
   /**
    * Add the parameter definitions
    */
   @Override
   protected void addParameterDefinitions(List<ParameterDefinition> paramList) 
   {
      paramList.add(new ParameterDefinitionImpl(PARAM_DEST, DataTypeDefinition.TEXT, true, getParamDisplayLabel(PARAM_DEST)));
      paramList.add(new ParameterDefinitionImpl(PARAM_TEMPLATE, DataTypeDefinition.TEXT, true, getParamDisplayLabel(PARAM_TEMPLATE)));
   }
}