/*
 * BeanInspectorPanel.java
 *
 * Created on June 19, 2006, 2:57 PM
 */

package it.businesslogic.ireport.data;

import it.businesslogic.ireport.JRField;
import it.businesslogic.ireport.ReportClassLoader;
import it.businesslogic.ireport.gui.JBTreeCellRenderer;
import it.businesslogic.ireport.gui.MainFrame;
import it.businesslogic.ireport.gui.TreeJRField;
import it.businesslogic.ireport.util.Misc;
import java.util.List;
import java.util.Vector;
import javax.swing.JTable;
import javax.swing.table.DefaultTableModel;
import javax.swing.tree.DefaultMutableTreeNode;
import javax.swing.tree.DefaultTreeModel;
import javax.swing.tree.TreePath;

/**
 *
 * @author  gtoffoli
 */
public class BeanInspectorPanel extends javax.swing.JPanel {
    
    private boolean pathOnDescription = false;
    private JTable jTableFields = null; 
    private boolean comboVisible = true;
    
    
    /** Creates new form BeanInspectorPanel */
    public BeanInspectorPanel() {
        initComponents();
        
        DefaultTreeModel dttm = (DefaultTreeModel)jTree1.getModel();
        DefaultMutableTreeNode root = new DefaultMutableTreeNode();
        jTree1.setModel(new DefaultTreeModel( root ));
        
        jTree1.setCellRenderer( new JBTreeCellRenderer());
    }
    
    
    public void setClassNames(List classNames)
    {
        if (classNames == null) return;
        
        jComboBox1.removeAllItems();
        for (int i=0; i<classNames.size(); ++i)
        {
            jComboBox1.addItem( classNames.get(i));
        }
        
        jComboBox1ActionPerformed(null);
    }
    
    /**
     * Must be used when the combobox is not visible...
     */
    public void setClassName(String className)
    {
        DefaultMutableTreeNode root = (DefaultMutableTreeNode)jTree1.getModel().getRoot();
        root.removeAllChildren();
        jTree1.updateUI();
        if (className != null && className.trim().length() > 0)
        {
            exploreBean( root,className, "");
        }
    }
    
    /** 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() {
        java.awt.GridBagConstraints gridBagConstraints;

        jPanel1 = new javax.swing.JPanel();
        jLabel1 = new javax.swing.JLabel();
        jComboBox1 = new javax.swing.JComboBox();
        jScrollPane1 = new javax.swing.JScrollPane();
        jTree1 = new javax.swing.JTree();
        jPanel2 = new javax.swing.JPanel();
        jButton2 = new javax.swing.JButton();
        jButton3 = new javax.swing.JButton();

        setLayout(new java.awt.GridBagLayout());

        jPanel1.setLayout(new java.awt.GridBagLayout());

        jLabel1.setText("Bean");
        gridBagConstraints = new java.awt.GridBagConstraints();
        gridBagConstraints.insets = new java.awt.Insets(4, 4, 4, 4);
        jPanel1.add(jLabel1, gridBagConstraints);

        jComboBox1.setMinimumSize(new java.awt.Dimension(51, 22));
        jComboBox1.addActionListener(new java.awt.event.ActionListener() {
            public void actionPerformed(java.awt.event.ActionEvent evt) {
                jComboBox1ActionPerformed(evt);
            }
        });

        gridBagConstraints = new java.awt.GridBagConstraints();
        gridBagConstraints.fill = java.awt.GridBagConstraints.HORIZONTAL;
        gridBagConstraints.weightx = 1.0;
        gridBagConstraints.insets = new java.awt.Insets(4, 0, 4, 0);
        jPanel1.add(jComboBox1, gridBagConstraints);

        gridBagConstraints = new java.awt.GridBagConstraints();
        gridBagConstraints.gridx = 0;
        gridBagConstraints.fill = java.awt.GridBagConstraints.HORIZONTAL;
        gridBagConstraints.weightx = 1.0;
        add(jPanel1, gridBagConstraints);

        jTree1.setRootVisible(false);
        jTree1.addMouseListener(new java.awt.event.MouseAdapter() {
            public void mouseClicked(java.awt.event.MouseEvent evt) {
                jTree1MouseClicked1(evt);
            }
        });

        jScrollPane1.setViewportView(jTree1);

        gridBagConstraints = new java.awt.GridBagConstraints();
        gridBagConstraints.gridx = 0;
        gridBagConstraints.gridwidth = 3;
        gridBagConstraints.fill = java.awt.GridBagConstraints.BOTH;
        gridBagConstraints.weightx = 1.0;
        gridBagConstraints.weighty = 1.0;
        gridBagConstraints.insets = new java.awt.Insets(0, 4, 0, 0);
        add(jScrollPane1, gridBagConstraints);

        jPanel2.setLayout(new java.awt.GridBagLayout());

        jButton2.setText("Add selected field(s)");
        jButton2.addActionListener(new java.awt.event.ActionListener() {
            public void actionPerformed(java.awt.event.ActionEvent evt) {
                jButton2ActionPerformed(evt);
            }
        });

        gridBagConstraints = new java.awt.GridBagConstraints();
        gridBagConstraints.anchor = java.awt.GridBagConstraints.NORTHEAST;
        gridBagConstraints.weightx = 1.0;
        gridBagConstraints.insets = new java.awt.Insets(2, 0, 2, 4);
        jPanel2.add(jButton2, gridBagConstraints);

        jButton3.setText("Clear fields list");
        jButton3.addActionListener(new java.awt.event.ActionListener() {
            public void actionPerformed(java.awt.event.ActionEvent evt) {
                jButton2ActionPerformed1(evt);
            }
        });

        gridBagConstraints = new java.awt.GridBagConstraints();
        gridBagConstraints.anchor = java.awt.GridBagConstraints.NORTHEAST;
        gridBagConstraints.insets = new java.awt.Insets(2, 0, 2, 0);
        jPanel2.add(jButton3, gridBagConstraints);

        gridBagConstraints = new java.awt.GridBagConstraints();
        gridBagConstraints.gridx = 0;
        gridBagConstraints.fill = java.awt.GridBagConstraints.HORIZONTAL;
        gridBagConstraints.weightx = 1.0;
        gridBagConstraints.insets = new java.awt.Insets(0, 4, 0, 0);
        add(jPanel2, gridBagConstraints);

    }// </editor-fold>//GEN-END:initComponents

    private void jButton2ActionPerformed1(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_jButton2ActionPerformed1

        DefaultTableModel dtm = (DefaultTableModel)getJTableFields().getModel();
        dtm.setRowCount(0);
        
    }//GEN-LAST:event_jButton2ActionPerformed1

    private void jButton2ActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_jButton2ActionPerformed

        
        // Get all selected paths...
        if (MainFrame.getMainInstance().getActiveReportFrame() == null || getJTableFields() == null){
            return;
        }
        
        DefaultTableModel dtm = (DefaultTableModel)getJTableFields().getModel();
         
        TreePath[] paths = jTree1.getSelectionPaths();
        
        for (int i=0; i<paths.length; ++i)
        {
            boolean valid = true;
            TreePath tp = paths[i];

            TreeJRField tjrf =  (TreeJRField)((DefaultMutableTreeNode)tp.getLastPathComponent()).getUserObject();
            String returnType =  Misc.getJRFieldType( tjrf.getObj().getName() );
            it.businesslogic.ireport.JRField field = new it.businesslogic.ireport.JRField(tjrf.getField().getName(), returnType);
            field.setDescription(tjrf.getField().getDescription() );
            Vector row = new Vector();
            row.addElement(field);
            row.addElement(field.getClassType());
            row.addElement(field.getDescription());
            
            if (isComboVisible() && jComboBox1.getSelectedItem() instanceof FieldClassWrapper)
            {
                FieldClassWrapper cw = (FieldClassWrapper)jComboBox1.getSelectedItem();
                field.setName( cw.getFieldName() + "." + field.getDescription()   );
                field.setDescription( field.getName() );
            }

            // Check for duplicates fields...
            boolean found = fieldAlreadyExists(field);
            String baseName = field.getName();
            for (int j=1; isPathOnDescription() && found; ++j)
            {
                    field.setName(  baseName + "_" + j);
                    found = fieldAlreadyExists(field);
            }
            
            if (!found)
            {
                dtm.addRow(row);
                getJTableFields().getSelectionModel().addSelectionInterval( getJTableFields().getRowCount()-1, getJTableFields().getRowCount()-1 );
            }
        }
    }//GEN-LAST:event_jButton2ActionPerformed

    private void jComboBox1ActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_jComboBox1ActionPerformed

        Object obj = jComboBox1.getSelectedItem();
        if (obj == null) return;
        if (obj instanceof String) setClassName( (String)obj );
        if (obj instanceof FieldClassWrapper) setClassName( ((FieldClassWrapper)obj).getClassType());
            
    }//GEN-LAST:event_jComboBox1ActionPerformed

    
    private boolean fieldAlreadyExists(JRField field)
    {
        boolean found = false;
            for (int j=0; j<getJTableFields().getRowCount(); ++j)
            {
               Object ff = getJTableFields().getValueAt(j, 0);
               if ( ff instanceof it.businesslogic.ireport.JRField )
               {
                   if ( ((it.businesslogic.ireport.JRField)ff).getName().equals(field.getName()))
                   {
                       found = true;
                       break;
                   }
               }
            }
        
        return found;
    }
    
    private void jTree1MouseClicked1(java.awt.event.MouseEvent evt) {//GEN-FIRST:event_jTree1MouseClicked1

        
         if (evt.getClickCount() == 2 && evt.getButton() == evt.BUTTON1)
        {
            DefaultMutableTreeNode tn = (DefaultMutableTreeNode)jTree1.getSelectionPath().getLastPathComponent();
            
            if (tn.getChildCount()>0) return;
            
                /*if (!jTree1.isCollapsed( jTree1.getSelectionPath() ))
            {
                jTree1.collapsePath( jTree1.getSelectionPath() );
                return;
            }
                 *
                 */
            if (tn.getUserObject() instanceof TreeJRField)
            {
                TreeJRField jrf = (TreeJRField)tn.getUserObject();
                if (!jrf.getObj().isPrimitive() && !jrf.getObj().getName().startsWith("java.lang."))
                {
                   exploreBean(tn, jrf.getObj().getName(), 
                           isPathOnDescription() ?
                            Misc.nvl(  jrf.getField().getDescription() , "") :
                            Misc.nvl(  jrf.getField().getName() , "")   );
                }
            }
        }       
         
    }//GEN-LAST:event_jTree1MouseClicked1
    
    
    public void exploreBean(DefaultMutableTreeNode root, String classname, String parentPath)
    {
        try {
            
            root.removeAllChildren();
            if (parentPath.length() > 0) parentPath += ".";
            
            ReportClassLoader reportClassLoader = new ReportClassLoader();
            reportClassLoader.rescanLibDirectory();
            Class clazz = Class.forName(classname,true,reportClassLoader);
            
            java.beans.PropertyDescriptor[] pd = org.apache.commons.beanutils.PropertyUtils.getPropertyDescriptors(clazz);
            for (int nd =0; nd < pd.length; ++nd)
            {
                   String fieldName = pd[nd].getName();
                   if (pd[nd].getPropertyType() != null && pd[nd].getReadMethod() != null)
                   {
                       String returnType =  pd[nd].getPropertyType().getName();
                       it.businesslogic.ireport.JRField field = new it.businesslogic.ireport.JRField( Misc.getJRFieldType( fieldName ), returnType);
                       if (isPathOnDescription())
                       {
                            field.setDescription(parentPath + fieldName);
                       }
                       else
                       {
                           field.setName(parentPath + fieldName);
                       }
                       
                       TreeJRField jtf = new TreeJRField();
                   
                       jtf.setField( field );
                       jtf.setObj( pd[nd].getPropertyType() );
                   
                       boolean bChildrens = true;
                       if (pd[nd].getPropertyType().isPrimitive() || pd[nd].getPropertyType().getName().startsWith("java.lang."))
                       {
                           bChildrens = false;
                       }
                       root.add(new DefaultMutableTreeNode(jtf, bChildrens));
                   }
            }
            
            jTree1.expandPath( new TreePath(root.getPath()) );
            jTree1.updateUI();
            
        } catch (ClassNotFoundException cnf)
        {
            javax.swing.JOptionPane.showMessageDialog(this, "Class not found!\nCheck your classpath and retry.\n" + cnf.getMessage(),"Error",javax.swing.JOptionPane.ERROR_MESSAGE);
            return;
        } catch (Exception ex)
        {
            javax.swing.JOptionPane.showMessageDialog(this, ex.getMessage() ,"Error",javax.swing.JOptionPane.ERROR_MESSAGE);
            return;
        }
    }

    public JTable getJTableFields() {
        return jTableFields;
    }

    public void setJTableFields(JTable jTableFields) {
        this.jTableFields = jTableFields;
    }

    public boolean isComboVisible() {
        return comboVisible;
    }

    public void setComboVisible(boolean comboVisible) {
        this.comboVisible = comboVisible;
        jPanel1.setVisible( comboVisible );
    }

    public boolean isPathOnDescription() {
        return pathOnDescription;
    }

    public void setPathOnDescription(boolean pathOnDescription) {
        this.pathOnDescription = pathOnDescription;
    }
    
    // Variables declaration - do not modify//GEN-BEGIN:variables
    private javax.swing.JButton jButton2;
    private javax.swing.JButton jButton3;
    private javax.swing.JComboBox jComboBox1;
    private javax.swing.JLabel jLabel1;
    private javax.swing.JPanel jPanel1;
    private javax.swing.JPanel jPanel2;
    private javax.swing.JScrollPane jScrollPane1;
    private javax.swing.JTree jTree1;
    // End of variables declaration//GEN-END:variables
    
    
    
    
}
