package net.sourceforge.ganttproject;

import java.awt.Component;
import java.awt.Dimension;
import java.awt.event.ActionEvent;
import java.awt.event.FocusAdapter;
import java.awt.event.FocusEvent;
import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;
import java.text.MessageFormat;
import java.util.ArrayList;
import java.util.Collections;
import java.util.Comparator;
import java.util.List;

import javax.swing.Action;
import javax.swing.DefaultCellEditor;
import javax.swing.InputMap;
import javax.swing.JTable;
import javax.swing.JTextField;
import javax.swing.KeyStroke;
import javax.swing.SwingUtilities;
import javax.swing.event.TableColumnModelListener;
import javax.swing.table.TableColumn;
import javax.swing.table.TableColumnModel;
import javax.swing.tree.TreePath;

import net.sourceforge.ganttproject.action.GPAction;
import net.sourceforge.ganttproject.gui.GanttDialogCustomColumn;
import net.sourceforge.ganttproject.gui.TableHeaderUIFacade;
import net.sourceforge.ganttproject.gui.UIFacade;
import net.sourceforge.ganttproject.language.GanttLanguage;
import net.sourceforge.ganttproject.task.CustomPropertyEvent;
import net.sourceforge.ganttproject.task.CustomColumn;
import net.sourceforge.ganttproject.task.Task;

import org.jdesktop.swingx.table.TableColumnExt;
import org.jdesktop.swingx.table.TableColumnModelExt;

/**
 * Treetable used to displayed tabular data and hierarchical data.
 * 
 * @author bbaranne
 * @version 1.0 (20050301) (yyyymmdd)
 */
public class GanttTreeTable extends GPTreeTableBase implements GanttLanguage.Listener, CustomPropertyListener {
    /**
     * model of the treetable.
     */
    private final GanttTreeTableModel ttModel;

    private TableColumnExt myColType;

    private TableColumnExt myColPriority;

    private TableColumnExt myColNotes;

    private TableColumnExt myColName;

    private TableColumnExt myColBegDate;

    private TableColumnExt myColEndDate;

    private TableColumnExt myColDuration;

    private TableColumnExt myColCompletion;

    private TableColumnExt myColCoordinator;

    private TableColumnExt myColPredecessors;

    private TableColumnExt myColID;

    private TableColumnExt myColAssignments;

    private TableColumnExt myColLineNumber;

    /**
     * Creates an instance of GanttTreeTable with the given TreeTableModel.
     * 
     * @param model
     *            TreeTableModel.
     */
    public GanttTreeTable(IGanttProject project, UIFacade uifacade, GanttTreeTableModel model, CustomPropertyManager customPropertyManager) {
        super(project, uifacade, model, customPropertyManager);
        GanttLanguage.getInstance().addListener(this);
        this.ttModel = model;
        initTreeTable();
        createDefaultColumns();
    }

    /**
     * Creates tooltips for gantt table with tasks
     */
    public String getToolTipText(MouseEvent e) {
        String tip = null;
        TreePath selectionPath = getPathForLocation(e.getX(), e.getY());
        if (selectionPath != null) {
            Object selectedTaskNode = selectionPath.getLastPathComponent();
            /* Use appropriate column from model */
            int columnAtModel = convertColumnIndexToModel(columnAtPoint(e.getPoint()));
            /* Get strings for tooltip from model - task values for different columns */
            String toolTip = ttModel.getToolTipAt(selectedTaskNode, columnAtModel);
            /* Show tooltip when column not empty */
            if (toolTip != null && !toolTip.trim().equals("")) {
                tip = "<html><b>"+ttModel.getColumnName(columnAtModel)+" :</b> " + toolTip + "</html>"; 
            }
        }
        return tip;
    }

    protected void createDefaultColumns() {
        myColName = newTableColumnExt(0);
        myColName.setPreferredWidth(120);
        myColName.setIdentifier("tpd3");
        addColumn(myColName);
        myColName.setVisible(true);
        
        myColBegDate = newTableColumnExt(4);
        myColBegDate.setCellRenderer(newDateCellRenderer());
        myColBegDate.setIdentifier("tpd4");
        addColumn(myColBegDate);
        myColBegDate.setVisible(true);
        
        myColEndDate = newTableColumnExt(5);
        myColEndDate.setCellRenderer(newDateCellRenderer());
        myColEndDate.setIdentifier("tpd5");
        addColumn(myColEndDate);
        myColEndDate.setVisible(true);
        
        myColType = newTableColumnExt(1);
        addColumn(myColType);
        myColType.setVisible(false);
        
        myColPriority = newTableColumnExt(2);
        addColumn(myColPriority);
        myColPriority.setVisible(false);
        
        myColNotes = newTableColumnExt(3);
        addColumn(myColNotes);
        myColNotes.setVisible(false);
        
        myColDuration = newTableColumnExt(6);
        addColumn(myColDuration);
        myColDuration.setVisible(false);
        
        myColCompletion = newTableColumnExt(7);
        addColumn(myColCompletion);
        myColCompletion.setVisible(false);
        
        myColCoordinator = newTableColumnExt(8);
        addColumn(myColCoordinator);
        myColCoordinator.setVisible(false);
        
        myColPredecessors = newTableColumnExt(9);
        addColumn(myColPredecessors);
        myColPredecessors.setVisible(false);
        
        myColID = newTableColumnExt(10);
        addColumn(myColID);
        myColID.setVisible(false);
        
        myColAssignments = newTableColumnExt(11);
        addColumn(myColAssignments);
        myColAssignments.setVisible(false);
        
        myColLineNumber = newTableColumnExt(12);
        addColumn(myColLineNumber);
        myColLineNumber.setVisible(false);
        
        Runnable t = new Runnable() {
            public void run() {
                calculateWidth();
                revalidate();
            }
        };
        SwingUtilities.invokeLater(t);
    }

    protected void initTreeTable() {
        super.initTreeTable();
        getTable().getColumnModel().addColumnModelListener((TableColumnModelListener)getTreeTableModel());
        
    }

    protected void addNewCustomColumn(CustomPropertyDefinition customPropertyDefinition) {
        super.addNewCustomColumn(customPropertyDefinition);
        GanttTreeTableModel treeTableModel = (GanttTreeTableModel) getTreeTableModel();
        treeTableModel.addCustomColumn(customPropertyDefinition.getName());
    }

    protected void deleteCustomColumn(CustomPropertyDefinition customPropertyDefinition) {
        super.deleteCustomColumn(customPropertyDefinition);
        GanttTreeTableModel treeTableModel = (GanttTreeTableModel) getTreeTableModel();
        treeTableModel.deleteCustomColumn(customPropertyDefinition.getName());
    }    
    /**
     * Changes the language. The table headers change and also the menu items.
     * For the moment when the user changes the language every columns are
     * redisplayed (even if they were hidden).
     * 
     * @param ganttLanguage
     */
    public void languageChanged(GanttLanguage.Event changeEvent) {
        TableColumnModel tcm = this.getTable().getColumnModel();
        //reloadColumns();
    }


    /**
     * This class handles the mouse actions on the treetable header.
     * 
     * @author bbaranne Mar 1, 2005
     * @version 1.0 Show the popupMenu when popup is triggered.
     */

    /**
     * The class replaces the cell editor used in the hierarchical column of the
     * tree table.
     * 
     * @author bbaranne (Benoit Baranne)
     */
    class NameCellEditor extends DefaultCellEditor {
        private JTextField field = null;

        public NameCellEditor() {
            super(new JTextField());
            field = (JTextField) this.editorComponent;
        }

        @Override
        public boolean stopCellEditing() {
            System.err.println("Stop cell editing");
            return super.stopCellEditing();
        }


        @Override
        public void cancelCellEditing() {
            System.err.println("Cancel cell editing");
            super.cancelCellEditing();
        }


        @Override
        public Object getCellEditorValue() {
            // TODO Auto-generated method stub
            return super.getCellEditorValue();
        }


        @Override
        public Component getComponent() {
            // TODO Auto-generated method stub
            return super.getComponent();
        }


        public Component getTableCellEditorComponent(JTable arg0, Object arg1, boolean arg2, int arg3, int arg4) {
            final JTextField result = (JTextField) super.getTableCellEditorComponent(arg0, arg1, arg2, arg3, arg4);
            result.selectAll();
            result.addFocusListener(new FocusAdapter() {
                public void focusGained(FocusEvent arg0) {
                    super.focusGained(arg0);
//					((JTextComponent)result).selectAll();
                }

                public void focusLost(FocusEvent arg0) {
                    new Exception().printStackTrace();
                    super.focusLost(arg0);
                    
                }
                
            });
            
            return result;
        }

//
        public void requestFocus() {
            SwingUtilities.invokeLater(new Runnable() {
                public void run() {
                    field.requestFocus();
                    field.selectAll();
            }
            });
        }
    }

    public void editNewTask(Task t) {
        TreePath selectedPath = getTree().getSelectionPath();
        int c = getTable().convertColumnIndexToView(myColName.getModelIndex());
        
        //NameCellEditor nameCellEditor = (NameCellEditor) getTable().getCellEditor(-1, c);
        int row = getTree().getRowForPath(selectedPath);
        //TableCellEditor editor = getCellEditor(row, c);
        getTreeTable().editCellAt(row, c);
        getEditorComponent().requestFocus();
    }
}
