
/*
* Copyright 2003-2010 Tufts University  Licensed under the
 * Educational Community License, Version 2.0 (the "License"); you may
 * not use this file except in compliance with the License. You may
 * obtain a copy of the License at
 * 
 * http://www.osedu.org/licenses/ECL-2.0
 * 
 * Unless required by applicable law or agreed to in writing,
 * software distributed under the License is distributed on an "AS IS"
 * BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express
 * or implied. See the License for the specific language governing
 * permissions and limitations under the License.
 */

package edu.tufts.vue.metadata.ui;

import java.awt.FlowLayout;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;

import javax.swing.BorderFactory;
import javax.swing.BoxLayout;
import javax.swing.DefaultCellEditor;
import javax.swing.JButton;
import javax.swing.JComboBox;
import javax.swing.JComponent;
import javax.swing.JDialog;
import javax.swing.JLabel;
import javax.swing.JPanel;
import javax.swing.JScrollPane;
import javax.swing.JTable;
import javax.swing.JTextField;
import javax.swing.SwingUtilities;
import javax.swing.table.AbstractTableModel;
import javax.swing.table.DefaultTableCellRenderer;

import tufts.vue.VueResources;
import tufts.vue.VueUtil;
import tufts.vue.gui.GUI;
import edu.tufts.vue.metadata.CategoryModel;
import edu.tufts.vue.ontology.OntType;
import edu.tufts.vue.ontology.Ontology;

//import tufts.vue.gui.DockWindow;

/*
 * CategoryEditor.java
 *
 * Created on August 17, 2007, 2:05 PM
 *
 * @author dhelle01
 */
public class CategoryEditor extends JPanel 
{
    private static final boolean DEBUG_LOCAL = false;
    
    // for best results: modify next two in tandem (at exchange rate of one pirxl from ROW_GAP for 
    // each two in ROW_HEIGHT in order to maintain proper text box height
    public final static int ROW_HEIGHT = 39;
    public final static int ROW_GAP = 7;
    
    public final static int ROW_INSET = 0;
    
    public final static int BUTTON_COL_WIDTH = 35;
    
    //private JTable metadataSetTable;
    private JTable customCategoryTable;
    
    //private JPanel setPanel;
    private JPanel customPanel;
    
    private JPanel buttonPanel;
    private JButton cancelButton;
    private JButton doneButton;
    
    private boolean newCategoryRequested;
    
    private JDialog dialog;
    
    public CategoryEditor(JDialog dialog,final JComboBox categories,
                          final MetadataEditor metadataEditor,
                          final tufts.vue.LWComponent current,
                          final int row,
                          final int col) 
    {
        this.dialog = dialog;
        setLayout(new BoxLayout(this,BoxLayout.Y_AXIS));
        //setPanel = new JPanel();
        //metadataSetTable = new JTable(new FullMetadataSetTableModel());
        //metadataSetTable.setDefaultRenderer(java.lang.Object.class,new SetTableRenderer());
        //metadataSetTable.setDefaultEditor(java.lang.Object.class,new SetTableEditor());
        //setPanel.add(metadataSetTable);
        customPanel = new JPanel(new java.awt.BorderLayout());
        customCategoryTable = new JTable(new MetadataCategoryTableModel());
        customCategoryTable.setOpaque(false);
        customCategoryTable.setDefaultRenderer(java.lang.Object.class,new CustomCategoryTableRenderer());
        customCategoryTable.setDefaultEditor(java.lang.Object.class,new CustomCategoryTableEditor());
        ((DefaultCellEditor)customCategoryTable.getDefaultEditor(java.lang.Object.class)).setClickCountToStart(1);
        customCategoryTable.getColumnModel().getColumn(0).setHeaderRenderer(new CustomCategoryTableHeaderRenderer());
        customCategoryTable.getColumnModel().getColumn(1).setHeaderRenderer(new CustomCategoryTableHeaderRenderer());
        int editorWidth = getWidth();
        customCategoryTable.getColumnModel().getColumn(0).setMinWidth(editorWidth-BUTTON_COL_WIDTH);
        customCategoryTable.getColumnModel().getColumn(1).setMaxWidth(BUTTON_COL_WIDTH); 
        
        customCategoryTable.setRowHeight(ROW_HEIGHT);
        customCategoryTable.getTableHeader().setReorderingAllowed(false);
        
        //metadataSetTable.setRowHeight(ROW_HEIGHT);
        //metadataSetTable.getTableHeader().setReorderingAllowed(false);

        customCategoryTable.setGridColor(new java.awt.Color(getBackground().getRed(),getBackground().getBlue(),getBackground().getGreen(),0));
        customCategoryTable.setBorder(BorderFactory.createEmptyBorder(5,5,5,5));
        customCategoryTable.setIntercellSpacing(new java.awt.Dimension(0,0));
        final JScrollPane scroll = new JScrollPane(customCategoryTable);
        scroll.setBackground(getBackground());
        scroll.setBorder(BorderFactory.createEmptyBorder(10,20,10,20));
        scroll.getViewport().setOpaque(false);

        customCategoryTable.getTableHeader().addMouseListener(new java.awt.event.MouseAdapter()
        {
                   public void mousePressed(java.awt.event.MouseEvent evt)
                   {
                       if(evt.getX()>customCategoryTable.getWidth()-BUTTON_COL_WIDTH)
                       {
                           
                         newCategoryRequested = true;
                         
                         /*if(customCategoryTable.getCellEditor() != null)
                         {
                             customCategoryTable.getCellEditor().stopCellEditing();
                             //scroll.requestFocus();
                             CategoryEditor.this.requestFocus(false);
                         }*/
                         
                         ((MetadataCategoryTableModel)customCategoryTable.getModel()).refresh();

                         SwingUtilities.invokeLater(new Runnable(){
                            public void run()
                            {
                              scroll.getVerticalScrollBar().setValue(scroll.getVerticalScrollBar().getMaximum());                              
                            }
                         });
                       }
                   }
                   
                   
                   public void mouseEntered(java.awt.event.MouseEvent e)
                   {
                       // todo -- use mouse moved to make it any move near the add button.. 
                       if((customCategoryTable.getCellEditor() != null)/* && (e.getX()>customCategoryTable.getWidth()-BUTTON_COL_WIDTH)*/) 
                       {
                          customCategoryTable.getCellEditor().stopCellEditing(); 
                       }
                   }
       });
       
       /*customCategoryTable.addMouseListener(new java.awt.event.MouseAdapter()
               {
                   public void mouseReleased(java.awt.event.MouseEvent evt)
                   {
                       if(evt.getX()>customCategoryTable.getWidth()-BUTTON_COL_WIDTH)
                       {
                         CategoryModel vueCategoryModel = tufts.vue.VUE.getCategoryModel();
                         java.util.List<OntType> ontTypes = vueCategoryModel.getCustomOntology().getOntTypes();
                         int selectedRow = customCategoryTable.getSelectedRow();
                         if(customCategoryTable.getSelectedColumn()== 1 && ontTypes.size() > selectedRow)
                         {
                            ontTypes.remove(selectedRow);
                            customCategoryTable.repaint();
                            requestFocusInWindow();
                            tufts.vue.VUE.getCategoryModel().saveCustomOntology();
                         }
                       }
                   }
        });*/ 


        
        //customPanel.setBorder(BorderFactory.createEmptyBorder(15,15,15,15));

        customPanel.add(scroll);
        //add(setPanel);
        // todo: add separator
        add(customPanel);

        //if(DEBUG_LOCAL)
        //{    
        //  System.out.println("scroll: " + scroll);
        //  System.out.println("categoryTable: " + customCategoryTable);
        //}
        
        buttonPanel = new JPanel(new FlowLayout(FlowLayout.RIGHT));
        buttonPanel.setBorder(BorderFactory.createEmptyBorder(0,0,5,15));
       // cancelButton = new JButton(VueResources.getString("button.cancel.lable"));
       // cancelButton.setFont(GUI.LabelFace);
        doneButton = new JButton(VueResources.getString("button.close.label"));
        doneButton.setFont(GUI.LabelFace);
        //buttonPanel.add(cancelButton);
        //buttonPanel.add(cancelButton);
        buttonPanel.add(doneButton);
        add(buttonPanel);
        
        
        
        doneButton.addActionListener(new java.awt.event.ActionListener() { public void actionPerformed(java.awt.event.ActionEvent e) {
                ((CategoryComboBoxModel)categories.getModel()).refreshCategoryMenu();
                CategoryEditor.this.dialog.dispose();
        }});
                //categories.setSelectedItem(categories.getSelectedItem());
                //int n = categories.getModel().getSize();
                // final String currentKey = metadataEditor.getKeyForRow(row);
                // if (currentKey != null) {
                //     MetadataEditor.selectKnownCategory(currentKey, categories);
                //     categories.repaint();
                // }
                // Object currObject = null;
                // tufts.vue.LWComponent currComponent = null;
                // if (metadataEditor.getCurrentMultiples() !=null )
                //     currComponent = metadataEditor.getCurrentMultiples();
                // else if(metadataEditor.getCurrent() !=null )
                //     currComponent = metadataEditor.getCurrent();
                // else { CategoryEditor.this.dialog.dispose(); return;  }
                // currObject = currComponent.getMetadataList().getMetadata().get(row).getObject();
                // Object currValue = (((String[])currObject)[0]);
    }
    
    class CustomCategoryTableHeaderRenderer extends DefaultTableCellRenderer
    {   
       public java.awt.Component getTableCellRendererComponent(JTable table, Object value,boolean isSelected,boolean hasFocus,int row,int col)
       {
           //setBorder(BorderFactory.createEmptyBorder(10,10,10,10));
           JComponent comp = new JPanel();
           if(col == 0)
           {    
               comp =  new JLabel(VueResources.getString("addcustomcategory.label"));
               comp.setFont(tufts.vue.gui.GUI.LabelFace);
           }
           else if(col == 1)
           {
               //comp = new JLabel();
               //((JLabel)comp).setIcon(tufts.vue.VueResources.getImageIcon("metadata.editor.add.up"));
                //comp.setBorder(BorderFactory.createEmptyBorder(5,0,0,0));
                JPanel holder = new JPanel();
                holder.add(new tufts.vue.gui.VueButton("keywords.button.add"));
                comp.add(holder);
           }
           else
           {
               comp = new JLabel("");
           }

           comp.setOpaque(true);
           comp.setBackground(CategoryEditor.this.getBackground());
           comp.setBorder(BorderFactory.createEmptyBorder(ROW_GAP,ROW_INSET,ROW_GAP,ROW_INSET));

           return comp;
       }
    }

    
    /*class SetTableRenderer extends DefaultTableCellRenderer
    {
        JPanel checkPanel = new JPanel();
        JCheckBox check = new JCheckBox();
        JLabel label = new JLabel();
        
        public java.awt.Component getTableCellRendererComponent(JTable table,Object value,boolean isSelected,
                                                                boolean hasFocus,int row,int col)
        {
            if(col == 0)
            {
                checkPanel.add(check);
                return checkPanel;
            }
            if(col == 1)
            {
                
                if(DEBUG_LOCAL)
                {    
                  System.out.println("CategoryEditor: " + value.getClass());
                }
                
                if(value instanceof Ontology)
                {
                    label.setText(((Ontology)value).getLabel());
                }

                return label;
            }
            
            label.setText("ERROR");
            return label;
        }
    } */
    
    
    /*class SetTableEditor extends DefaultCellEditor
    {
        JPanel checkPanel = new JPanel();
        JCheckBox check = new JCheckBox();
        JLabel label = new JLabel();
        
        public SetTableEditor()
        {
            super(new JTextField());
            //label = (JTextField)getComponent();
        }
        
        public java.awt.Component getTableCellEditorComponent(JTable table,Object value,boolean isSelected,
                                                                int row,int col)
        {
            if(col == 0)
            {
                checkPanel.add(check);
                return checkPanel;
            }
            if(col == 1)
            {
                
                if(DEBUG_LOCAL)
                {    
                  System.out.println("CategoryEditor: " + value.getClass());
                }
                
                if(value instanceof Ontology)
                {
                    label.setText(((Ontology)value).getLabel());
                }

                return label;
            }
            
            label.setText("ERROR");
            return label;
        }
    }*/
    
    class CustomCategoryTableRenderer extends DefaultTableCellRenderer
    {
        JPanel checkPanel = new JPanel();
        //JCheckBox check = new JCheckBox();
        JTextField label = new JTextField();
        tufts.vue.gui.VueButton deleteButton = new tufts.vue.gui.VueButton("keywords.button.delete");
        JPanel deletePanel = new JPanel();
        
        public CustomCategoryTableRenderer()
        {
            deletePanel.setBorder(BorderFactory.createEmptyBorder(5,1,0,0));
            deletePanel.add(deleteButton);
            label.setFont(tufts.vue.gui.GUI.LabelFace);
        }
        
        public java.awt.Component getTableCellRendererComponent(JTable table,Object value,boolean isSelected,
                                                                boolean hasFocus,int row,int col)
        {
            JPanel comp = new JPanel(new java.awt.BorderLayout());
            
            if(col == 1)
            {
               // JLabel button = new JLabel();
               // button.setIcon(tufts.vue.VueResources.getImageIcon("metadata.editor.delete.up"));
               // comp.add(button);
                
                //return checkPanel;
                
                /*if(DEBUG_LOCAL)
                {
                    System.out.println("CE: in table renderer -- showing delete button: " + row);
                }*/
                
                return deletePanel;
            }
            if(col == 0)
            {
                //label.setBorder(BorderFactory.createEmptyBorder(ROW_GAP,ROW_INSET,ROW_GAP,ROW_INSET));
                
                //if(DEBUG_LOCAL)
                //{    
                //  System.out.println("CategoryEditor: " + value.getClass() + " row: " + row + " col: " + col);
                //}
                
                if(value instanceof OntType)
                {
                    label.setText(((OntType)value).getLabel());
                    //if(DEBUG_LOCAL)
                    //{    
                    //  System.out.println("Label text in category component: " + label.getText());
                    //}
                }
                    
                else
                {
                  label.setText(value.toString());
                }
                comp.add(label);
                //return label;
            }
            
            comp.setBorder(BorderFactory.createEmptyBorder(ROW_GAP,ROW_INSET,ROW_GAP,ROW_INSET));
            //label.setText("ERROR");
            return comp;
        }
    }
    
    
    class CustomCategoryTableEditor extends DefaultCellEditor
    {
        //JPanel checkPanel = new JPanel();
        //JPanel deletePanel = new JPanel();
        //JCheckBox check = new JCheckBox();
        JTextField label = new JTextField();
        
        //private int row;
        //private int col;
        
        public CustomCategoryTableEditor()
        {
            super(new JTextField());
            label.setFont(GUI.LabelFace);
            label = (JTextField)getComponent();
            
            /*label.addFocusListener(new java.awt.event.FocusAdapter(){
                   public void focusLost(java.awt.event.FocusEvent fe)
                   {
                       if( (row == customCategoryTable.getModel().getRowCount() - 1) && newCategoryRequested )
                       {
                           CategoryModel cats = tufts.vue.VUE.getCategoryModel();
                           cats.addCustomCategory(label.getText());
                           
                           ((MetadataCategoryTableModel)customCategoryTable.getModel()).refresh();
                           
                           cats.saveCustomOntology();
                           
                           newCategoryRequested = false;
                       }
                       else
                       {
                           CategoryModel cats = tufts.vue.VUE.getCategoryModel();
                           cats.addCustomCategory(label.getText(),cats.getCustomOntology().getOntTypes().get(row));
                           
                           ((MetadataCategoryTableModel)customCategoryTable.getModel()).refresh();
                           
                           cats.saveCustomOntology(); 
                       }
                   }
                }); */
        }
        
        public java.awt.Component getTableCellEditorComponent(final JTable table,Object value,boolean isSelected,
                                                                final int row,int col)
        {
            JPanel comp = new JPanel(new java.awt.BorderLayout());
            
            if(col == 1)
            {
                //if(DEBUG_LOCAL)
                //{
                //  System.out.println("CE - creating delete button editor " + row);    
                //}
                
                //checkPanel.add(check);
                //comp.add(check);
                //return checkPanel;
                JPanel deletePanel = new JPanel();
                deletePanel.setBorder(BorderFactory.createEmptyBorder(5,1,0,0));
                tufts.vue.gui.VueButton deleteButton = new tufts.vue.gui.VueButton("keywords.button.delete");
                
                       
                deleteButton.addMouseListener(new java.awt.event.MouseAdapter()
                {
                   public void mouseReleased(java.awt.event.MouseEvent evt)
                   {
                       //if(evt.getX()>customCategoryTable.getWidth()-BUTTON_COL_WIDTH)
                       //{
                         CategoryModel vueCategoryModel = tufts.vue.VUE.getCategoryModel();
                         java.util.List<OntType> ontTypes = vueCategoryModel.getCustomOntology().getOntTypes();
                         //int selectedRow = customCategoryTable.getSelectedRow();
                         //if(customCategoryTable.getSelectedColumn()== 1 && ontTypes.size() > selectedRow)
                         //{
                            if(ontTypes.size() > row)
                              ontTypes.remove(row);
                            //customCategoryTable.repaint();
                            //requestFocusInWindow();
                            tufts.vue.VUE.getCategoryModel().saveCustomOntology();
                            
                            ((MetadataCategoryTableModel)customCategoryTable.getModel()).refresh();
                            customCategoryTable.repaint();
                            requestFocusInWindow();
                         //}
                       //}
                   }
                }); 
                
                deletePanel.add(deleteButton);
                return deletePanel;
            }
            if(col == 0)
            {
                final JTextField label = new JTextField();
                label.setFont(GUI.LabelFace);
                //this.row = row;
                //this.col = col;
                
                //if(DEBUG_LOCAL)
                //{    
                //  System.out.println("CategoryEditor: " + value.getClass());
                //}
                if(value instanceof OntType)
                {
                    label.setText(((OntType)value).getLabel());
                }
                
                /*label.addMouseListener(new java.awt.event.MouseAdapter() {
                    public void mouseExited(java.awt.event.MouseEvent e)
                    {
                       if(customCategoryTable.getCellEditor() != null) 
                       {
                          customCategoryTable.getCellEditor().stopCellEditing(); 
                       }
                    }
                });*/
                
                label.addFocusListener(new java.awt.event.FocusAdapter(){
                   public void focusLost(java.awt.event.FocusEvent fe)
                   {
                       if(DEBUG_LOCAL)
                       {
                         System.out.println("CE: label focus lost -- " + row);    
                       }
                       
                       if( (row == table.getModel().getRowCount() - 1) && newCategoryRequested )
                       {
                           CategoryModel cats = tufts.vue.VUE.getCategoryModel();
                           cats.addCustomCategory(label.getText());
                           
                           ((MetadataCategoryTableModel)customCategoryTable.getModel()).refresh();
                           
                           cats.saveCustomOntology();
                           
                           newCategoryRequested = false;
                       }
                       else
                       {
                           CategoryModel cats = tufts.vue.VUE.getCategoryModel();
                           cats.addCustomCategory(label.getText(),cats.getCustomOntology().getOntTypes().get(row));
                           
                           ((MetadataCategoryTableModel)customCategoryTable.getModel()).refresh();
                           
                           cats.saveCustomOntology(); 
                       }
                   }
                });

                comp.add(label);
                //return label;
            }

            comp.setBorder(BorderFactory.createEmptyBorder(ROW_GAP,ROW_INSET,ROW_GAP,ROW_INSET));
            return comp;
            //label.setText("ERROR");
            //return label;
        }
    }
    
    /*class FullMetadataSetTableModel extends AbstractTableModel
    {
        List<Boolean> selections = new ArrayList<Boolean>();
        private CategoryModel vueCategoryModel = tufts.vue.VUE.getCategoryModel();
        
        public int getRowCount()
        {
            return vueCategoryModel.size();
        }
        
        
         
        //  first column contains checkbox that will remove or add ontologies
        //  second column contains ontology names   
        public int getColumnCount()
        {
            return 2;
        }
        
        public Object getValueAt(int row,int col)
        {
            if(col == 1)
            {
              return vueCategoryModel.get(row);
            }
            else
            //if(col == 0)
            {
              //return selections.get(row);
              return Boolean.TRUE;
            }

        }
    }*/
    
    class MetadataCategoryTableModel extends AbstractTableModel
    {
        
        private CategoryModel vueCategoryModel = tufts.vue.VUE.getCategoryModel();
        
        /**
         *
         * column 1: category, which is an OntType and will appear
         * as a simple string
         *
         * column 2: remove button (should change CategoryModel)
         *
         **/
        public int getColumnCount()
        {
            return 2;
        }
        
        public boolean isCellEditable(int row,int col)
        {
            return true;
            /*if(col == 0)
                return true;
            else
                return false; */
        }
        
        public int getRowCount()
        {          
            Ontology customOntology = vueCategoryModel.getCustomOntology();
            
            if(customOntology == null || vueCategoryModel.getCustomOntology().getOntTypes().size() ==0)
            {
                newCategoryRequested = true;
                return 1;
            }
            

            if(/*(customOntology !=null) &&*/ !newCategoryRequested)
              return vueCategoryModel.getCustomOntology().getOntTypes().size();
            else if(customOntology != null)
              return vueCategoryModel.getCustomOntology().getOntTypes().size() + 1;
            else
              return 0;
            // vueCategoryModel.getCustomCategories.getSize();
        }
        
        public Object getValueAt(int row,int col)
        {
            if(col == 0 && vueCategoryModel.getCustomOntology() == null)
            {
                return "";
            }
            if(col == 0 && row < vueCategoryModel.getCustomOntology().getOntTypes().size())
            {
              OntType category = vueCategoryModel.getCustomOntology().getOntTypes().get(row);
              return category;
            }
            else
            if(col == 0 && row == vueCategoryModel.getCustomOntology().getOntTypes().size())
            {
                return "";
            }
            else
            //if(row == 1)
            {
              return "remove";
            }
        }

        public void refresh()
        {
           fireTableDataChanged();
        }
    }
    
}
