/*
 * 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.ui;

import java.awt.BorderLayout;
import java.awt.Cursor;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.KeyEvent;
import java.util.ArrayList;
import java.util.Vector;

import javax.swing.AbstractAction;
import javax.swing.Action;
import javax.swing.Box;
import javax.swing.JButton;
import javax.swing.JComponent;
import javax.swing.JDialog;
import javax.swing.JFrame;
import javax.swing.JOptionPane;
import javax.swing.JPanel;
import javax.swing.JRootPane;
import javax.swing.JScrollPane;
import javax.swing.JTextArea;
import javax.swing.JTree;
import javax.swing.KeyStroke;
import javax.swing.event.TreeModelListener;
import javax.swing.tree.TreeModel;
import javax.swing.tree.TreePath;
import javax.swing.tree.TreeSelectionModel;

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.cp.utils.Pair;
import fr.gouv.finances.cp.utils.ui.DisplayExceptionDlg;
import fr.gouv.finances.cp.utils.ui.InfiniteGlassPane;
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;

/**
 * This dialog box allows user to remove documents from data layer.
 * It shows a tree-structured view of database and allows user to select
 * a node and delete everything under this node.
 * @author chm
 * @since 2.0
 */
public class DlgCleanDatabaseOld extends JDialog {
    /**
     * Comment for <code>serialVersionUID</code>
     */
    private static final long serialVersionUID = 3256721779816151348L;
    private Action escapeAction;
    private DocumentsModel dm;
    private static Logger logger = Logger.getLogger(DlgCleanDatabaseOld.class);
    private JTree tree = null;
	private JButton pbClose=null, pbPurge=null;

    public DlgCleanDatabaseOld(JFrame parent,DocumentsModel dm) {
        super(parent);
        this.dm = dm;
        initComponents();
    }
    protected void initComponents() {
		int sepInfo = 2;						// 2
		int lineInfo = sepInfo + 2;				// 4
		int sepData = lineInfo + 2;				// 6
		int treeLine = sepData + 2;				// 8
		int buttonLine1 = treeLine + 2;			// 10
		
		JTextArea area = null;
		
		FormLayout fl = new FormLayout(
				//        1		2	  3	   4		
						"3dlu,20dlu,140dlu,3dlu",
				"7dlu,"+                                   // 1
				"pref,"+                                   // 2
				"3dlu,"+                                   // 3
				"pref,"+                                   // 4
				"7dlu,"+                                   // 5
				"pref,"+                                   // 6
				"3dlu,"+                                   // 7
				"140dlu,"+                                  // 8
				"7dlu,"+                                   // 9
				"pref,"+                                   // 10
				"7dlu");                                   // 11
		CellConstraints cc = new CellConstraints();
		PanelBuilder pb = new PanelBuilder(fl);
		tree = new JTree(new DatabaseTreeDataDonnee(dm));

		pb.addSeparator("Informations",					cc.xyw(2,sepInfo,2));
		pb.add(area = new JTextArea(), 					cc.xy(3,lineInfo));
		
		pb.addSeparator("Documents",						cc.xyw(2,sepData,2));
		pb.add(new JScrollPane(tree),								cc.xy(3,treeLine));

		pbPurge = new JButton("Supprimer");

		JPanel bPane = new JPanel(new BorderLayout());
		bPane.add(pbPurge,BorderLayout.WEST);
		bPane.add(Box.createHorizontalGlue(),BorderLayout.CENTER);
		bPane.add(pbClose = new JButton(escapeAction),BorderLayout.EAST);
		
        pb.add(bPane,									cc.xyw(2,buttonLine1,2));
        
		area.setEditable(false);
		area.setLineWrap(true);
		area.setRows(3);
		area.setBackground(getBackground());
		area.setText("Sélectionnez dans le graphique ci-dessous\nles éléments que vous souhaitez purger.");
		
		tree.setScrollsOnExpand(true);
		tree.setRootVisible(false);
                tree.getSelectionModel().setSelectionMode(TreeSelectionModel.SINGLE_TREE_SELECTION);
		
		getRootPane().setDefaultButton(pbClose);
        
        setContentPane(pb.getPanel());
        
        pbPurge.addActionListener(new ActionListener() {
            public void actionPerformed(ActionEvent evt) {
                purge(tree.getSelectionPath());
            }
        });
        
		pack();
		setLocationRelativeTo(getParent());
		setGlassPane(new InfiniteGlassPane());
        setVisible(true);
    }
    /**
     * 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(DlgCleanDatabaseOld.this,daEx);
                        } catch(DataConfigurationException dcEx) {
                            new DisplayExceptionDlg(DlgCleanDatabaseOld.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(DlgCleanDatabaseOld.this,daEx);
                        } catch(DataConfigurationException dcEx) {
                            new DisplayExceptionDlg(DlgCleanDatabaseOld.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(DlgCleanDatabaseOld.this,daEx);
                        } catch(DataConfigurationException dcEx) {
                            new DisplayExceptionDlg(DlgCleanDatabaseOld.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(DlgCleanDatabaseOld.this,daEx);
                        } catch(DataConfigurationException dcEx) {
                            new DisplayExceptionDlg(DlgCleanDatabaseOld.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(DlgCleanDatabaseOld.this,daEx);
                        } catch(DataConfigurationException dcEx) {
                            new DisplayExceptionDlg(DlgCleanDatabaseOld.this,dcEx);
                        }
                    }
                };
                break;
            }
	    }
	    if(process!=null) {
	        logger.debug("deleting");
	        SwingWorker deleter = new Deleter (process,this);
	        deleter.execute();
	    }
    }
    @Override
	protected JRootPane createRootPane() {
	    KeyStroke ks = KeyStroke.getKeyStroke(KeyEvent.VK_ESCAPE,0);
	    JRootPane rp = new JRootPane();
		escapeAction = new AbstractAction("Fermer") {
		    /**
             * Comment for <code>serialVersionUID</code>
             */
            private static final long serialVersionUID = 1L;

            public void actionPerformed(ActionEvent evt) {
		        setVisible(false);
		    }
		};
	    rp.registerKeyboardAction(escapeAction,"TOTOTOTO",ks,JComponent.WHEN_IN_FOCUSED_WINDOW);
	    return rp;
	}
	private void enableButtons(boolean activate) {
	    pbClose.setEnabled(activate);
	    pbPurge.setEnabled(activate);
	}
	
	private class Deleter extends SwingWorker {
        private Runnable process=null;
        private DlgCleanDatabaseOld dlg=null;
        public Deleter(Runnable process,DlgCleanDatabaseOld 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() {
            dlg.tree.setModel(new DatabaseTreeDataDonnee(dm));
            dlg.setCursor(Cursor.getDefaultCursor());
            dlg.enableButtons(true);
        }
	}
}
