/*
 * Copyright
 *   2007 axYus - www.axyus.com
 *   2008 L.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.plugin.signature;

import javax.swing.JFrame;
import javax.swing.JOptionPane;
import javax.swing.SwingUtilities;
import javax.swing.JFrame;
import javax.swing.JFileChooser;

import javax.swing.filechooser.FileFilter;
import java.io.File;

import org.apache.log4j.Logger;
import java.security.cert.X509Certificate;


import fr.gouv.finances.cp.xemelios.ui.MainWindow;
import fr.gouv.finances.cp.xemelios.common.config.DocumentModel;
import fr.gouv.finances.cp.xemelios.common.config.DocumentsModel;
import fr.gouv.finances.cp.xemelios.common.config.TraitementExterneModel;
import fr.gouv.finances.cp.xemelios.importers.EtatImporteur;
import java.util.ArrayList;

/**
 *  Cree une boite de dialogue permettant de choisir le fichier a verifier et
 * les conditions de traitement
 * Les options compliquées ne sont pas visibles à l'utilisateur ..
 * ce qui suppose qu'on les ait préparées dans le fichier de configuration
 * @author lm
 */
public class DlgSignatureLight extends javax.swing.JDialog {
//    private static Logger logger = Logger.getLogger(DlgSignatureLight.class);

    private JFrame parentWindow;
    File modelBaseDirectory;
    File fileToVerify = null;
    File fileToGenerate = null;
    JFileChooser fc;
    static Logger logger = Logger.getLogger(DlgSignatureLight.class);
    private TraitementExterneModel texModel = null;
    private DocumentModel docModel = null;

    /**
     * Constructeur sans parametre pour IDE
     */
    public DlgSignatureLight() {

    }

    /**
     * Creates a new instance of DlgSignatureLight 
     *@param  parent 
     *@param  modal 
     */
    public DlgSignatureLight(JFrame parent, boolean modal) {
        super(parent, modal);
        parentWindow = parent;
        initComponents();
        if (MainWindow.instance != null) {// Sinon on a tout faux
            DocumentsModel docModels = null;
            docModels = MainWindow.instance.getDocModels();
            docModel = docModels.getDocumentById("PES_Aller");
            logger.info(docModel);
            modelBaseDirectory = new File(docModel.getBaseDirectory());
            // logger.info(docModel);
            texModel = docModel.getTraitementExterneById("verification-signature");


        } else {


        }
        setLocationRelativeTo(parent);
    }

    /**
     * Montre le résultat de la vérification
     * @param verifier l'objet SignatureVerifier qui a opéré la vérification
     */
    public void showStatus(SignatureVerifier verifier) {
        String bla = verifier.getStatusAsString();

        int sever = verifier.getStatusAsSeverity();

        JOptionPane.showMessageDialog(parentWindow,
                bla,
                "Résultat de la vérification",
                sever == SignatureVerifier.VFY_VERYBAD ? JOptionPane.ERROR_MESSAGE : (sever == SignatureVerifier.VFY_BAD ? JOptionPane.WARNING_MESSAGE : JOptionPane.PLAIN_MESSAGE));
    }

    /**
     * Execute la vérification aprèes choix des parametres
     */
    public void doVerify() {
        if (fileToVerify != null) {
            SignatureVerifierFactory svf = SignatureVerifierFactory.newInstance(docModel.getNamespaces());
            SignatureVerifier verifier = null;

            // taille du fichier en Mega; si elle depasse la limite on essaiera
            // la librairie JNI
            int sizeM = (int) (fileToVerify.length() / 1000000);
//            System.out.println("Actual File size=" + sizeM);
            svf.setAttribute(SignatureVerifierFactory.ACTUAL_FILE_SIZE, sizeM);

            if (texModel != null) {
                String paramval;
                // System.out.println("Found texModel");
                svf.setAttribute(SignatureVerifierFactory.DO_POSTTRAIT, false);
                paramval = texModel.getParameterValue("always_use_libxml2");
                if (paramval != null && "true".equals(paramval)) {
                    svf.setAttribute(SignatureVerifierFactory.USE_APACHEXMLSEC, false);
                    svf.setAttribute(SignatureVerifierFactory.USE_LIBXML2, true);
                } else {
                    svf.setAttribute(SignatureVerifierFactory.USE_APACHEXMLSEC, true);
                    svf.setAttribute(SignatureVerifierFactory.USE_LIBXML2, false);
                }
                paramval = texModel.getParameterValue("do_validation");
                if (paramval != null && "true".equals(paramval)) {
                    svf.setAttribute(SignatureVerifierFactory.VALIDATE_SCHEMA_OR_DTD, true);
                } else {
                    svf.setAttribute(SignatureVerifierFactory.VALIDATE_SCHEMA_OR_DTD, false);
                }
                //   paramval = texModel.getParameterValue("do_posttrait" ); 
//              if(paramval != null&& "true".equals(paramval) ) {
//                 svf.setAttribute(SignatureVerifierFactory.DO_POSTTRAIT, true);
//              }else {
//                 svf.setAttribute(SignatureVerifierFactory.DO_POSTTRAIT, false);
//              }
                paramval = texModel.getParameterValue("signature_xpath");
                if (paramval != null) {
                    logger.debug("Found paramval=" + paramval);
                    svf.setAttribute(SignatureVerifierFactory.SIGNATURE_XPATH, paramval);
                } else {
                    svf.setAttribute(SignatureVerifierFactory.SIGNATURE_XPATH, "//ds:Signature");
                }
                paramval = texModel.getParameterValue("external_dtd");
                if (paramval != null) {
                    logger.debug("Found paramval=" + paramval);
                    File exdtdf = new File(modelBaseDirectory, paramval);
                    svf.setAttribute(SignatureVerifierFactory.EXTERNAL_DTD, exdtdf.getAbsolutePath());
                } else {
                    svf.setAttribute(SignatureVerifierFactory.EXTERNAL_DTD, "src/pes-aller/conf/PES_V2/pes_v2.DTD");
                }

                paramval = texModel.getParameterValue("max_file_size_apachexmlsec");
                if (paramval != null) {
                    //   System.out.println("Found paramval=" + paramval);
                    int numval = Integer.parseInt(paramval);

                    svf.setAttribute(SignatureVerifierFactory.MAX_FILE_SIZE_APACHEXMLSEC, numval);
                } else {
                    svf.setAttribute(SignatureVerifierFactory.MAX_FILE_SIZE_APACHEXMLSEC, 10);
                }


            } else {

                svf.setAttribute(SignatureVerifierFactory.DO_POSTTRAIT, false);
                svf.setAttribute(SignatureVerifierFactory.USE_APACHEXMLSEC, true);
                svf.setAttribute(SignatureVerifierFactory.USE_LIBXML2, false);
                svf.setAttribute(SignatureVerifierFactory.VALIDATE_SCHEMA_OR_DTD, false);

                svf.setAttribute(SignatureVerifierFactory.SIGNATURE_XPATH, "//ds:Signature");
                svf.setAttribute(SignatureVerifierFactory.EXTERNAL_DTD, "src/pes-aller/conf/pes_v2.DTD");
            }


            if (false) { // on ne veur pas de report de bordereau dans la verions Xemelios

                // Show save dialog; this method does not return until the dialog is closed
                if (fileToGenerate != null) {
                    fc = new JFileChooser(fileToGenerate);
                } else {
                    fc = new JFileChooser(".");
                }
                fc.addChoosableFileFilter(new FileFilter() {

                    public boolean accept(File f) {
                        return f.isDirectory() || f.getName().toUpperCase().endsWith("XML");
                    }

                    public String getDescription() {
                        return "Document XML";
                    }
                });
                fc.showSaveDialog(null);
                fileToGenerate = fc.getSelectedFile();
                if (fileToGenerate == null) {
                    return;
                }
            }
            try {
                verifier = svf.newSignatureVerifier();
                verifier.initialize();
                verifier.verifyFile(fileToVerify.getAbsolutePath());
                if (verifier.hasPostTrait()) {
                    verifier.postTraitement(fileToGenerate.getAbsolutePath());
                }
                for (int i = 0; i < verifier.getFoundSignatures(); ++i) {
                    Integer istatus = verifier.getIndividualStatus(i);
                    if (istatus != null) {
                        if (verifier.digestValid(istatus.intValue())) {
                            logger.info("Signature " + i + ":VALIDE");
                        } else {
                            logger.info("Signature " + i + ":INVALIDE");
                        }
                        if (verifier.isX509Cert(istatus.intValue())) {
                            logger.info("Signature " + i + "=> certificat X509");
                            X509Certificate cert = verifier.getCert(i);
                            if (cert != null) {
                                logger.info("PRINTING CERT=");
                                logger.info(cert);
                            }
                        } else {
                            logger.info("Signature " + i + ":pas de certificat");
                        }
                    }
                }
               /* for (int i = 0; i < verifier.getCertVectorSize(); ++i) {
                    X509Certificate cert = verifier.getCert(i);
                    if (cert != null) {
                        System.out.println("PRINTING CERT=");
                        System.out.println(cert);
                    }
                }*/
                verifier.terminate();
            } catch (Exception e) {

                e.printStackTrace();

            }
            if (verifier != null) {
                showStatus(verifier);
            }
//            if (jCheckBoxFermerApres.isSelected()) {
//                close();
//            }
            if(GlobalSignaturePlugin.isInXemelios()) {
                if(verifier.getStatusAsSeverity()==SignatureVerifier.VFY_GOOD) {
                    if(JOptionPane.showConfirmDialog(this, "Voulez-vous importer ce fichier ?","Importer",JOptionPane.YES_NO_OPTION)==JOptionPane.YES_OPTION) {
                        DocumentModel dm = MainWindow.getInstance().getDocModels().getDocumentById("PES_Aller");
                        try {
                            Class clazz = Class.forName(dm.getImportClass());
                            Object obj = clazz.newInstance();
                            if(!(obj instanceof EtatImporteur)) {
                                JOptionPane.showMessageDialog(this,"Cette classe n'est pas un importeur.\nLe fichier de configuration qui vous a été livré est certainement invalide.\nVeuillez contacter votre fournisseur.\n","Erreur",JOptionPane.ERROR_MESSAGE);
                                return;
                            }
                            EtatImporteur ei = (EtatImporteur)obj;
                            MainWindow.ImportContent fToImport = new MainWindow.ImportContent();
                            ArrayList<File> files = new ArrayList<File>();
                            files.add(fileToVerify);
                            fToImport.setFilesToImport(files);
                            MainWindow.getInstance().doImport(ei,fToImport,dm, false);
                        } catch(Exception ex) {}
                    }
                }
            }
            setVisible(false);
        } else {
            JOptionPane.showMessageDialog(parentWindow, "Il faut d'abord sélectionner un fichier!");
        }

    }

    /**
     * 
     */
    public void ShowInputFileSelector() {
        if (fileToVerify != null) {
            fc = new JFileChooser(fileToVerify);
        } else {
            fc = new JFileChooser(".");
        }
        fc.addChoosableFileFilter(new FileFilter() {

            public boolean accept(File f) {
                return f.isDirectory() || f.getName().toUpperCase().endsWith("XML");
            }

            public String getDescription() {
                return "Document XML";
            }
        });
        // Show open dialog; this method does not return until the dialog is closed
        fc.showOpenDialog(null);
        fileToVerify = fc.getSelectedFile();
        if (fileToVerify != null) {
            textFieldInputFile.setText(fileToVerify.getAbsolutePath());
        }

    }

    /** This method is called from within the constructor to
     * initialize the form.
     * WARNING: Do NOT modify this code. The content of this method is
     * always regenerated by the Form Editor.
     */
    // <editor-fold defaultstate="collapsed" desc="Generated Code">
    public void run() {
//        setSize(400, 330);
        setVisible(true);
    }

    /**
     * 
     */
    public void close() {
        SwingUtilities.getWindowAncestor(this).dispose();
    }

    /**
     * @param args the command line arguments
     */
    public static void main(String args[]) {
        java.awt.EventQueue.invokeLater(new Runnable() {

            public void run() {
                JFrame frame = new JFrame("test");
                DlgSignatureLight dialog = new DlgSignatureLight(frame, true);
                dialog.addWindowListener(new java.awt.event.WindowAdapter() {

                    @Override
                    public void windowClosing(java.awt.event.WindowEvent e) {
                        System.exit(0);
                    }
                });

                dialog.run();
            }
        });
    }

    // <editor-fold defaultstate="collapsed" desc="Generated Code">//GEN-BEGIN:initComponents
    private void initComponents() {

        buttonGroup1 = new javax.swing.ButtonGroup();
        jDialog1 = new javax.swing.JDialog();
        jDialog2 = new javax.swing.JDialog();
        jDialog3 = new javax.swing.JDialog();
        jDialog4 = new javax.swing.JDialog();
        jButtonOK = new javax.swing.JButton();
        jButtonAnnuler = new javax.swing.JButton();
        jLabel1 = new javax.swing.JLabel();
        jButtonInputFile = new javax.swing.JButton();
        label1 = new java.awt.Label();
        textFieldInputFile = new javax.swing.JTextField();

        org.jdesktop.layout.GroupLayout jDialog1Layout = new org.jdesktop.layout.GroupLayout(jDialog1.getContentPane());
        jDialog1.getContentPane().setLayout(jDialog1Layout);
        jDialog1Layout.setHorizontalGroup(
            jDialog1Layout.createParallelGroup(org.jdesktop.layout.GroupLayout.LEADING)
            .add(0, 400, Short.MAX_VALUE)
        );
        jDialog1Layout.setVerticalGroup(
            jDialog1Layout.createParallelGroup(org.jdesktop.layout.GroupLayout.LEADING)
            .add(0, 300, Short.MAX_VALUE)
        );

        org.jdesktop.layout.GroupLayout jDialog2Layout = new org.jdesktop.layout.GroupLayout(jDialog2.getContentPane());
        jDialog2.getContentPane().setLayout(jDialog2Layout);
        jDialog2Layout.setHorizontalGroup(
            jDialog2Layout.createParallelGroup(org.jdesktop.layout.GroupLayout.LEADING)
            .add(0, 400, Short.MAX_VALUE)
        );
        jDialog2Layout.setVerticalGroup(
            jDialog2Layout.createParallelGroup(org.jdesktop.layout.GroupLayout.LEADING)
            .add(0, 300, Short.MAX_VALUE)
        );

        org.jdesktop.layout.GroupLayout jDialog3Layout = new org.jdesktop.layout.GroupLayout(jDialog3.getContentPane());
        jDialog3.getContentPane().setLayout(jDialog3Layout);
        jDialog3Layout.setHorizontalGroup(
            jDialog3Layout.createParallelGroup(org.jdesktop.layout.GroupLayout.LEADING)
            .add(0, 400, Short.MAX_VALUE)
        );
        jDialog3Layout.setVerticalGroup(
            jDialog3Layout.createParallelGroup(org.jdesktop.layout.GroupLayout.LEADING)
            .add(0, 300, Short.MAX_VALUE)
        );

        org.jdesktop.layout.GroupLayout jDialog4Layout = new org.jdesktop.layout.GroupLayout(jDialog4.getContentPane());
        jDialog4.getContentPane().setLayout(jDialog4Layout);
        jDialog4Layout.setHorizontalGroup(
            jDialog4Layout.createParallelGroup(org.jdesktop.layout.GroupLayout.LEADING)
            .add(0, 400, Short.MAX_VALUE)
        );
        jDialog4Layout.setVerticalGroup(
            jDialog4Layout.createParallelGroup(org.jdesktop.layout.GroupLayout.LEADING)
            .add(0, 300, Short.MAX_VALUE)
        );

        setDefaultCloseOperation(javax.swing.WindowConstants.DISPOSE_ON_CLOSE);
        setTitle("Vérification Flux PES Signé");

        jButtonOK.setText("Vérifier");
        jButtonOK.setName("jButtonOK"); // NOI18N
        jButtonOK.addActionListener(new java.awt.event.ActionListener() {
            public void actionPerformed(java.awt.event.ActionEvent evt) {
                jButtonOKActionPerformed(evt);
            }
        });

        jButtonAnnuler.setText("Fermer");
        jButtonAnnuler.setName("jButtonAnnuler"); // NOI18N
        jButtonAnnuler.addActionListener(new java.awt.event.ActionListener() {
            public void actionPerformed(java.awt.event.ActionEvent evt) {
                jButtonAnnulerActionPerformed(evt);
            }
        });

        jLabel1.setName("jLabel1"); // NOI18N

        jButtonInputFile.setText("...");
        jButtonInputFile.setName("jButtonInputFile"); // NOI18N
        jButtonInputFile.addActionListener(new java.awt.event.ActionListener() {
            public void actionPerformed(java.awt.event.ActionEvent evt) {
                jButtonInputFileActionPerformed(evt);
            }
        });

        label1.setText("Fichier à analyser...");

        org.jdesktop.layout.GroupLayout layout = new org.jdesktop.layout.GroupLayout(getContentPane());
        getContentPane().setLayout(layout);
        layout.setHorizontalGroup(
            layout.createParallelGroup(org.jdesktop.layout.GroupLayout.LEADING)
            .add(layout.createSequentialGroup()
                .add(layout.createParallelGroup(org.jdesktop.layout.GroupLayout.LEADING)
                    .add(layout.createSequentialGroup()
                        .add(313, 313, 313)
                        .add(jLabel1))
                    .add(layout.createSequentialGroup()
                        .addContainerGap()
                        .add(label1, org.jdesktop.layout.GroupLayout.PREFERRED_SIZE, org.jdesktop.layout.GroupLayout.DEFAULT_SIZE, org.jdesktop.layout.GroupLayout.PREFERRED_SIZE))
                    .add(org.jdesktop.layout.GroupLayout.TRAILING, layout.createSequentialGroup()
                        .addContainerGap()
                        .add(jButtonAnnuler)
                        .addPreferredGap(org.jdesktop.layout.LayoutStyle.UNRELATED)
                        .add(jButtonOK))
                    .add(org.jdesktop.layout.GroupLayout.TRAILING, layout.createSequentialGroup()
                        .addContainerGap()
                        .add(textFieldInputFile, org.jdesktop.layout.GroupLayout.DEFAULT_SIZE, 334, Short.MAX_VALUE)
                        .add(12, 12, 12)
                        .add(jButtonInputFile, org.jdesktop.layout.GroupLayout.PREFERRED_SIZE, 28, org.jdesktop.layout.GroupLayout.PREFERRED_SIZE)))
                .addContainerGap())
        );
        layout.setVerticalGroup(
            layout.createParallelGroup(org.jdesktop.layout.GroupLayout.LEADING)
            .add(layout.createSequentialGroup()
                .addContainerGap()
                .add(label1, org.jdesktop.layout.GroupLayout.PREFERRED_SIZE, org.jdesktop.layout.GroupLayout.DEFAULT_SIZE, org.jdesktop.layout.GroupLayout.PREFERRED_SIZE)
                .addPreferredGap(org.jdesktop.layout.LayoutStyle.RELATED, org.jdesktop.layout.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)
                .add(layout.createParallelGroup(org.jdesktop.layout.GroupLayout.LEADING)
                    .add(jButtonInputFile)
                    .add(textFieldInputFile, org.jdesktop.layout.GroupLayout.PREFERRED_SIZE, org.jdesktop.layout.GroupLayout.DEFAULT_SIZE, org.jdesktop.layout.GroupLayout.PREFERRED_SIZE))
                .add(28, 28, 28)
                .add(layout.createParallelGroup(org.jdesktop.layout.GroupLayout.LEADING, false)
                    .add(jLabel1)
                    .add(layout.createParallelGroup(org.jdesktop.layout.GroupLayout.BASELINE)
                        .add(jButtonOK, org.jdesktop.layout.GroupLayout.DEFAULT_SIZE, 27, Short.MAX_VALUE)
                        .add(jButtonAnnuler, org.jdesktop.layout.GroupLayout.DEFAULT_SIZE, org.jdesktop.layout.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)))
                .addContainerGap())
        );

        label1.getAccessibleContext().setAccessibleName("");
        label1.getAccessibleContext().setAccessibleParent(jLabel1);

        pack();
    }// </editor-fold>//GEN-END:initComponents
   private void jButtonOKActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_jButtonOKActionPerformed
       doVerify(); 
   }//GEN-LAST:event_jButtonOKActionPerformed
   private void jButtonAnnulerActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_jButtonAnnulerActionPerformed
       close();
   }//GEN-LAST:event_jButtonAnnulerActionPerformed
   private void jButtonInputFileActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_jButtonInputFileActionPerformed
       ShowInputFileSelector();
   }//GEN-LAST:event_jButtonInputFileActionPerformed

    // Variables declaration - do not modify//GEN-BEGIN:variables
    private javax.swing.ButtonGroup buttonGroup1;
    private javax.swing.JButton jButtonAnnuler;
    private javax.swing.JButton jButtonInputFile;
    private javax.swing.JButton jButtonOK;
    private javax.swing.JDialog jDialog1;
    private javax.swing.JDialog jDialog2;
    private javax.swing.JDialog jDialog3;
    private javax.swing.JDialog jDialog4;
    private javax.swing.JLabel jLabel1;
    private java.awt.Label label1;
    private javax.swing.JTextField textFieldInputFile;
    // End of variables declaration//GEN-END:variables
}
