/*
 * Copyright 
 *   2005 axYus - www.axyus.com
 *   2005 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.importers;

import java.io.File;
import java.util.Collection;
import java.util.concurrent.CancellationException;
import java.util.concurrent.ExecutionException;

import javax.swing.SwingUtilities;

import org.apache.log4j.Logger;
import org.jdesktop.swingworker.SwingWorker;

import fr.gouv.finances.dgfip.utils.Pair;
import fr.gouv.finances.dgfip.xemelios.auth.XemeliosUser;
import fr.gouv.finances.dgfip.xemelios.common.FileInfo;
import fr.gouv.finances.dgfip.xemelios.common.PJRef;
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.DataImpl;
import fr.gouv.finances.dgfip.xemelios.data.DataLayerManager;

/**
 * Classe a surcharger pour creer des importeurs 
 * @author chm
 */
public abstract class EtatImporteur extends SwingWorker<String, String> {

    private static Logger logger = Logger.getLogger(EtatImporteur.class);
    protected DocumentModel dm;
    protected Pair col;
    protected Pair bdg;
    protected File[] filesToImport;
    protected PJRef[] pjs;
    protected Exception inProcessException = null;
    protected long start;
    private ImportServiceProvider impSvcProvider;
    protected XemeliosUser user;
    private FileInfo fileInfo = null;

    @Override
    public String doInBackground() {
        fileInfo = new FileInfo();
        start = System.currentTimeMillis();
        this.getImpSvcProvider().displayProgress((filesToImport==null?0:filesToImport.length) + (pjs==null?0:pjs.length));
        try {
            preProcess();
            if(filesToImport!=null) {
                for (int i = 0; i < filesToImport.length; i++) {
                    if (isCancelled()) {
                        break;
                    }
                    try {
                        File f = filesToImport[i];
                        final String fName = f.getName();
                        try {
                            if (SwingUtilities.isEventDispatchThread()) {
                                firePropertyChange("FILE_NAME", null, fName);
                            } else {
                                SwingUtilities.invokeAndWait(new Runnable() {

                                    public void run() {
                                        firePropertyChange("FILE_NAME", null, fName);
                                    }
                                });
                            }
                        } catch (Throwable t) {
                            logger.fatal("in fireFileName:", t);
                        }
                        preImportFile(f);
                        fileInfo.merge(importFile(f));
                        postImportFile(f);
                        /**
                         * FA 55 - FA 65: deplacement apres l'import du fichier
                         */
                        col = bdg = null;
                    // FIN FA 55
                    } catch (Exception ex) {
                        inProcessException = ex;
                        ex.printStackTrace();
                    }
                }
            }
        } catch (Exception ex) {
            inProcessException = ex;
            ex.printStackTrace();
        }
        try {
            postProcess(inProcessException != null);
        } catch (Exception ex) {
            inProcessException = ex;
            ex.printStackTrace();
        }
        if (!isCancelled()) {
            try {
                DataImpl di = DataLayerManager.getImplementation();
                if(pjs!=null) {
                    for (PJRef pj : pjs) {
                        if (isCancelled()) {
                            break;
                        }
                        final String fName = pj.getFileName();
                        try {
                            SwingUtilities.invokeAndWait(new Runnable() {

                                public void run() {
                                    firePropertyChange("FILE_NAME", null, fName);
                                }
                            });
                        } catch (Throwable t) {
                            logger.fatal("in fireFileName:", t);
                        }
                        if (pj.isValid()) {
                            di.importPj(pj,user);
                        }
                    }
                }
            } catch (Exception ex) {
                inProcessException = ex;
                ex.printStackTrace();
            }
        }
        StringBuffer msg = new StringBuffer();
        if (!isCancelled()) {
            msg.append("L'import des fichiers est terminé.\n");
            if (fileInfo.getGlobalCount() == 0) {
                msg.append("Pas de données importées.");
            } else {
                try {
                    msg.append(fileInfo.toString(Loader.getDocumentsInfos(null)));
                } catch(Exception ex) {
                    // on ignore tout
                }
                msg.append(getAdditionalMessage());
            }
        } else {
            msg.append("L'import des fichiers a été interrompu.");
        }
        logger.info("\n" + msg);
        firePropertyChange("terminated", null, msg);	// histoire de pas faire un new
        return msg.toString();
    }

    @Override
    protected void done() {
        super.done();
        if (inProcessException != null) {
            getImpSvcProvider().displayException(inProcessException);
        }
        String msg = "";
        try {
            msg = get();
        } catch (InterruptedException iEx) {
            iEx.printStackTrace();
        } catch (ExecutionException eEx) {
            eEx.printStackTrace();
        } catch (CancellationException cEx) {
            //cEx.printStackTrace();
            msg = "Import annulé";
        }
        getImpSvcProvider().displayMessage(msg, ImportServiceProvider.MSG_TYPE_INFORMATION);
    }
    public DocumentModel getDocumentModel() { return dm; }
    /**
     * Definit le modele de document
     * @param dm
     */
    public void setDocument(DocumentModel dm) {
        this.dm = dm;
    }

    /**
     * Definit le modele de document ainsi que la collectivite, le budget 
     * @param dm,bdg,col
     */
    public void setDocument(DocumentModel dm, Pair collectivite, Pair budget) {
        this.dm = dm;
        this.bdg = budget;
        this.col = collectivite;
    }

    /**
     * Importe le fichier
     * @param f le fichier a importer
     * @throws Exception
     */
    public abstract String getAdditionalMessage();

    /**
     * Definit les fichiers a importer
     * @param fichiers les fichiers a importer
     * @throws Exception
     */
    public void setFilesToImport(Collection<File> fichiers) throws Exception {
        Object[] data = fichiers.toArray();
        filesToImport = new File[data.length];
        for (int i = 0; i < data.length; i++) {
            filesToImport[i] = (File) data[i];
        }
    }

    public void setFilesToImport(File[] fichiers) throws Exception {
        filesToImport = fichiers;
    }

    public void setPjs(Collection<PJRef> piecesJointes) throws Exception {
        Object[] data = piecesJointes.toArray();
        pjs = new PJRef[data.length];
        for (int i = 0; i < data.length; i++) {
            pjs[i] = (PJRef) data[i];
        }
    }

    /**
     * Cette methode est appelee une unique fois avant l'import des fichiers.
     * Pour placer des initialisations et des prï¿½traitements, surcharger
     * cette mï¿½thode.
     * @throws Exception Si cette methode jette une exception, tout le traitement
     * d'import est stoppï¿½
     */
    protected void preProcess() throws Exception {
    }

    /**
     * Cette methode est appelee une unique fois apres l'import des fichiers.
     * Pour placer des post-traitements, surcharger cette mï¿½thode.
     * @param isErrorOccured Vaut <tt>true</tt> si le process d'import a leve
     * une exception, <tt>false</tt> si l'import s'est correctement deroule
     * @throws Exception
     */
    protected void postProcess(boolean isErrorOccured) throws Exception {
    }

    /**
     * Cette methode est appelee systematiquement pour chaque fichier a importer
     * avant l'appel ï¿½ la methode {@link import(File)}
     * @param f Le fichier qui sera importe.
     */
    protected void preImportFile(File f) throws Exception {
    }

    /**
     * Cette methode est appelee systematiquement pour chaque fichier a importer
     * apres l'appel ï¿½ la methode {@link import(File)}
     * @param f Le fichier qui a ete importe.
     */
    protected void postImportFile(File f) throws Exception {
    }

    protected abstract FileInfo importFile(File f) throws Exception;

//	@Override
//    protected void done() {
//        super.done();
//        
//        if(inProcessException!=null) {
//            new DisplayExceptionDlg((JFrame)null,inProcessException);
//        }
//        String msg="";
//        try {
//            msg=get();
//        } catch(InterruptedException iEx) {
//            iEx.printStackTrace();
//    	} catch(ExecutionException eEx) {
//    	    eEx.printStackTrace();
//    	} catch(CancellationException cEx) {
//    	    //cEx.printStackTrace();
//    	    msg = "Import annulï¿½";
//    	}
//        JOptionPane.showMessageDialog(owner,msg,"Import",JOptionPane.INFORMATION_MESSAGE);
//    }
    public ImportServiceProvider getImpSvcProvider() {
        return impSvcProvider;
    }

    public void setImpSvcProvider(ImportServiceProvider impSvcProvider) {
        this.impSvcProvider = impSvcProvider;
    }
    
    public XemeliosUser getUser() { return user; }
    public Pair getCollectivite() { return col; }
    public Pair getBudget() { return bdg; }
    public void setCollectivite(Pair p) { col=p; }
    public void setBudget(Pair p) { bdg=p; }
    public FileInfo getFileInfo() { return fileInfo; }
}
