/*
 * Copyright
 *   2009 axYus - www.axyus.com
 *   2009 C.Marchand - christophe.marchand@axyus.com
 *   2009 JP.Tessier - jean-philippe.tessier@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 General Public License as published by
 * the Free Software Foundation; either version 2 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 General Public License for more details.
 *
 * You should have received a copy of the GNU 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.dgfip.xemelios.cg.linkResolver;

import java.io.File;
import java.io.FileInputStream;
import java.util.ArrayList;

import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.DocumentBuilderFactory;
import javax.xml.transform.Result;
import javax.xml.transform.Transformer;
import javax.xml.transform.TransformerException;
import javax.xml.transform.TransformerFactory;
import javax.xml.transform.dom.DOMSource;
import javax.xml.transform.stream.StreamResult;
import javax.xml.transform.stream.StreamSource;
import javax.xml.xpath.XPath;
import javax.xml.xpath.XPathFactory;

import org.apache.log4j.Logger;
import org.w3c.dom.Document;

import fr.gouv.finances.dgfip.utils.NavigationContext;
import fr.gouv.finances.dgfip.utils.Pair;
import fr.gouv.finances.dgfip.utils.xml.transform.CustomURIResolver;
import fr.gouv.finances.dgfip.xemelios.auth.XemeliosUser;
import fr.gouv.finances.dgfip.xemelios.common.config.DocumentModel;
import fr.gouv.finances.dgfip.xemelios.common.config.ElementModel;
import fr.gouv.finances.dgfip.xemelios.common.config.EtatModel;
import fr.gouv.finances.dgfip.xemelios.common.config.Loader;
import fr.gouv.finances.dgfip.xemelios.common.config.customLinks.CustomLinkParameters;
import fr.gouv.finances.dgfip.xemelios.common.config.customLinks.CustomLinkResolver;
import fr.gouv.finances.dgfip.xemelios.common.config.customLinks.UnresolvedException;
import fr.gouv.finances.dgfip.xemelios.data.DataConfigurationException;
import fr.gouv.finances.dgfip.xemelios.data.DataImpl;
import fr.gouv.finances.dgfip.xemelios.data.DataLayerManager;

/**
 *
 * @author chm
 */
public class CGCustomLinkResolver extends CustomLinkResolver {
	private static final Logger logger = Logger.getLogger(CGCustomLinkResolver.class);

	public CGCustomLinkResolver() {
		super();
		logger.debug("instanciating");
	}

	@Override
	public NavigationContext resolve(CustomLinkParameters parameters,Result result, NavigationContext ctx, XemeliosUser user) throws DataConfigurationException, UnresolvedException {
		logger.debug("in resolve(CustomLinkParameters,Result,NavigationContext,XemeliosUser)");
		//Hashtable<String,String> hParams = new Hashtable<String,String>();
		if(parameters.getSrcDocId().equals("compteGestion") && parameters.getSrcEtatId().equals("BalanceGenerale")){
			treatBalanceGenerale(parameters,ctx);
			commonTreatment(parameters,ctx,result,user);    		
		} else if(parameters.getSrcDocId().equals("compteGestion") && parameters.getSrcEtatId().equals("FichesBudgetaires")){
			treatFichesBudgetaires(parameters,ctx);
			commonTreatment(parameters,ctx,result,user);
		}
		return ctx;
	}

	private void commonTreatment(CustomLinkParameters parameters, NavigationContext ctx, Result result, XemeliosUser user) throws UnresolvedException,DataConfigurationException {
		logger.debug("in commontTreatment(CustomLinkParameters,NavigationContext,Result,XemeliosUser)");
		try{
			DataImpl impl = DataLayerManager.getImplementation();
			DocumentModel dm = Loader.getDocumentsInfos(null).getDocumentById(ctx.getDocId());
			EtatModel em = dm.getEtatById(ctx.getEtatId());
			ElementModel element = em.getElementById(ctx.getElementId());
			File xslFile = null;
			xslFile = new File(new File(new File(System.getProperty("user.home")),"xemelios/documents-def-ovrrd"),element.getXslt());
			if(!xslFile.exists()) xslFile = new File(em.getParent().getBaseDirectory(),element.getXslt());

			FileInputStream fis = new FileInputStream(xslFile);
			String docId = null;
			if(ctx.getPath()==null) {
				ArrayList<String> documents = impl.getDocumentListFromSpecialKeys(element,ctx.getCollectivite(),ctx.getBudget(),ctx.getSp1(),ctx.getSp2(),ctx.getSp3(),user);
				if(documents.size()==0) {
					throw new UnresolvedException("Le document est introuvable.");
				} else if(documents.size()>1 && !em.isMultiPage()) {
					throw new UnresolvedException("Plusieurs documents répondant à ces critères ont été trouvés.");
				} else {
					docId = documents.get(0);
				}
			} else {
				if(ctx.getElementId()==null) {
					ctx.setElementId(element.getId());
				}
				if(ctx.getPath()!=null && ctx.getPath().startsWith("[")) {
					ctx.setPath(element.getPath().getFormattedPath()+ctx.getPath());
				}
				ArrayList<String> documents = impl.getDocumentListFromXPath(element,ctx.getCollectivite(),ctx.getBudget(),ctx.getSp1(),ctx.getSp2(),ctx.getSp3(),ctx.getPath(), user);
				if(documents.size()==0) {
					throw new UnresolvedException("Ce compte n'est associé a aucun(e) "+ctx.getEtatId()+".");
				} else if(documents.size()>1){
					docId=documents.get(0);
				} else {
					docId=documents.get(0);
				}
			}

			Document doc = impl.getDocumentAsDom(em,new Pair(ctx.getCollectivite(),null),new Pair(ctx.getBudget(),null),docId , user);
			TransformerFactory tFactory = TransformerFactory.newInstance();
			tFactory.setURIResolver(new CustomURIResolver(tFactory.getURIResolver(), xslFile.getParentFile().toURI().toURL().toExternalForm()));
			Transformer t = tFactory.newTransformer(new StreamSource(xslFile));
			for(String key:parameters.getParameters().keySet()) {
				if(key.startsWith("xsl:param")) {
					String paramValue = parameters.getParameter(key);
					int virg = paramValue.indexOf(',');
					String pName = paramValue.substring(1,virg);
					String pValue = paramValue.substring(virg+1,paramValue.length()-1);
					t.setParameter(pName, pValue);
				}
			}
			t.transform(new DOMSource(doc),result);
		} catch(UnresolvedException unEx) {
			throw unEx;
		} catch (Exception e) {
			logger.error("commontTreatment(CustomLinkParameters,NavigationContext,Result,XemeliosUser)",e);
			throw new DataConfigurationException(e);
		}
	}

	private void treatBalanceGenerale(CustomLinkParameters parameters,NavigationContext ctx){
		try{
			logger.debug("in treatBalanceGenerale(CustomLinkParameters parameters,NavigationContext ctx)");
			DocumentModel dm = Loader.getDocumentsInfos(null).getDocumentById(ctx.getDocId());
			String baseDir = dm.getBaseDirectory();
			File f = new File(baseDir,dm.getParameters().getParameter("liens.balance").getValue());
			DocumentBuilder db = DocumentBuilderFactory.newInstance().newDocumentBuilder();
			Document LiensBalance = db.parse(f);

			String CodRD= (parameters.getParameter("CodRD")!=null)?parameters.getParameter("CodRD"):"";
			String numCompte = parameters.getParameter("numCompte");

			ctx.setDocId("compteGestion");
			if(parameters.getSrcCollectivite() != null){
				ctx.setCollectivite(parameters.getSrcCollectivite());
			}
			if(parameters.getSrcBudget() != null){
				ctx.setBudget(parameters.getSrcBudget());
			}
			if(parameters.getParameter("sp1") != null){
				ctx.setSp1(parameters.getParameter("sp1"));
			}
			if(parameters.getParameter("sp2") != null){
				ctx.setSp2(parameters.getParameter("sp2"));
			}
			if(parameters.getParameter("sp3") != null){
				ctx.setSp3(parameters.getParameter("sp3"));
			}

			if(numCompte != null) { 
				if(numCompte.startsWith("1")){   // Compte de classe 1
					ctx.setEtatId("FichesBudgetaires");
					ctx.setElementId("PageFichesBudgetaires");
					ctx.setPath("[n:EnteteFichesBudgetaires/@NumCompte="+numCompte+"][n:EnteteFichesBudgetaires/@CodRD="+CodRD+"]");

				} else if(numCompte.startsWith("2")){  // Compte de classe 2		
					ctx.setEtatId("FichesBudgetaires");
					ctx.setElementId("PageFichesBudgetaires");
					ctx.setPath("[n:EnteteFichesBudgetaires/@NumCompte="+numCompte+"][n:EnteteFichesBudgetaires/@CodRD="+CodRD+"]");

				} else if((numCompte.startsWith("4") || numCompte.startsWith("5")) && (!numCompte.startsWith("48") && !numCompte.startsWith("49"))){  // Compte de classe 4  ou 5      		
					XPath xp = XPathFactory.newInstance().newXPath();	    	
					String compteGestion = parameters.getParameter("cg");
					String typeLien = parameters.getParameter("type");

					String etatSolde = xp.evaluate("/Editions/Comptes[@Edition='"+compteGestion+"']/Compte[@Numero='"+numCompte+"']/@Solde",LiensBalance.getDocumentElement());	    	
					String etatDebit = xp.evaluate("/Editions/Comptes[@Edition='"+compteGestion+"']/Compte[@Numero='"+numCompte+"']/@Debit",LiensBalance.getDocumentElement());
					String etatCredit = xp.evaluate("/Editions/Comptes[@Edition='"+compteGestion+"']/Compte[@Numero='"+numCompte+"']/@Credit",LiensBalance.getDocumentElement());

					if(etatSolde!=null && !etatSolde.equals("") && typeLien.equals("solde")){
						String path = "";
						if(etatSolde.equals("ERAR") || etatSolde.equals("ERAP")){
							if(etatSolde.equals("ERAR")){
								path += "[n:EnteteSolde/@Type='RAR']";
							}else{
								path += "[n:EnteteSolde/@Type='RAP']";		    					
							}
							etatSolde="Solde";
						}
						ctx.setEtatId(etatSolde);
						ctx.setElementId("Page"+etatSolde);

						path += "[n:Entete"+etatSolde+"/@NumCompte="+numCompte+"]";
						if(CodRD!=null && !CodRD.equals("") && !etatSolde.equals("DeveloppementSoldes") && !etatSolde.equals("Solde") && !etatSolde.equals("LivreAuxiliaire")){
							path += "[n:Entete"+etatSolde+"/@CodRD="+CodRD+"]";
						}
						ctx.setPath(path);
					}else if(etatCredit!=null && !etatCredit.equals("") && typeLien.equals("totaux") && CodRD!=null && CodRD.equals("R")){
						String path = "";
						if(etatCredit.equals("ERAR") || etatCredit.equals("ERAP")){
							if(etatCredit.equals("ERAR")){
								path += "[n:EnteteSolde/@Type='RAR']";
							}else{
								path += "[n:EnteteSolde/@Type='RAP']";		    					
							}
							etatCredit="Solde";							
						}
						ctx.setEtatId(etatCredit);
						ctx.setElementId("Page"+etatCredit);

						path += "[n:Entete"+etatCredit+"/@NumCompte="+numCompte+"]";
						if(CodRD!=null && !CodRD.equals("") && !etatCredit.equals("DeveloppementSoldes") && !etatCredit.equals("Solde") && !etatCredit.equals("LivreAuxiliaire")){
							path += "[n:Entete"+etatCredit+"/@CodRD="+CodRD+"]";
						}
						ctx.setPath(path);
					}else if(etatDebit!=null && !etatDebit.equals("") && typeLien.equals("totaux") && CodRD!=null && CodRD.equals("D")){
						String path = "";
						if(etatDebit.equals("ERAR") || etatDebit.equals("ERAP")){
							if(etatDebit.equals("ERAR")){
								path += "[n:EnteteSolde/@Type='RAR']";
							}else{
								path += "[n:EnteteSolde/@Type='RAP']";		    					
							}
							etatDebit="Solde";
						}
						ctx.setEtatId(etatDebit);
						ctx.setElementId("Page"+etatDebit);

						path += "[n:Entete"+etatDebit+"/@NumCompte="+numCompte+"]";
						if(CodRD!=null && !CodRD.equals("") && !etatDebit.equals("DeveloppementSoldes") && !etatDebit.equals("Solde") && !etatDebit.equals("LivreAuxiliaire")){
							path += "[n:Entete"+etatDebit+"/@CodRD="+CodRD+"]";
						}
						ctx.setPath(path);
					} else {
						ctx.setEtatId("LivreAuxiliaire");
		    			ctx.setElementId("PageLivreAuxiliaire");
		    			ctx.setPath("[n:EnteteLivreAuxiliaire/@NumCompte="+numCompte+"]");
					}
				} else if(numCompte.startsWith("48")){  // Compte de classe 48
					ctx.setEtatId("FichesBudgetaires");
					ctx.setElementId("PageFichesBudgetaires");
					if(numCompte.contains("9")){
						CodRD="R";
					}else{
						CodRD="D";
					}
					ctx.setPath("[n:EnteteFichesBudgetaires/@NumCompte="+numCompte+"][n:EnteteFichesBudgetaires/@CodRD="+CodRD+"]");
				} else if(numCompte.startsWith("49")){  // Compte de classe 49
					ctx.setEtatId("FichesBudgetaires");
					ctx.setElementId("PageFichesBudgetaires");
					if(numCompte.contains("9")){
						CodRD="R";
					}else{
						CodRD="D";
					}
					ctx.setPath("[n:EnteteFichesBudgetaires/@NumCompte="+numCompte+"][n:EnteteFichesBudgetaires/@CodRD="+CodRD+"]");
				} else if(numCompte.startsWith("6")){  // Compte de classe 6
					ctx.setEtatId("FichesBudgetaires");
					ctx.setElementId("PageFichesBudgetaires");
					if(numCompte.contains("9")){
						CodRD="R";
					}else{
						CodRD="D";
					}
					ctx.setPath("[n:EnteteFichesBudgetaires/@NumCompte="+numCompte+"][n:EnteteFichesBudgetaires/@CodRD="+CodRD+"]");
				} else if(numCompte.startsWith("7")){  // Compte de classe 7
					ctx.setEtatId("FichesBudgetaires");
					ctx.setElementId("PageFichesBudgetaires");
					if(numCompte.contains("9")){
						CodRD="D";
					}else{
						CodRD="R";
					}
					ctx.setPath("[n:EnteteFichesBudgetaires/@NumCompte="+numCompte+"][n:EnteteFichesBudgetaires/@CodRD="+CodRD+"]");
				}
			}
		} catch (Exception e){
			e.printStackTrace();
		}
	}

	private void treatFichesBudgetaires(CustomLinkParameters parameters,NavigationContext ctx) throws UnresolvedException {
		try{
			//String numeroTypePiece = parameters.getParameter("numeroTypePiece");
			String codRD = parameters.getParameter("codRD");
			String exercice = parameters.getParameter("exercice");
			String mtEmis = parameters.getParameter("mtEmis");
			String mtAnn = parameters.getParameter("mtAnn");
            String mandatId = parameters.getParameter("mandatId");

			/*DocumentModel dm = MainWindow.getInstance().getDocModels().getDocumentById(parameters.getSrcDocId());
			EtatModel em = dm.getEtatById(parameters.getSrcEtatId());

			File f = new File(em.getParent().getBaseDirectory(),"cg-m14/TypesBordereaux.xml");
			DocumentBuilder domParser = DocumentBuilderFactory.newInstance().newDocumentBuilder();
	        Document typesBordereaux = domParser.parse(new FileInputStream(f));

	        XPath xp = XPathFactory.newInstance().newXPath();
	        Object pieces = null;
	        if(codRD.equals("D")){
	        	pieces = xp.evaluate("//Depense/Correspondance/Piece", typesBordereaux.getDocumentElement(), XPathConstants.NODESET);
	        }else{
	        	pieces = xp.evaluate("//Recette/Correspondance/Piece", typesBordereaux.getDocumentElement(), XPathConstants.NODESET);
	        }
	        Vector<String> typeBordereau = new Vector<String>();

	        if(pieces instanceof NodeList) {
		        NodeList nl = (NodeList)pieces; 
		        for(int i=0;i<nl.getLength();i++) {
		            Element piece = (Element)nl.item(i);
		            String libellePiece = piece.getAttribute("Libelle");
		            String codePiece = piece.getAttribute("Code");
		            if(numeroTypePiece.toLowerCase().contains(libellePiece.toLowerCase())){
		            	if(!codePiece.equals("13") && !codePiece.equals("14")){
		            		typeBordereau.add(piece.getParentNode().getAttributes().getNamedItem("TypeBordereauCode").getNodeValue());
		            	} else {
		            		if(mtEmis!=null && mtEmis.length()>0){
		            			typeBordereau.add("01");
		            		} else if(mtAnn!=null && mtAnn.length()>0){
		            			typeBordereau.add("02");
		            		}
		            	}
		            }
		        }
	        } else if(pieces instanceof List) {
	        	for(Element piece: (List<Element>)pieces) {
	        		String libellePiece = piece.getAttribute("Libelle");
	        		String codePiece = piece.getAttribute("Code");
	        		if(!codePiece.equals("13") && !codePiece.equals("14")){
	            		typeBordereau.add(piece.getParentNode().getAttributes().getNamedItem("TypeBordereauCode").getNodeValue());
	            	} else {
	            		if(mtEmis!=null && mtEmis.length()>0){
	            			typeBordereau.add("01");
	            		} else if(mtAnn!=null && mtAnn.length()>0){
	            			typeBordereau.add("02");
	            		}
	            	}
	        	}
	        }*/
			//logger.debug(this.getClass().getName()+" : Type Bordereau = "+typeBordereau.get(0));

			ctx.setDocId("PES_Aller");
			if(codRD.equals("D")){
				ctx.setEtatId("PES_DepenseAller");
				ctx.setElementId("Piece");
			}else{
				ctx.setEtatId("PES_RecetteAller");
				ctx.setElementId("PieceRecette");
			}

			if(parameters.getSrcCollectivite() != null){
				ctx.setCollectivite(parameters.getSrcCollectivite());
			}
			if(parameters.getSrcBudget() != null){
				ctx.setBudget(parameters.getSrcBudget());
			}
			if(ctx.getSp1() != null){
				//ctx.resetSp1();
				ctx.setSp1(null);
			}
			String typeBordereau ="";
			if(mtEmis!=null && mtEmis.length()>0){
				typeBordereau="01";
			} else if(mtAnn!=null && mtAnn.length()>0){
				typeBordereau="02";
			}
//			ctx.setPath("[n:BlocBordereau/n:Exer/@V="+exercice+"][n:BlocBordereau/n:TypBord/@V="+typeBordereau+"]");
            StringBuffer path = new StringBuffer();
            path.append("[../n:BlocBordereau/n:Exer/@V=").append(exercice).append("][../n:BlocBordereau/n:TypBord/@V=").append(typeBordereau).append("]");
            if("D".equals(codRD)) {
                path.append("[n:BlocPiece/n:InfoPce/n:IdPce/@V=").append(mandatId).append("]");
            } else {
                path.append("[n:BlocPiece/n:IdPce/@V=").append(mandatId).append("]");
            }
            ctx.setPath(path.toString());
		} catch (Exception e) {
			logger.debug("Erreur", e);
			throw new UnresolvedException("treatFichesBudgetaires(CustomLinkParameters parameters,NavigationContext ctx)");
		}
	}

	private void debug(Document doc){
		try {
			Transformer t = TransformerFactory.newInstance().newTransformer();
			//t.setOutputProperty(OutputKeys.INDENT, "yes");
			//t.setOutputProperty(OutputKeys.METHOD,"xml");
			System.out.println("\n******************* DEBUG *******************");
			t.transform(new DOMSource(doc), new StreamResult(System.out));
			System.out.println("\n***************** FIN DEBUG *******************");
		} catch (TransformerException e) {
			e.printStackTrace();
		}
	}

}
