/*
 * Copyright
 *   2007 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 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.plugins;

import java.awt.Graphics;
import java.util.Hashtable;

import javax.swing.JDialog;
import javax.swing.JFrame;
import javax.swing.SwingUtilities;

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

import com.jgoodies.forms.builder.PanelBuilder;
import com.jgoodies.forms.layout.CellConstraints;
import com.jgoodies.forms.layout.FormLayout;

import fr.gouv.finances.dgfip.utils.Pair;
import fr.gouv.finances.cp.utils.ui.IhmFactory;
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.PluginModel;
import fr.gouv.finances.cp.xemelios.importers.ImportServiceSwingProvider.PaintableProgress;
import fr.gouv.finances.cp.xemelios.ui.MainWindow;
import fr.gouv.finances.cp.xemelios.ui.SearchWindow;
import fr.gouv.finances.dgfip.xemelios.plugins.ExportPlugin.ProgressListener;

/**
 * Defines contract to make plugins.
 * An implementation must provide a constructor with no parameters
 * @author chm
 */
public abstract class XemeliosPlugin extends SwingWorker<Object, String> implements ProgressListener {

    private static final Logger logger = Logger.getLogger(XemeliosPlugin.class);
    public static final int TYPE_SEARCH = 1;
    public static final int TYPE_EXPORT = 2;
    private ElementModel elementModel;
    private EtatModel etatModel;
    private DocumentModel documentModel;
    private Hashtable<String, String> params;
    private PluginModel pm;
    private int maxProgress;
    private String progressMessage;
    private ProgressDlg progress = null;
    private long start;
    private SearchWindow sw;
    private Pair collectivite = null,  budget = null, refenrenceNomenclature = null;


    public abstract int getPluginType();
    private MainWindow owner;

    public void setOwner(fr.gouv.finances.cp.xemelios.ui.MainWindow owner) {
        this.owner = owner;
    }

    public JFrame getOwner() {
        return owner;
    }

    public void setElementModel(ElementModel em) {
        this.elementModel = em;
        this.etatModel = this.elementModel.getParent();
        this.documentModel = this.etatModel.getParent();
    }

    protected final ElementModel getElementModel() {
        return elementModel;
    }

    protected final EtatModel getEtatModel() {
        return etatModel;
    }

    protected final DocumentModel getDocumentModel() {
        return documentModel;
    }

    public void setParameters(Hashtable<String, String> params) {
        this.params = params;
    }

    protected final Hashtable<String, String> getParameters() {
        return params;
    }

    public void setModel(PluginModel pm) {
        this.pm = pm;
    }

    public void setStart(long start) {
        this.start = start;
    }

    public long getStart() {
        return start;
    }

    protected final PluginModel getPluginModel() {
        return pm;
    }

    public void setCollectivite(Pair collectivite) {
        this.collectivite = collectivite;
    }

    public void setBudget(Pair budget) {
        this.budget = budget;
    }

    public Pair getBudget() {
        return budget;
    }

    public Pair getCollectivite() {
        return collectivite;
    }

    public void setProgressInfos(int maxProgress, String progressMessage) {
        this.maxProgress = maxProgress;
        this.progressMessage = progressMessage;
    }

    public void pushProgress() {
        if (progress != null) {
            progress.pushProgress();
        }
    }

    public void setProgressVisible(boolean show) {
        if (show) {
            progress = new ProgressDlg(owner, maxProgress, progressMessage);
            progress.setVisible(true);
        } else if (progress != null) {
            progress.setDefaultCloseOperation(JDialog.DISPOSE_ON_CLOSE);
            progress.setVisible(false);
        }
    }

    @Override
    public void done() {
        owner.stopWaiter();
    }

    public void setSearchWindow(SearchWindow sw) {
        this.sw = sw;
    }

    public SearchWindow getSearchWindow() {
        return sw;
    }

    public final class ProgressDlg extends JDialog implements ProgressListener {

        /**
         * Comment for <code>serialVersionUID</code>
         */
        private static final long serialVersionUID = 1L;
        public static final String DEFAULT_TEXT = "Recherche en cours : ";
        private PaintableProgress globalProgress;
        private int maxProgress,  value = 0;
        private String progressMessage;

        public ProgressDlg(JFrame owner, int maxProgress, String progressMessage) {
            super(owner, DEFAULT_TEXT);
            this.maxProgress = maxProgress;
            this.progressMessage = progressMessage;
            initComponents();
        }

        protected void initComponents() {
            IhmFactory iF = IhmFactory.newInstance();
            FormLayout fl = null;
            fl = new FormLayout("3dlu,pref,3dlu", "3dlu,pref,1dlu,pref,3dlu");
            CellConstraints cc = new CellConstraints();
            PanelBuilder pb = new PanelBuilder(fl);

            pb.add(iF.newLabel(progressMessage, "normal"), cc.xy(2, 2));
            globalProgress = new PaintableProgress(0, 100);
            globalProgress.setStringPainted(true);
            globalProgress.setMaximum(maxProgress);
            pb.add(globalProgress, cc.xy(2, 4));

            setContentPane(pb.getPanel());
            setResizable(false);
            setDefaultCloseOperation(DO_NOTHING_ON_CLOSE);
            pack();
            setLocationRelativeTo(getOwner());
            setVisible(true);
            Graphics g = getGraphics();
            g.setClip(0, 0, getWidth(), getHeight());
            paint(g);
        }

        public void repaintImmediatly() {
            Runnable code = new Runnable() {

                public void run() {
                    globalProgress.paintImmediatly();
                    Graphics g = getGraphics();
                    g.setClip(0, 0, getWidth(), getHeight());
                    if (isLightweight()) {
                        paint(g);
                    } else {
                        update(g);
                    }
                }
            };
            if (SwingUtilities.isEventDispatchThread()) {
                code.run();
            } else {
                try {
                    SwingUtilities.invokeAndWait(code);
                } catch (Throwable t) {
                    logger.error("repaintImmediatly", t);
                }
            }
        }

        public void pushProgress() {
            value++;
//    	    logger.debug("progress: "+value);
            globalProgress.setValue(value);
            repaintImmediatly();
        //repaint();
        }

        public void setProgressInfos(int maxProgress, String progressMessage) {
            //throw new UnsupportedOperationException("Not supported yet.");
        }

        public void setProgressVisible(boolean show) {
            //throw new UnsupportedOperationException("Not supported yet.");
        }
    }
}
