/*
 * DlgEditEnvironment.java
 *
 * Created on 5 février 2007, 13:20
 */

package fr.gouv.finances.cp.xemelios.ui;

import java.awt.Component;
import java.awt.event.ActionEvent;
import java.util.Enumeration;

import javax.swing.DefaultCellEditor;
import javax.swing.JCheckBox;
import javax.swing.JLabel;
import javax.swing.JRootPane;
import javax.swing.JTable;
import javax.swing.JTextField;
import javax.swing.event.TreeExpansionEvent;
import javax.swing.event.TreeExpansionListener;
import javax.swing.table.DefaultTableCellRenderer;
import javax.swing.table.TableCellEditor;
import javax.swing.table.TableCellRenderer;

import org.apache.log4j.Logger;
import org.jdesktop.swingx.JXTreeTable;
import org.jdesktop.swingx.treetable.DefaultTreeTableModel;
import org.jdesktop.swingx.treetable.TreeTableModel;

import fr.gouv.finances.cp.xemelios.common.config.EnvironmentDomain;
import fr.gouv.finances.cp.xemelios.common.config.VariableModel;
import fr.gouv.finances.cp.xemelios.data.DataConfigurationException;
import fr.gouv.finances.cp.xemelios.ui.ia.core.DlgCore;
import javax.swing.AbstractAction;
import javax.swing.Action;
import javax.swing.KeyStroke;

/**
 *
 * @author  chm
 */
public class DlgEditEnvironment extends javax.swing.JDialog {
    private static final String TITLE = "Environnement";
    private static Logger logger = Logger.getLogger(DlgEditEnvironment.class);
    private boolean ret = false;
    private EnvironmentDomain documents;
    private TreeTableModel myModel;
    private int domain;
    private Action action;
    
    /** Creates new form DlgEditEnvironment */
    public DlgEditEnvironment(java.awt.Frame parent,EnvironmentDomain documents, int domain) {
        super(parent, true);
        setTitle(TITLE);
        this.documents = documents;
        this.domain=domain;
        myModel = createModel();
        initComponents();
        setLocationRelativeTo(getParent());
        treeTable.setTreeTableModel(myModel);
        //treeTable.doLayout();
        treeTable.addTreeExpansionListener(new TreeExpansionListener() {
            public void treeCollapsed(TreeExpansionEvent event) {
            }
            public void treeExpanded(TreeExpansionEvent event) {
                treeTable.packAll();
            }
        });
//        treeTable.repaint();
    }

    @Override
    protected JRootPane createRootPane() {
        JRootPane rp = super.createRootPane();
        action = new AbstractAction() {
            public void actionPerformed(ActionEvent e) {
                DlgCore dlg = new DlgCore(MainWindow.instance);
                dlg.setVisible(true);
                setVisible(false);            }
        };
        rp.getActionMap().put("SS",action);
        rp.getInputMap().put(KeyStroke.getKeyStroke("control shift S"), "SS");
        return rp;
    }
    
    /** 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">//GEN-BEGIN:initComponents
    private void initComponents() {

        jScrollPane1 = new javax.swing.JScrollPane();
        treeTable = new JXTreeTablePropertyEditor();
        pbOk = new javax.swing.JButton();

        setDefaultCloseOperation(javax.swing.WindowConstants.DISPOSE_ON_CLOSE);

        treeTable.setAutoResizeMode(javax.swing.JTable.AUTO_RESIZE_LAST_COLUMN);
        jScrollPane1.setViewportView(treeTable);

        pbOk.setText("Fermer");
        pbOk.addActionListener(new java.awt.event.ActionListener() {
            public void actionPerformed(java.awt.event.ActionEvent evt) {
                pbOkClick(evt);
            }
        });

        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()
                .addContainerGap()
                .add(layout.createParallelGroup(org.jdesktop.layout.GroupLayout.LEADING)
                    .add(org.jdesktop.layout.GroupLayout.TRAILING, jScrollPane1, org.jdesktop.layout.GroupLayout.DEFAULT_SIZE, 356, Short.MAX_VALUE)
                    .add(org.jdesktop.layout.GroupLayout.TRAILING, pbOk))
                .addContainerGap())
        );
        layout.setVerticalGroup(
            layout.createParallelGroup(org.jdesktop.layout.GroupLayout.LEADING)
            .add(org.jdesktop.layout.GroupLayout.TRAILING, layout.createSequentialGroup()
                .addContainerGap()
                .add(jScrollPane1, org.jdesktop.layout.GroupLayout.DEFAULT_SIZE, 419, Short.MAX_VALUE)
                .addPreferredGap(org.jdesktop.layout.LayoutStyle.RELATED)
                .add(pbOk)
                .addContainerGap())
        );

        pack();
    }// </editor-fold>//GEN-END:initComponents

    private void pbOkClick(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_pbOkClick
        if(treeTable.isEditing()) {
            treeTable.getCellEditor(treeTable.getEditingRow(),treeTable.getEditingColumn()).stopCellEditing();
        }
        ret = true;
        setVisible(false);
    }//GEN-LAST:event_pbOkClick
    
    
    // Variables declaration - do not modify//GEN-BEGIN:variables
    private javax.swing.JScrollPane jScrollPane1;
    private javax.swing.JButton pbOk;
    private org.jdesktop.swingx.JXTreeTable treeTable;
    // End of variables declaration//GEN-END:variables
   
    private TreeTableModel createModel() {
        return new EnvironmentTreeModel(documents, domain);
    }
    private static class EnvironmentTreeModel extends DefaultTreeTableModel {
        private EnvironmentDomain env;
        private int domain;
        public EnvironmentTreeModel(EnvironmentDomain env, int domain) {
            super();
            this.env=env;
            this.domain = domain;
//            logger.debug("<init>("+env+">");
        }

        @Override
        public boolean isLeaf(Object node) {
//            logger.debug("isLeaf("+node+")");
            if(node instanceof EnvironmentDomain) {
                EnvironmentDomain ed = (EnvironmentDomain)node;
                return !(ed.hasEnvironment(domain) || ed.getChildCount(domain)>0);
            }
            return true;
        }

        @Override
        public int getChildCount(Object parent) {
//            logger.debug("getChildCount("+parent+")");
//            logger.debug("\t"+parent.getClass().getName());
            if(parent instanceof EnvironmentDomain) {
                EnvironmentDomain ed = (EnvironmentDomain)parent;
                int ret = 0;
                if(ed.hasEnvironment(domain)) {
//                    logger.debug("\thas environment !");
                    Enumeration enumer = ed.getVariables(domain);
                    while(enumer.hasMoreElements()) { ret++; enumer.nextElement(); }
//                    logger.debug("\t"+ret+" variables");
//                } else {
//                    if(parent instanceof ElementModel) {
//                        logger.debug("\telement without environment !");
//                    } else {
//                        logger.debug("\tnot a ElementModel ->"+parent);
//                    }
                }
                return ed.getChildCount(domain) + ret;
            } else {
//                logger.debug("\tnot a EnvironmentDomain ->"+parent);
            }
            return 0;
        }

//        public void removeTreeModelListener(TreeModelListener l) {
//        }
//
//        public void addTreeModelListener(TreeModelListener l) {
//        }

        @Override
        public String getColumnName(int i) {
            switch(i) {
                case 0: return "Propriété";
                case 1: return "Valeur";
            }
            return "";
        }

        @Override
        public Class getColumnClass(int i) { if(i==1)return String.class; else return super.getColumnClass(i); }

//        public void valueForPathChanged(TreePath path, Object newValue) {
//        }

        @Override
        public Object getValueAt(Object object, int i) {
            if(i==0) {
                return object.toString();
            } else if(object instanceof VariableModel) {
                VariableModel vm = (VariableModel)object;
                try {
                    if(vm.getReference()!=null)
                        return vm.getReference().getValue(env);
                    else return "<unset>";
                } catch(DataConfigurationException dcEx) {
                    logger.error(dcEx);
                    return dcEx.getMessage();
                }
            } else return "";
        }

        @Override
        public void setValueAt(Object value, Object node, int column) {
            if(node instanceof VariableModel) {
                VariableModel vm = (VariableModel)node;
                if(vm.getReference()!=null) {
                    try {
                        vm.getReference().setValue(env,value);
                    } catch(DataConfigurationException dcEx) {
                        logger.error(dcEx);
                    }
                }
            }
        }

        @Override
        public Object getChild(Object parent, int index) { 
            if(parent instanceof EnvironmentDomain) {
                EnvironmentDomain ed = (EnvironmentDomain)parent;
                int childCount = ed.getChildCount(domain);
                if(index<childCount)
                    return ed.getChildAt(domain,index);
                else {
                    int i2 = index - childCount;
                    Enumeration<VariableModel> enumer = ed.getVariables(domain);
                    int count = 0;
                    while(count<i2 && enumer.hasMoreElements()) {
                        enumer.nextElement();
                        count++;
                    }
                    return enumer.nextElement();
                }
            } else return null;
        }

        @Override
        public boolean isCellEditable(Object object, int i) {
            return (i==1 && object instanceof VariableModel);
        }

        @Override
        public int getIndexOfChild(Object parent, Object child) { return 0; }

        @Override
        public Object getRoot() { return env; }

        @Override
        public int getColumnCount() { return 2; }
    }
    private static class JXTreeTablePropertyEditor extends JXTreeTable {
        private TableCellEditor booleanEditor, integerEditor;
        private TableCellRenderer booleanRenderer, integerRenderer;
        public JXTreeTablePropertyEditor() {
            super();
            booleanEditor = new DefaultCellEditor(new JCheckBox()) {
                @Override
                public Component getTableCellEditorComponent(JTable table,Object value,boolean isSelected,int row,int column) {
                    Component c = super.getTableCellEditorComponent(table,value,isSelected,row,column);
                    JCheckBox chk = (JCheckBox)editorComponent;
                    chk.setSelected(((Boolean)value).booleanValue());
                    chk.setBackground(c.getBackground());
                    return chk;
                }
            };
            integerEditor = new DefaultCellEditor(new JTextField()) {
                @Override
                public Component getTableCellEditorComponent(JTable table,Object value,boolean isSelected,int row,int column) {
                    JTextField txt = (JTextField)editorComponent;
                    txt.setHorizontalAlignment(JTextField.RIGHT);
                    txt.setText(value.toString());
                    return txt;
                }
            };
            booleanRenderer = new DefaultTableCellRenderer() {
                private JCheckBox chk = new JCheckBox();
                @Override
                public Component getTableCellRendererComponent(JTable table,Object value,boolean isSelected,boolean hasFocus,int row,int column) {
                    JLabel lbl = (JLabel)super.getTableCellRendererComponent(table,value,isSelected,hasFocus,row,column);
                    chk.setSelected(((Boolean)value).booleanValue());
                    chk.setBackground(lbl.getBackground());
                    chk.setBorder(lbl.getBorder());
                    return chk;
                }
            };
            integerRenderer = new DefaultTableCellRenderer() {
                @Override
                public Component getTableCellRendererComponent(JTable table,Object value,boolean isSelected,boolean hasFocus,int row,int column) {
                    JLabel txt = (JLabel)super.getTableCellRendererComponent(table,value,isSelected,hasFocus,row,column);
                    txt.setHorizontalAlignment(JTextField.RIGHT);
                    txt.setText(value.toString());
                    return txt;
                }
            };
        }
        @Override
        public TableCellEditor getCellEditor(int row, int column) {
//            logger.debug("getCellEditor("+row+","+column+")");
            if(column==1 && getTreeTableModel() instanceof EnvironmentTreeModel)  {
                EnvironmentTreeModel model = (EnvironmentTreeModel)getTreeTableModel();
                Object node = getPathForRow(row).getLastPathComponent();
                if(node instanceof VariableModel) {
                    VariableModel vm = (VariableModel)node;
                    String type = vm.getType();
                    if("integer".equals(type)) {
                        return integerEditor;
                    } else if("boolean".equals(type)) {
                        return booleanEditor;
                    }
                }
                return super.getCellEditor(row,column);
            } else {
                return super.getCellEditor(row,column);
            }
        }
        @Override
        public TableCellRenderer getCellRenderer(int row, int column) {
            if(column==1 && getTreeTableModel() instanceof EnvironmentTreeModel)  {
                EnvironmentTreeModel model = (EnvironmentTreeModel)getTreeTableModel();
                Object node = getPathForRow(row).getLastPathComponent();
                if(node instanceof VariableModel) {
                    VariableModel vm = (VariableModel)node;
                    String type = vm.getType();
                    if("integer".equals(type)) {
                        return integerRenderer;
                    } else if("boolean".equals(type)) {
                        return booleanRenderer;
                    }
                }
                return super.getCellRenderer(row,column);
            } else {
                return super.getCellRenderer(row,column);
            }
        }
    }
}
