/*
 * Copyright
 *   2007 axYus - www.axyus.com
 *   2009 c.Marhcand - 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 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.dgfip.xemelios.cg.refCollecPatcher;

import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.InputStream;
import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.ResultSet;

import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.DocumentBuilderFactory;
import javax.xml.transform.OutputKeys;
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 net.sf.saxon.TransformerFactoryImpl;

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

import fr.gouv.finances.dgfip.xemelios.common.FileInfo;
import fr.gouv.finances.dgfip.xemelios.common.config.DocumentModel;
import fr.gouv.finances.dgfip.xemelios.common.config.Loader;
import fr.gouv.finances.dgfip.xemelios.data.impl.pool.PoolManager;
import fr.gouv.finances.dgfip.xemelios.importers.AbstractImportPatcherImpl;

/**
 *
 * @author christophe.marchand
 */
public class RefCollecPatcher extends AbstractImportPatcherImpl {
    private static final Logger logger = Logger.getLogger(RefCollecPatcher.class);
    protected DocumentBuilderFactory domFactory;
    protected TransformerFactory transformerFactory;

    public RefCollecPatcher() {
        super();
        domFactory = DocumentBuilderFactory.newInstance();
        domFactory.setNamespaceAware(true);
        transformerFactory = TransformerFactoryImpl.newInstance();
    }
    public FileInfo run() {
        FileInfo ret = new FileInfo();
        getImportServiceProvider().startLongWait();
        String collectiviteId = (String)getParameter("collectivite-id");
        Integer exercice = (Integer)getParameter("exercice");
        Connection conPatch = null, con2 = null, con3=null;
        int rowPatched = 0;
        try {
            DocumentModel dm = Loader.getDocumentsInfos(null).getDocumentById("ref-collec-spl");
            if(dm==null) return ret;    // le document n'est pas dispo, on ne patch pas
            conPatch = PoolManager.getInstance().getConnection();
            con2 = PoolManager.getInstance().getConnection();
            PreparedStatement ps = conPatch.prepareStatement("SELECT COLLECTIVITE, BUDGET, DOC_ID FROM REF_COLL_SPL_COLLECTIVITESSPL_COLL_IX WHERE IDCOLL=? AND EXERCICE=?");
            ps.setString(1,collectiviteId);
            ps.setInt(2, exercice);
            ResultSet rs = ps.executeQuery();
            while(rs.next()) {
                if(patchDocument(rs.getString(1), rs.getString(2), rs.getString(3),con2)) rowPatched++;
            }
        } catch(Exception ex) {
            logger.error("run() - collectivite-id="+collectiviteId,ex);
        } finally {
            if(conPatch!=null) {
                PoolManager.getInstance().releaseConnection(conPatch);
            }
            if(con2!=null) PoolManager.getInstance().releaseConnection(con2);
            getImportServiceProvider().endLongWait();
        }
        ret.setMessage(rowPatched+" collectivités amendées par cet import\n");
        return ret;
    }

    private boolean patchDocument(String collectivite,String budget,String docId,Connection con) throws Exception {
        boolean ret = true;
        PreparedStatement ps = con.prepareStatement("UPDATE REF_COLL_SPL_COLLECTIVITESSPL_COLL_IX SET ARCHIVE='Oui' WHERE COLLECTIVITE=? AND BUDGET=? AND DOC_ID=?");
        ps.setString(1,collectivite);
        ps.setString(2, budget);
        ps.setString(3, docId);
        ps.executeUpdate();

        ps = con.prepareStatement("SELECT DOC, ENCODING FROM REF_COLL_SPL_DOCUMENTS WHERE COLLECTIVITE=? AND BUDGET=? AND DOC_ID=?");
        ps.setString(1,collectivite);
        ps.setString(2,budget);
        ps.setString(3,docId);
        ResultSet rs = ps.executeQuery();
        if(rs.next()) {
            String encoding = rs.getString(2);
            byte[] buff = new byte[512];
            ByteArrayOutputStream baos = new ByteArrayOutputStream();
            InputStream is = rs.getAsciiStream(1);
            int length = is.read(buff);
            while (length > 0) {
                baos.write(buff, 0, length);
                length = is.read(buff);
            }
            DocumentBuilder builder = domFactory.newDocumentBuilder();
            byte[] byteArray = baos.toByteArray();
            InputStream bis = new ByteArrayInputStream(byteArray);
            Document doc = builder.parse(bis);

            Transformer trans = transformerFactory.newTransformer(new StreamSource(this.getClass().getClassLoader().getResourceAsStream("fr/gouv/finances/dgfip/xemelios/cg/refCollecPatcher/collec-patcher.xsl")));
            ByteArrayOutputStream newDoc = new ByteArrayOutputStream();
            // préparation de l'objet Liasses
            DocumentBuilder domBuilder = domFactory.newDocumentBuilder();
            trans.setParameter("archive","Oui");
            trans.setOutputProperty(OutputKeys.ENCODING, encoding);
            trans.transform(new DOMSource(doc), new StreamResult(newDoc));
            ps.close();
            ps = con.prepareStatement("UPDATE REF_COLL_SPL_DOCUMENTS SET DOC=? WHERE COLLECTIVITE=? AND BUDGET=? AND DOC_ID=?");
            ps.setString(2,collectivite);
            ps.setString(3,budget);
            ps.setString(4,docId);
            byte[] newDocArray = newDoc.toByteArray();
            InputStream isNewDoc = new ByteArrayInputStream(newDocArray);
            ps.setBinaryStream(1, isNewDoc, newDocArray.length);
            if(ps.executeUpdate()>0) ret = true;
            ps.close();
        }
        return ret;
    }
}
