/*
 * Copyright (c) 2000, 2002, Oracle and/or its affiliates. All rights reserved.
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
 *
 * This code is free software; you can redistribute it and/or modify it
 * under the terms of the GNU General Public License version 2 only, as
 * published by the Free Software Foundation.
 *
 * This code 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 General Public License
 * version 2 for more details (a copy is included in the LICENSE file that
 * accompanied this code).
 *
 * You should have received a copy of the GNU General Public License version
 * 2 along with this work; if not, write to the Free Software Foundation,
 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
 *
 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
 * or visit www.oracle.com if you need additional information or have any
 * questions.
 *
 */

package sun.jvm.hotspot.ui;

import java.util.*;

import java.awt.*;
import java.awt.event.*;

import javax.swing.*;
import javax.swing.table.*;

import sun.jvm.hotspot.oops.ObjectHistogram;
import sun.jvm.hotspot.oops.ObjectHistogramElement;
import sun.jvm.hotspot.oops.Klass;

import sun.jvm.hotspot.ui.table.LongCellRenderer;
import sun.jvm.hotspot.ui.table.SortableTableModel;
import sun.jvm.hotspot.ui.table.SortHeaderCellRenderer;
import sun.jvm.hotspot.ui.table.SortHeaderMouseAdapter;
import sun.jvm.hotspot.ui.table.TableModelComparator;

import sun.jvm.hotspot.ui.action.*;

import com.sun.java.swing.ui.StatusBar;
import com.sun.java.swing.ui.CommonToolBar;

import com.sun.java.swing.action.ActionManager;
import com.sun.java.swing.action.DelegateAction;

/**
 * Displays the results of an ObjectHistogram run in a JTable, with a
 * button to display all objects of that type
 */
public class ObjectHistogramPanel extends JPanel implements ActionListener {
    private ObjectHistogramTableModel dataModel;
    private ObjectHistogramToolBar toolbar;
    private StatusBar statusBar;
    private JTable     table;
    private java.util.List listeners;

    public ObjectHistogramPanel(ObjectHistogram histo) {
        dataModel = new ObjectHistogramTableModel(histo);
        statusBar = new StatusBar();

        table = new JTable(dataModel, new ObjectHistogramColummModel());
        table.setSelectionMode(ListSelectionModel.SINGLE_SELECTION);
        table.addMouseListener(new MouseAdapter() {
                public void mouseClicked(MouseEvent evt) {
                    if (evt.getClickCount() == 2) {
                        fireShowObjectsOfType();
                    }
                }
            });

        JTableHeader header = table.getTableHeader();
        header.setDefaultRenderer(new SortHeaderCellRenderer(header, dataModel));
        header.addMouseListener(new SortHeaderMouseAdapter(table, dataModel));

        setLayout(new BorderLayout());

        toolbar = new ObjectHistogramToolBar(statusBar);
        add(toolbar, BorderLayout.NORTH);
        add(new JScrollPane(table), BorderLayout.CENTER);
        add(statusBar, BorderLayout.SOUTH);

        registerActions();
    }

    private class ObjectHistogramToolBar extends CommonToolBar {

        private JTextField searchTF;

        public ObjectHistogramToolBar(StatusBar status) {
            super(HSDBActionManager.getInstance(), status);
        }

        protected void addComponents() {
            searchTF = new JTextField();
            searchTF.setToolTipText("Find in Class Description");

            // Pressing Enter on the text field will search
            InputMap im = searchTF.getInputMap();
            im.put(KeyStroke.getKeyStroke("ENTER"), "enterPressed");
            ActionMap am = searchTF.getActionMap();
            am.put("enterPressed", manager.getAction(FindAction.VALUE_COMMAND));

            add(searchTF);
            addButton(manager.getAction(FindAction.VALUE_COMMAND));
            addButton(manager.getAction(ShowAction.VALUE_COMMAND));
        }

        public String getFindText() {
            return searchTF.getText();
        }
    }

    private class ObjectHistogramColummModel extends DefaultTableColumnModel {
        private final String LABEL_SIZE = "Size";
        private final String LABEL_COUNT = "Count";
        private final String LABEL_DESC = "Class Description";


        public ObjectHistogramColummModel() {
            // Should actually get the line metrics for
            int PREF_WIDTH = 80;
            int MAX_WIDTH = 100;
            int HUGE_WIDTH = 140;

            LongCellRenderer lcRender = new LongCellRenderer();

            TableColumn column;

            // Size
            column = new TableColumn(0, PREF_WIDTH);
            column.setHeaderValue(LABEL_SIZE);
            column.setMaxWidth(MAX_WIDTH);
            column.setResizable(false);
            column.setCellRenderer(lcRender);
            addColumn(column);

            // Count
            column = new TableColumn(1, PREF_WIDTH);
            column.setHeaderValue(LABEL_COUNT);
            column.setMaxWidth(MAX_WIDTH);
            column.setResizable(false);
            column.setCellRenderer(lcRender);
            addColumn(column);

            // Description
            column = new TableColumn(2, HUGE_WIDTH);
            column.setHeaderValue(LABEL_DESC);
            addColumn(column);
        }
    }


    /**
     * A table model which encapsulates the ObjectHistogram
     */
    private class ObjectHistogramTableModel extends SortableTableModel {
        private String[] columnNames = { "Size", "Count", "Class Description" };
        private Class[] columnClasses = { Long.class, Long.class, String.class };

        public ObjectHistogramTableModel(ObjectHistogram histo) {
            // Set the rows
            elements = histo.getElements();
            setComparator(new ObjectHistogramComparator(this));

        }

        public int getColumnCount() {
            return columnNames.length;
        }

        public int getRowCount() {
            return elements.size();
        }

        public String getColumnName(int col) {
            return columnNames[col];
        }

        public Class getColumnClass(int col) {
            return columnClasses[col];
        }

        public Object getValueAt(int row, int col) {
            return getValueForColumn(getElement(row), col);
        }

        public Object getValueForColumn(Object obj, int col) {
            ObjectHistogramElement el = (ObjectHistogramElement)obj;
            switch (col) {
            case 0:
                return new Long(el.getSize());
            case 1:
                return new Long(el.getCount());
            case 2:
                return el.getDescription();
            default:
                throw new RuntimeException("Index (" + col + ") out of bounds");
            }
        }

        public ObjectHistogramElement getElement(int index) {
            return (ObjectHistogramElement) elements.get(index);
        }

        private class ObjectHistogramComparator extends TableModelComparator {

            public ObjectHistogramComparator(ObjectHistogramTableModel model) {
                super(model);
            }

            /**
             * Returns the value for the comparing object for the
             * column.
             *
             * @param obj Object that was passed for Comparator
             * @param column the column to retrieve
             */
            public Object getValueForColumn(Object obj, int column) {
                ObjectHistogramTableModel omodel = (ObjectHistogramTableModel)model;
                return omodel.getValueForColumn(obj, column);
            }
        }

    }


    //
    // ActionListener implementation and actions support
    //

    public void actionPerformed(ActionEvent evt) {
        String command = evt.getActionCommand();

        if (command.equals(ShowAction.VALUE_COMMAND)) {
            fireShowObjectsOfType();
        } else if (command.equals(FindAction.VALUE_COMMAND)) {
            findObject();
        }

    }

    protected void registerActions() {
        registerAction(FindAction.VALUE_COMMAND);
        registerAction(ShowAction.VALUE_COMMAND);
    }

    private void registerAction(String actionName) {
        ActionManager manager = ActionManager.getInstance();
        DelegateAction action = manager.getDelegateAction(actionName);
        action.addActionListener(this);
    }

    public interface Listener {
        public void showObjectsOfType(Klass type);
    }

    public void addPanelListener(Listener listener) {
        if (listeners == null) {
            listeners = new ArrayList();
        }
        listeners.add(listener);
    }

    public void removePanelListener(Listener listener) {
        if (listeners != null) {
            listeners.remove(listener);
        }
    }

    //--------------------------------------------------------------------------------
    // Internals only below this point
    //

    /**
     * Find and select the row that contains the text in the find field starting
     * from the current selected row.
     *
     * Uses a linear search from the current row. Could be optimized withing the
     * model and internal representation.
     */
    private void findObject() {
        String findText = toolbar.getFindText();

        if (findText == null || findText.equals("")) {
            return;
        }

        TableModel model = table.getModel();

        int row = table.getSelectedRow();
        if (row == model.getRowCount()) {
            row = 0;
        } else {
            // Start at the row after the selected row.
            row++;
        }

        String value;
        for (int i = row; i < model.getRowCount(); i++) {
            value = (String)model.getValueAt(i, 2);
            if (value != null && value.startsWith(findText)) {
                table.setRowSelectionInterval(i, i);
                Rectangle cellBounds = table.getCellRect(i, 0, true);
                table.scrollRectToVisible(cellBounds);
                return;
            }
        }

        // Wrap the table to search in the top rows.
        for (int i = 0; i < row; i++) {
            value = (String)model.getValueAt(i, 2);
            if (value != null && value.startsWith(findText)) {
                table.setRowSelectionInterval(i, i);
                Rectangle cellBounds = table.getCellRect(i, 0, true);
                table.scrollRectToVisible(cellBounds);
                return;
            }
        }
    }

    private void fireShowObjectsOfType() {
        int i = table.getSelectedRow();
        if (i < 0) {
            return;
        }

        ObjectHistogramElement el = dataModel.getElement(i);

        for (Iterator iter = listeners.iterator(); iter.hasNext(); ) {
            Listener listener = (Listener) iter.next();
            listener.showObjectsOfType(el.getKlass());
        }
    }

    public static void main(String[] args) {

    }
}
