/*
 * Copyright
 *   2007 axYus - www.axyus.com
 *  2009 Laurent Meckert <laurent.meckert@axyus.com>
 *
 * This file is part of XEMELIOS.
 *
 * XEMELIOS is free software; you can redistribute it and/or modify
 * it under the terms of the GNU Lesser General Public License as published by
 * the Free Software Foundation; either version 3 of the License, or
 * (at your option) any later version.
 *
 * XEMELIOS is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU Lesser General Public License for more details.
 *
 * You should have received a copy of the GNU Lesser General Public License
 * along with XEMELIOS; if not, write to the Free Software
 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
 */

package fr.gouv.finances.cp.xemelios.controls.editors;

import fr.gouv.finances.dgfip.utils.Pair;
import fr.gouv.finances.dgfip.xemelios.common.Constants;
import fr.gouv.finances.dgfip.xemelios.common.config.DocumentModel;
import fr.gouv.finances.dgfip.xemelios.common.config.DocumentsModel;
import fr.gouv.finances.dgfip.xemelios.common.config.Loader;
import fr.gouv.finances.cp.xemelios.controls.AbstractControlContentHandler;
import fr.gouv.finances.cp.xemelios.controls.MainControl;
import fr.gouv.finances.cp.xemelios.controls.models.DocumentControlModel;
import fr.gouv.finances.cp.xemelios.controls.models.ParamModel;

import fr.gouv.finances.cp.xemelios.controls.ControlProgressListener;
import fr.gouv.finances.cp.xemelios.ui.MainWindow;
import fr.gouv.finances.dgfip.xemelios.auth.UnauthorizedException;
import fr.gouv.finances.dgfip.xemelios.auth.XemeliosUser;
import fr.gouv.finances.dgfip.xemelios.common.ToolException;
import java.io.File;
import java.util.Hashtable;
import javax.xml.transform.Transformer;
import javax.xml.transform.TransformerFactory;
import javax.xml.transform.stream.StreamSource;

import org.w3c.dom.Document;
import javax.xml.transform.dom.DOMResult;

import javax.xml.parsers.DocumentBuilderFactory;

/**
 *
 * @author chm
 */
public class Controller implements ControlProgressListener {

   MainControl mc;
   DocumentsModel config;
   DocumentModel pesConfig;
   DocumentModel rapportConfig;

   /**
    *
    * @param typeDoc modele de document
    * @throws Exception
    */
   public Controller(String typeDoc) throws Exception {
      config = Loader.getDocumentsInfos(System.getProperty(Constants.SYS_PROP_DOC_DEF_DIR));

      pesConfig = config.getDocumentById(typeDoc); //("PES_Aller");
      rapportConfig = config.getDocumentById("DocumentRapport");
      mc = new MainControl(pesConfig, config) {

         @Override
         public AbstractControlContentHandler getControlContentHandler(DocumentModel dm, DocumentControlModel docCtrlMod, Hashtable<String, Object> parameters, MainWindow frame, String file) {
            AbstractControlContentHandler cch = new AbstractControlContentHandler(dm, docCtrlMod, parameters, (MainWindow) null, file) {

               public Pair getCollectivite(DocumentModel dm, String fileName) throws ToolException {
                  return new Pair("xxxxxxxxxxx", "Collectivité d'analyse");
               }

               public Pair getBudget(DocumentModel dm, Pair collectivite, String fileName) throws ToolException, UnauthorizedException {
                  return new Pair("00", "Budget principal");
               }
            };
            return cch;
         }
      };
   }

   /**
    * Verifie que tous les parametres necessaires sont renseignes
    * @param hashParams  cle = id du parametres, value = un objet (String, Boolean etc...). Si un parametre doit &ecirc;tre une liste de valeur, exprimer l'ensemble des valeurs sous la forme <tt>"{val1, val2, val3, ...}"</tt>
    * @return true/false (succes/echec)
    */
   public boolean checkParameters(Hashtable<String, Object> hashParams) {
      boolean ret = true;
      DocumentControlModel dcm = mc.getDocumentControl();
      for (ParamModel param : dcm.getParams()) {

         Object val = hashParams.get(param.getId());
         if (val == null) {
            System.err.println("ERROR: Mandatory parameter " + param.getId() + " Not found ");
            ret = false;
            continue;
         }
      }
      return ret;
   }

   /**
    * Pour aider à la mise au point
    * donne la liste des parametres obligatoires
    * pour le type de document choisis
    */
   public void listMandatoryParameters() {

      DocumentControlModel dcm = mc.getDocumentControl();
      System.err.println("Mandatory parameters are:");
      for (ParamModel param : dcm.getParams()) {
         System.err.println(param.getId() + "( " + param.getDatatype() + ")");

      }

   }

   public String getParameterDataType(String paramId){
      DocumentControlModel dcm = mc.getDocumentControl();
      ParamModel param = dcm.getParamById(paramId);
      if(param != null)
         return param.getDatatype();
      else 
         return null;

   }


   /**
    *
    * @param fileToRead le fichier à analyser/enrichir
    * @param parameters hashtable key = id de parametre, value = Object correspondant. Si une valeur est une liste de valeurs, il faut passer l'ensemble des valeurs sous la forme <tt>{val1, val2, val3, ...}</tt>.
    * @return  une Hashtable key = DocumentEnrichi ou Rapport, value = dom.document. {DocumentEnrichi=org.w3c.dom.Document, Rapport=org.w3c.dom.Document}
    * @throws Exception
    */
   public Hashtable<String, Document> controle(File fileToRead, Hashtable<String, Object> parameters) throws Exception {
      //  XemeliosUser localUser = new LocalUser();


      Hashtable<String, Document> domDocuments = new Hashtable<String, Document>();
      if (!checkParameters(parameters)) {
         listMandatoryParameters();
         return domDocuments;// qui est    vide
      }
      File rapport = File.createTempFile("rapport", "xml");

      File tmpEnrichi = File.createTempFile("pesv2-enrichi", "xml");
      mc.setControlProgressListener(this);
      mc.setParameters(parameters);
      mc.setFileToControl(fileToRead);
      mc.setFichierEnrichiLocation(tmpEnrichi.getAbsolutePath());
      mc.setRapportLocation(rapport.getAbsolutePath());

      // use any utility to run control
      mc.run();

      if (mc.getControlStatus() != MainControl.STATUS_NOT_CONTROLLED) {
         if (mc.getControlStatus() > MainControl.STATUS_NOT_SCHEMA_VALID) {
            // on applique la XSL d'import specifique aux controle standalone au flux enrichi
            TransformerFactory tFactory = TransformerFactory.newInstance();
            Transformer tr = tFactory.newTransformer(new StreamSource(new File(pesConfig.getBaseDirectory(), pesConfig.getGlobalImportXsltFile())));
            DOMResult result = new DOMResult();

            tr.transform(new StreamSource(tmpEnrichi), result);
            tmpEnrichi.delete();

            domDocuments.put("DocumentEnrichi", (Document) result.getNode());
         }
         if (rapportConfig.getGlobalImportXsltFile() != null && rapportConfig.getGlobalImportXsltFile().length() > 0) {
            TransformerFactory tFactory = TransformerFactory.newInstance();
            Transformer tr = tFactory.newTransformer(new StreamSource(new File(rapportConfig.getBaseDirectory(), rapportConfig.getGlobalImportXsltFile())));
            DOMResult result = new DOMResult();
            tr.transform(new StreamSource(rapport), result);
            domDocuments.put("Rapport", (Document) result.getNode());
         } else {

            DocumentBuilderFactory dFactory = DocumentBuilderFactory.newInstance();
            Document drapport = dFactory.newDocumentBuilder().parse(rapport);
            domDocuments.put("Rapport", drapport);
            rapport.delete();
         }
      }
      return domDocuments;
   }

   public void notifyImportFinished(MainControl.Triplet triplet) {
   }

   public void notifyImportInterrupted(boolean hide) {
   }

   public void stopWaiting() {
   }

   public void notifyTechniqueValidationFailed() {
   }

   /**
    * @TODO : AUTHORISATIONS A GERER CORRECTEMENT
    * LM  = recopié tel quel mais inutilisé
    */
   public static class LocalUser implements XemeliosUser {

      public String getId() {
         return "local";
      }

      public String getDisplayName() {
         return getId();
      }

      public boolean hasRole(String arg0) {
         return true;
      }

      public boolean hasDocument(String arg0) {
         return true;
      }

      public boolean hasCollectivite(String arg0, DocumentModel dm) {
         return true;
      }
   }
}
