/*
 * Copyright
 *   2007 axYus - www.axyus.com
 *   2007 N.Le Corre - nicolas.lecorre@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.ui;

import java.awt.Cursor;
import java.awt.event.ActionEvent;
import java.util.StringTokenizer;

import javax.swing.JOptionPane;
import javax.swing.tree.TreePath;

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

import fr.gouv.finances.cp.utils.Pair;
import fr.gouv.finances.cp.utils.ui.DisplayExceptionDlg;
import fr.gouv.finances.cp.xemelios.common.config.DocumentModel;
import fr.gouv.finances.cp.xemelios.common.config.DocumentsModel;
import fr.gouv.finances.cp.xemelios.data.DataAccessException;
import fr.gouv.finances.cp.xemelios.data.DataConfigurationException;
import fr.gouv.finances.cp.xemelios.data.DataLayerManager;

@SuppressWarnings("serial")
public class DlgCleanDatabase extends DlgChooseDocuments {
    private static Logger logger = Logger.getLogger(DlgCleanDatabaseOld.class);
    
    public DlgCleanDatabase(java.awt.Frame parent, boolean modal, DocumentsModel _dm) {
        super(parent, modal, _dm, true);
        setTitle("Suppression");
        setBActionLibelle("Supprimer");
        setVisible(true);
    }
    
    @Override
    protected void doAction(ActionEvent evt) {
        if (getJTabbedPane1().getSelectedComponent() instanceof PanelChooseDatabaseDonnees)
            purge(((PanelChooseDatabaseDonnees)getJTabbedPane1().getSelectedComponent()).getJTree1().getSelectionPath());
        if (getJTabbedPane1().getSelectedComponent() instanceof PanelChooseDatabaseFichier)
            purgeFichiers();
    }
    
    /**
     * SUPPRESSION PAR FICHIER
     */
    protected void purgeFichiers() {
        if(JOptionPane.showConfirmDialog(this,"Etes-vous sur de vouloir supprimer les informations définitivement ?\n\nCette opération peut prendre beaucoup de temps\nsi le nombre d'éléments à supprimer est important.","Suppression",JOptionPane.YES_NO_OPTION)==JOptionPane.YES_OPTION) {
            DatabaseTreeDataFichier.Data datas =  ((PanelChooseDatabaseFichier)getJTabbedPane1().getSelectedComponent()).getData().getData();
            for (DatabaseTreeDataFichier.Data d:datas.getChilds()) {
//        		logger.debug("avant :\n"+d);
                inspectSelectionOfChilds(d);
//        		logger.debug("après:\n"+d);
                purgeData(d);
            }
        }
    }
    
    protected boolean inspectSelectionOfChilds(DatabaseTreeDataFichier.Data d) {
        if (d.getChilds().size()==0) {
            return d.isSelected();
        } else {
            boolean hasAllChildsSelected = true;
            for (DatabaseTreeDataFichier.Data dd:d.getChilds()) {
                hasAllChildsSelected &= inspectSelectionOfChilds(dd);
            }
            d.setSelected(d.isSelected() || hasAllChildsSelected);
            return hasAllChildsSelected;
        }
    }
    
    protected void purgeData(DatabaseTreeDataFichier.Data datas) {
        // Si l'on veux supprimer ce niveau
        if (datas.isSelected()) {
            doSuppressData(datas);
        } else {
            for (DatabaseTreeDataFichier.Data d:datas.getChilds()) {
                purgeData(d);
            }
        }
    }
    
    public void doSuppressData(DatabaseTreeDataFichier.Data d) {
        Runnable process = null;
        // suppression selon le niveau
        switch (d.getLevel()) {
            case DatabaseTreeDataFichier.Data.LVL_DOC : {
                final DocumentModel dm = getDm().getDocumentById(d.getKey());
                logger.debug("deleting DOC : "+dm.getId());
                process = new Runnable() {
                    public void run() {
                        try {
                            getGlassPane().setVisible(true);
                            DataLayerManager.getImplementation().removeDocumentModel(dm);
                            getGlassPane().setVisible(false);
                        } catch(DataAccessException daEx) {
                            new DisplayExceptionDlg(DlgCleanDatabase.this,daEx);
                        } catch(DataConfigurationException dcEx) {
                            new DisplayExceptionDlg(DlgCleanDatabase.this,dcEx);
                        }
                    }
                };
                break;
            }
            case DatabaseTreeDataFichier.Data.LVL_COL : {
                StringTokenizer st = new StringTokenizer(d.getKey(), "|");
                final DocumentModel dm = getDm().getDocumentById(st.nextToken());
                final Pair collectivite = new Pair(st.nextToken(), "");
                logger.debug("deleting COL : "+dm.getId()+", "+collectivite.key);
                process = new Runnable() {
                    public void run() {
                        try {
                            getGlassPane().setVisible(true);
                            DataLayerManager.getImplementation().removeCollectivite(dm, collectivite);
                            getGlassPane().setVisible(false);
                        } catch(DataAccessException daEx) {
                            new DisplayExceptionDlg(DlgCleanDatabase.this,daEx);
                        } catch(DataConfigurationException dcEx) {
                            new DisplayExceptionDlg(DlgCleanDatabase.this,dcEx);
                        }
                    }
                };
                break;
            }
            case DatabaseTreeDataFichier.Data.LVL_BUD : {
                StringTokenizer st = new StringTokenizer(d.getKey(), "|");
                final DocumentModel dm = getDm().getDocumentById(st.nextToken());
                final Pair collectivite = new Pair(st.nextToken(), "");
                final Pair budget = new Pair(st.nextToken(), "");
                logger.debug("deleting BUD : "+dm.getId()+", "+collectivite.key+", "+budget.key);
                process = new Runnable() {
                    public void run() {
                        try {
                            getGlassPane().setVisible(true);
                            DataLayerManager.getImplementation().removeBudget(dm, collectivite, budget);
                            getGlassPane().setVisible(false);
                        } catch(DataAccessException daEx) {
                            new DisplayExceptionDlg(DlgCleanDatabase.this,daEx);
                        } catch(DataConfigurationException dcEx) {
                            new DisplayExceptionDlg(DlgCleanDatabase.this,dcEx);
                        }
                    }
                };
                break;
            }
            case DatabaseTreeDataFichier.Data.LVL_FIC : {
                StringTokenizer st = new StringTokenizer(d.getKey(), "|");
                final DocumentModel dm = getDm().getDocumentById(st.nextToken());
                final Pair collectivite = new Pair(st.nextToken(), "");
                final Pair budget = new Pair(st.nextToken(), "");
                final String fichier = st.nextToken();
                logger.debug("deleting FIC : "+dm.getId()+", "+collectivite.key+", "+budget.key+", "+fichier);
                process = new Runnable() {
                    public void run() {
                        try {
                            getGlassPane().setVisible(true);
                            DataLayerManager.getImplementation().removeFichier(dm, fichier);
                            getGlassPane().setVisible(false);
                        } catch(DataAccessException daEx) {
                            new DisplayExceptionDlg(DlgCleanDatabase.this,daEx);
                        } catch(DataConfigurationException dcEx) {
                            new DisplayExceptionDlg(DlgCleanDatabase.this,dcEx);
                        }
                    }
                };
                break;
            }
        }
        if(process!=null) {
            logger.debug("deleting");
            SwingWorker deleter = new Deleter(process,this);
            deleter.execute();
        }
    }
    
    /**
     * SUPPRESSION PAR DONNEES
     */
    
    /**
     * Netoie la base a partir du chemin specifie
     * @param tp Le chemin a nettoyer
     * @return <tt>true</tt> s'il faut rafraichir l'arbre
     */
    protected void purge(TreePath tp) {
        if(tp==null) return;
        DatabaseTreeDataDonnee.DataNode node = (DatabaseTreeDataDonnee.DataNode)tp.getLastPathComponent();
        if(JOptionPane.showConfirmDialog(this,"Etes-vous sur de vouloir supprimer les informations\nconcernant "+node+" définitivement ?\n\nCette opération peut prendre beaucoup de temps\nsi le nombre d'éléments à supprimer est important.","Suppression",JOptionPane.YES_NO_OPTION)==JOptionPane.YES_OPTION) {
            purge(node);
        }
    }
    /**
     * Nettoie la base a partir du noeud specifie
     * @param dn
     * @return <tt>true</tt> s'il faut rafraichir l'arbre
     */
    protected void purge(DatabaseTreeDataDonnee.DataNode dn) {
        int level = dn.getType();
        Runnable process = null;
        switch(level) {
            case DatabaseTreeDataDonnee.DataNode.TYPE_DOCUMENT: {
                final DocumentModel dm = (DocumentModel)dn.getData();
                process = new Runnable() {
                    public void run() {
                        try {
                            getGlassPane().setVisible(true);
                            DataLayerManager.getImplementation().removeDocumentModel(dm);
                            getGlassPane().setVisible(false);
                        } catch(DataAccessException daEx) {
                            new DisplayExceptionDlg(DlgCleanDatabase.this,daEx);
                        } catch(DataConfigurationException dcEx) {
                            new DisplayExceptionDlg(DlgCleanDatabase.this,dcEx);
                        }
                    }
                };
                break;
            }
            case DatabaseTreeDataDonnee.DataNode.TYPE_COLLECTIVITE: {
                final DocumentModel dm = (DocumentModel)(dn.getParent().getData());
                final Pair collectivite = (Pair)dn.getData();
                process = new Runnable() {
                    public void run() {
                        try {
                            getGlassPane().setVisible(true);
                            DataLayerManager.getImplementation().removeCollectivite(dm,collectivite);
                            getGlassPane().setVisible(false);
                        } catch(DataAccessException daEx) {
                            new DisplayExceptionDlg(DlgCleanDatabase.this,daEx);
                        } catch(DataConfigurationException dcEx) {
                            new DisplayExceptionDlg(DlgCleanDatabase.this,dcEx);
                        }
                    }
                };
                break;
            }
            case DatabaseTreeDataDonnee.DataNode.TYPE_BUDGET: {
                final Pair budget = (Pair)dn.getData();
                final Pair collectivite = (Pair)dn.getParent().getData();
                final DocumentModel dm = (DocumentModel)(dn.getParent().getParent().getData());
                process = new Runnable() {
                    public void run() {
                        try {
                            getGlassPane().setVisible(true);
                            DataLayerManager.getImplementation().removeBudget(dm,collectivite,budget);
                            getGlassPane().setVisible(false);
                        } catch(DataAccessException daEx) {
                            new DisplayExceptionDlg(DlgCleanDatabase.this,daEx);
                        } catch(DataConfigurationException dcEx) {
                            new DisplayExceptionDlg(DlgCleanDatabase.this,dcEx);
                        }
                    }
                };
                break;
            }
            case DatabaseTreeDataDonnee.DataNode.TYPE_PERSO1: {
                final Pair perso1 = (Pair)dn.getData();
                final Pair budget = (Pair)dn.getParent().getData();
                final Pair collectivite = (Pair)dn.getParent().getParent().getData();
                final DocumentModel dm = (DocumentModel)(dn.getParent().getParent().getParent().getData());
                process = new Runnable() {
                    public void run() {
                        try {
                            getGlassPane().setVisible(true);
                            DataLayerManager.getImplementation().removeSpecialKey1(dm,collectivite,budget,perso1);
                            getGlassPane().setVisible(false);
                        } catch(DataAccessException daEx) {
                            new DisplayExceptionDlg(DlgCleanDatabase.this,daEx);
                        } catch(DataConfigurationException dcEx) {
                            new DisplayExceptionDlg(DlgCleanDatabase.this,dcEx);
                        }
                    }
                };
                break;
            }
            case DatabaseTreeDataDonnee.DataNode.TYPE_PERSO2: {
                final Pair perso2 = (Pair)dn.getData();
                final Pair perso1 = (Pair)dn.getParent().getData();
                final Pair budget = (Pair)dn.getParent().getParent().getData();
                final Pair collectivite = (Pair)dn.getParent().getParent().getParent().getData();
                final DocumentModel dm = (DocumentModel)(dn.getParent().getParent().getParent().getParent().getData());
                process = new Runnable() {
                    public void run() {
                        try {
                            getGlassPane().setVisible(true);
                            DataLayerManager.getImplementation().removeSpecialKey2(dm,collectivite,budget,perso1,perso2);
                            getGlassPane().setVisible(false);
                        } catch(DataAccessException daEx) {
                            new DisplayExceptionDlg(DlgCleanDatabase.this,daEx);
                        } catch(DataConfigurationException dcEx) {
                            new DisplayExceptionDlg(DlgCleanDatabase.this,dcEx);
                        }
                    }
                };
                break;
            }
        }
        if(process!=null) {
            logger.debug("deleting");
            SwingWorker deleter = new Deleter(process,this);
            deleter.execute();
        }
    }
    
    private class Deleter extends SwingWorker {
        private Runnable process=null;
        private DlgCleanDatabase dlg=null;
        public Deleter(Runnable process,DlgCleanDatabase dlg) {
            super();
            this.process=process;
            this.dlg = dlg;
        }
        @Override
        public String doInBackground() {
            dlg.enableButtons(false);
            dlg.setCursor(Cursor.getPredefinedCursor(Cursor.WAIT_CURSOR));
            process.run();
            return null;
        }
        @Override
        public void done() {
            if (getJTabbedPane1().getSelectedComponent() instanceof PanelChooseDatabaseDonnees)
                ((PanelChooseDatabaseDonnees)dlg.getJTabbedPane1().getSelectedComponent()).getJTree1().setModel(new DatabaseTreeDataDonnee(getDm()));
            if (getJTabbedPane1().getSelectedComponent() instanceof PanelChooseDatabaseFichier)
                ((PanelChooseDatabaseFichier)dlg.getJTabbedPane1().getSelectedComponent()).refresh();
            dlg.setCursor(Cursor.getDefaultCursor());
            dlg.enableButtons(true);
        }
    }
}
