/*
 * Copyright
 *   2008 axYus - www.axyus.com
 *   2008 C.Marchand - christophe.marchand@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.web.navigate;

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.data.DataLayerManager;
import fr.gouv.finances.dgfip.xemelios.services.XemeliosHelper;
import fr.gouv.finances.dgfip.xemelios.web.AttributeHelper;
import fr.gouv.finances.dgfip.xemelios.web.utils.StdDispatchAction;
import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.InputStream;
import java.net.URLDecoder;
import java.util.Enumeration;
import java.util.Hashtable;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSession;
import javax.xml.transform.Transformer;
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.XPathConstants;
import javax.xml.xpath.XPathFactory;
import net.sf.saxon.TransformerFactoryImpl;
import org.apache.log4j.Logger;
import org.apache.struts.action.ActionForm;
import org.apache.struts.action.ActionForward;
import org.apache.struts.action.ActionMapping;
import org.w3c.dom.Document;

public class DisplayDocumentAction extends StdDispatchAction {
    private static final Logger logger = Logger.getLogger(DisplayDocumentAction.class);

    @Override
    public ActionForward unspecified(ActionMapping mapping, ActionForm form, HttpServletRequest request, HttpServletResponse response) throws Exception {
        logger.debug(request.getQueryString());
        Hashtable<String,Object> parameters = new Hashtable<String,Object>();
        String documentId=null, etatId=null, elementId = null, docId = null;
        String collectiviteCode=null, budgetCode=null, collectiviteLib=null, budgetLib=null;
        HttpSession session = request.getSession();
        XemeliosUser user = AttributeHelper.getUser(session);
        
        for(Enumeration<String> names=request.getParameterNames();names.hasMoreElements();) {
            String paramName = names.nextElement();
            if(paramName.startsWith("xsl-param:")) {
                String xslParamName = paramName.substring("xsl-param:".length());
                String paramValue = URLDecoder.decode(request.getParameter(paramName), "UTF-8").trim();
                parameters.put(xslParamName,paramValue);
            } else if(paramName.equals("xsl:param")) {
                // ignore it here
            } else if("elementId".equals(paramName)) {
                elementId = URLDecoder.decode(request.getParameter(paramName), "UTF-8").trim();
            } else if("etatId".equals(paramName)) {
                etatId = URLDecoder.decode(request.getParameter(paramName), "UTF-8").trim();
            } else if("documentId".equals(paramName)) {
                documentId = URLDecoder.decode(request.getParameter(paramName), "UTF-8").trim();
            } else if("docId".equals(paramName)) {
                docId = URLDecoder.decode(request.getParameter(paramName), "UTF-8").trim();
            } else if("coll-code".equals(paramName)) {
                collectiviteCode = URLDecoder.decode(request.getParameter(paramName), "UTF-8").trim();
            } else if("budg-code".equals(paramName)) {
                budgetCode = URLDecoder.decode(request.getParameter(paramName), "UTF-8").trim();
            } else if("coll-lib".equals(paramName)) {
                collectiviteLib = URLDecoder.decode(request.getParameter(paramName), "UTF-8").trim();
            } else if("budg-lib".equals(paramName)) {
                budgetLib = URLDecoder.decode(request.getParameter(paramName), "UTF-8").trim();
            }
        }
        String[] xslParamsArray = request.getParameterValues("xsl:param");
        if(xslParamsArray!=null) {
            for(String xslParam:xslParamsArray) {
                int virg = xslParam.indexOf(',');
                String pName = xslParam.substring(1,virg);
                String pValue = xslParam.substring(virg+1,xslParam.length()-1);
                parameters.put(pName,pValue);
            }
        }

        Pair collectivite = new Pair(collectiviteCode,collectiviteLib);
        Pair budget = new Pair(budgetCode,budgetLib);
        
        if(documentId!=null && etatId!=null && elementId!=null && docId!=null) {
            DocumentModel documentModel = XemeliosHelper.getDocumentsModel(documentId);
            if(documentModel==null) throw new IllegalArgumentException("documentId parameter ("+documentId+") does not correspond to an existing document id.");
            EtatModel etatModel = documentModel.getEtatById(etatId);
            if(etatModel==null) throw new IllegalArgumentException("etatId parameter ("+etatId+") does not correspond to an existing etat id within "+documentId+" document.");
            ElementModel elementModel = etatModel.getElementById(elementId);
            if(elementModel==null) throw new IllegalArgumentException("elementId parameter ("+elementId+") does not correspond to an existing element id within "+documentId+" document / "+etatId+" etat.");
            
            XPath xp = XPathFactory.newInstance().newXPath();
            xp.setNamespaceContext(documentModel.getNamespaces());
            Document doc = DataLayerManager.getImplementation().getDocumentAsDom(etatModel, collectivite, budget, docId, user);
            if(doc==null) throw new Exception("Document introuvable: "+docId);
            String idRepository = null;
            if(documentModel.getReferenceNomenclaturePath()!=null && documentModel.getReferenceNomenclaturePath().getCodePath()!=null) {
                idRepository = (String)xp.evaluate(documentModel.getReferenceNomenclaturePath().getCodePath().getPath(),doc.getDocumentElement(),XPathConstants.STRING);
            }
            if(idRepository!=null && !(idRepository.length()>0)){
                idRepository=null;
            }
                        
            Document repository = DataLayerManager.getImplementation().getRepositoryAsDom(documentModel,collectivite,idRepository,user);
            if(repository!=null)
                parameters.put("repository",repository);
            parameters.put("config",XemeliosHelper.getDocumentsModel().getSmallDOM());
            parameters.put("collectivite",collectiviteCode);
            parameters.put("budget",budgetCode);
            parameters.put("collectivite-lib",collectivite.libelle);
            parameters.put("budget-lib",budget.libelle);
            parameters.put("browser-destination", "internal");  // il faut une destination "internal" pour avoir les liens.
            File f = null;
            f = new File(new File(new File(System.getProperty("user.home")),"xemelios/documents-def-ovrrd"),elementModel.getXslt());
            if(!f.exists())
                f = new File(documentModel.getBaseDirectory(),elementModel.getXslt());
            InputStream is = new FileInputStream(f);
            TransformerFactory tFactory = TransformerFactoryImpl.newInstance();
            tFactory.setURIResolver(new CustomURIResolver(tFactory.getURIResolver(), f.getParentFile().toURI().toURL().toExternalForm()));
            Transformer firstTrans = tFactory.newTransformer(new StreamSource(is));
            for(String key:parameters.keySet()) {
                firstTrans.setParameter(key, parameters.get(key));
            }
            ByteArrayOutputStream baos = new ByteArrayOutputStream();
            firstTrans.transform(new DOMSource(doc), new StreamResult(baos));
            is.close();

            File xslFile = new File(getServlet().getServletContext().getRealPath("/js/display/href-converter.xsl"));

            tFactory = TransformerFactoryImpl.newInstance();
            Transformer transformer = tFactory.newTransformer(new StreamSource(xslFile));
            transformer.setParameter("server",request.getServerName());
            transformer.setParameter("context",request.getContextPath());
            transformer.setParameter("port",request.getServerPort());
            ByteArrayInputStream bais = new ByteArrayInputStream(baos.toByteArray());
            AttributeHelper.setPreviousView(session,request.getServletPath()+"?"+request.getQueryString());
//            response.setContentType("text/html; charset=ISO-8859-1");
            transformer.transform(new StreamSource(bais), new StreamResult(response.getOutputStream()));
        }
        return null;
    }

}
