/*
 * Copyright (c) 2001, 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.awt.*;
import java.awt.datatransfer.*;
import java.awt.event.*;
import java.io.IOException;
import java.math.*;
import java.util.*;
import javax.swing.*;
import javax.swing.event.*;
import javax.swing.table.*;
import sun.jvm.hotspot.debugger.*;
import sun.jvm.hotspot.ui.*;

public class MemoryPanel extends JPanel {
  private boolean is64Bit;
  private Debugger debugger;
  private int addressSize;
  private String unmappedAddrString;
  private HighPrecisionJScrollBar scrollBar;
  private AbstractTableModel model;
  private JTable table;
  private BigInteger startVal;
  // Includes any partially-visible row at the bottom
  private int numVisibleRows;
  // Frequently-used subexpression
  private int numUsableRows;
  // Multi-row (and multi-column) selection. Have to duplicate state
  // from UI so this can work as we scroll off the screen.
  private boolean haveAnchor;
  private int     rowAnchorIndex;
  private int     colAnchorIndex;
  private boolean haveLead;
  private int     rowLeadIndex;
  private int     colLeadIndex;

  abstract class ActionWrapper extends AbstractAction {
    private Action parent;
    ActionWrapper() {
    }

    void setParent(Action parent) {
      this.parent = parent;
    }

    Action getParent() {
      return parent;
    }

    public void actionPerformed(ActionEvent e) {
      if (getParent() != null) {
        getParent().actionPerformed(e);
      }
    }
  }

  public MemoryPanel(final Debugger debugger, boolean is64Bit) {
    super();
    this.debugger = debugger;
    this.is64Bit = is64Bit;
    if (is64Bit) {
      addressSize = 8;
      unmappedAddrString = "??????????????????";
    } else {
      addressSize = 4;
      unmappedAddrString = "??????????";
    }
    setLayout(new BorderLayout());
    setupScrollBar();
    add(scrollBar, BorderLayout.EAST);

    model = new AbstractTableModel() {
        public int getRowCount() {
          return numVisibleRows;
        }
        public int getColumnCount() {
          return 2;
        }
        public Object getValueAt(int row, int column) {
          switch (column) {
          case 0:  return bigIntToHexString(startVal.add(new BigInteger(Integer.toString((row * addressSize)))));
          case 1: {
            try {
              Address addr = bigIntToAddress(startVal.add(new BigInteger(Integer.toString((row * addressSize)))));
              if (addr != null) {
                return addressToString(addr.getAddressAt(0));
              }
              return unmappedAddrString;
            } catch (UnmappedAddressException e) {
              return unmappedAddrString;
            }
          }
          default: throw new RuntimeException("Column " + column + " out of bounds");
          }
        }
        public boolean isCellEditable(int row, int col) {
          return false;
        }
      };

    // View with JTable with no header
    table = new JTable(model);
    table.setTableHeader(null);
    table.setShowGrid(false);
    table.setIntercellSpacing(new Dimension(0, 0));
    table.setCellSelectionEnabled(true);
    table.setSelectionMode(ListSelectionModel.SINGLE_INTERVAL_SELECTION);
    table.setDragEnabled(true);
    Font font = GraphicsUtilities.lookupFont("Courier");
    if (font == null) {
      throw new RuntimeException("Error looking up monospace font Courier");
    }
    table.setFont(font);

    // Export proper data.
    // We need to keep our own notion of the selection in order to
    // properly export data, since the selection can go beyond the
    // visible area on the screen (and since the table's model doesn't
    // back all of those slots).
    // Code thanks to Shannon.Hickey@sfbay
    table.setTransferHandler(new TransferHandler() {
        protected Transferable createTransferable(JComponent c) {
          JTable table = (JTable)c;
          if (haveSelection()) {
            StringBuffer buf = new StringBuffer();
            int iDir = (getRowAnchor() < getRowLead() ? 1 : -1);
            int jDir = (getColAnchor() < getColLead() ? 1 : -1);

            for (int i = getRowAnchor(); i != getRowLead() + iDir; i += iDir) {
              for (int j = getColAnchor(); j != getColLead() + jDir; j += jDir) {
                Object val = model.getValueAt(i, j);
                buf.append(val == null ? "" : val.toString());
                if (j != getColLead()) {
                  buf.append("\t");
                }
              }
              if (i != getRowLead()) {
                buf.append("\n");
              }
            }

            return new StringTransferable(buf.toString());
          }
          return null;
        }

        public int getSourceActions(JComponent c) {
          return COPY;
        }

        public boolean importData(JComponent c, Transferable t) {
          if (canImport(c, t.getTransferDataFlavors())) {
            try {
              String str = (String)t.getTransferData(DataFlavor.stringFlavor);
              handleImport(c, str);
              return true;
            } catch (UnsupportedFlavorException ufe) {
            } catch (IOException ioe) {
            }
          }

          return false;
        }

        public boolean canImport(JComponent c, DataFlavor[] flavors) {
          for (int i = 0; i < flavors.length; i++) {
            if (DataFlavor.stringFlavor.equals(flavors[i])) {
              return true;
            }
          }
          return false;
        }

        private void handleImport(JComponent c, String str) {
          // do whatever you want with the string here
          try {
            makeVisible(debugger.parseAddress(str));
            clearSelection();
            table.clearSelection();
          } catch (NumberFormatException e) {
            System.err.println("Unable to parse address \"" + str + "\"");
          }
        }
      });

    // Supporting keyboard scrolling
    // See src/share/classes/javax/swing/plaf/metal/MetalLookAndFeel.java,
    // search for Table.AncestorInputMap

    // Actions to override:
    // selectPreviousRow, selectNextRow,
    // scrollUpChangeSelection, scrollDownChangeSelection,
    // selectPreviousRowExtendSelection, selectNextRowExtendSelection,
    // scrollDownExtendSelection, scrollUpExtendSelection (Shift-PgDn/PgUp)

    ActionMap map = table.getActionMap();

    // Up arrow
    installActionWrapper(map, "selectPreviousRow", new ActionWrapper() {
        public void actionPerformed(ActionEvent e) {
          beginUpdate();
          clearSelection();
          if (table.getSelectedRow() == 0) {
            scrollBar.scrollUpOrLeft();
            table.setRowSelectionInterval(0, 0);
          } else {
            super.actionPerformed(e);
          }
          maybeGrabSelection();
          endUpdate();
        }
      });
    // Down arrow
    installActionWrapper(map, "selectNextRow", new ActionWrapper() {
        public void actionPerformed(ActionEvent e) {
          beginUpdate();
          clearSelection();
          int row = table.getSelectedRow();
          if (row >= numUsableRows) {
            scrollBar.scrollDownOrRight();
            table.setRowSelectionInterval(row, row);
          } else {
            super.actionPerformed(e);
          }
          maybeGrabSelection();
          endUpdate();
        }
      });
    // Page up
    installActionWrapper(map, "scrollUpChangeSelection", new ActionWrapper() {
        public void actionPerformed(ActionEvent e) {
          beginUpdate();
          clearSelection();
          int row = table.getSelectedRow();
          scrollBar.pageUpOrLeft();
          if (row >= 0) {
            table.setRowSelectionInterval(row, row);
          }
          maybeGrabSelection();
          endUpdate();
        }
      });
    // Page down
    installActionWrapper(map, "scrollDownChangeSelection", new ActionWrapper() {
        public void actionPerformed(ActionEvent e) {
          beginUpdate();
          clearSelection();
          int row = table.getSelectedRow();
          scrollBar.pageDownOrRight();
          if (row >= 0) {
            table.setRowSelectionInterval(row, row);
          }
          maybeGrabSelection();
          endUpdate();
        }
      });
    // Shift + Up arrow
    installActionWrapper(map, "selectPreviousRowExtendSelection", new ActionWrapper() {
        public void actionPerformed(ActionEvent e) {
          beginUpdate();
          if (!haveAnchor()) {
            setAnchorFromTable();
            setLeadFromTable();
            //            setAnchor(table.getSelectedRow());
            //            setLead(table.getSelectedRow());
          }
          int newLead = getRowLead() - 1;
          int newAnchor = getRowAnchor();
          if (newLead < 0) {
            scrollBar.scrollUpOrLeft();
            ++newLead;
            ++newAnchor;
          }
          setSelection(newAnchor, newLead, getColAnchor(), getColLead());
          //          printSelection();
          endUpdate();
        }
      });
    // Shift + Left arrow
    installActionWrapper(map, "selectPreviousColumnExtendSelection", new ActionWrapper() {
        public void actionPerformed(ActionEvent e) {
          beginUpdate();
          if (!haveAnchor()) {
            setAnchorFromTable();
            setLeadFromTable();
          }
          int newLead = Math.max(0, getColLead() - 1);
          setSelection(getRowAnchor(), getRowLead(), getColAnchor(), newLead);
          //          printSelection();
          endUpdate();
        }
      });
    // Shift + Down arrow
    installActionWrapper(map, "selectNextRowExtendSelection", new ActionWrapper() {
        public void actionPerformed(ActionEvent e) {
          beginUpdate();
          if (!haveAnchor()) {
            setAnchorFromTable();
            setLeadFromTable();
            //            setAnchor(table.getSelectedRow());
            //            setLead(table.getSelectedRow());
          }
          int newLead = getRowLead() + 1;
          int newAnchor = getRowAnchor();
          if (newLead > numUsableRows) {
            scrollBar.scrollDownOrRight();
            --newLead;
            --newAnchor;
          }
          setSelection(newAnchor, newLead, getColAnchor(), getColLead());
          //          printSelection();
          endUpdate();
        }
      });
    // Shift + Right arrow
    installActionWrapper(map, "selectNextColumnExtendSelection", new ActionWrapper() {
        public void actionPerformed(ActionEvent e) {
          beginUpdate();
          if (!haveAnchor()) {
            setAnchorFromTable();
            setLeadFromTable();
          }
          int newLead = Math.min(model.getColumnCount() - 1, getColLead() + 1);
          setSelection(getRowAnchor(), getRowLead(), getColAnchor(), newLead);
          //          printSelection();
          endUpdate();
        }
      });
    // Shift + Page up
    installActionWrapper(map, "scrollUpExtendSelection", new ActionWrapper() {
        public void actionPerformed(ActionEvent e) {
          beginUpdate();
          if (!haveAnchor()) {
            setAnchorFromTable();
            setLeadFromTable();
            //            setAnchor(table.getSelectedRow());
            //            setLead(table.getSelectedRow());
          }
          int newLead = getRowLead() - numUsableRows;
          int newAnchor = getRowAnchor();
          if (newLead < 0) {
            scrollBar.pageUpOrLeft();
            newLead += numUsableRows;
            newAnchor += numUsableRows;
          }
          setSelection(newAnchor, newLead, getColAnchor(), getColLead());
          //          printSelection();
          endUpdate();
        }
      });
    // Shift + Page down
    installActionWrapper(map, "scrollDownExtendSelection", new ActionWrapper() {
        public void actionPerformed(ActionEvent e) {
          beginUpdate();
          if (!haveAnchor()) {
            setAnchorFromTable();
            setLeadFromTable();
            //            setAnchor(table.getSelectedRow());
            //            setLead(table.getSelectedRow());
          }
          int newLead = getRowLead() + numUsableRows;
          int newAnchor = getRowAnchor();
          if (newLead > numUsableRows) {
            scrollBar.pageDownOrRight();
            newLead -= numUsableRows;
            newAnchor -= numUsableRows;
          }
          setSelection(newAnchor, newLead, getColAnchor(), getColLead());
          //          printSelection();
          endUpdate();
        }
      });

    // Clear our notion of selection upon mouse press
    table.addMouseListener(new MouseAdapter() {
        public void mousePressed(MouseEvent e) {
          if (shouldIgnore(e)) {
            return;
          }
          // Make shift-clicking work properly
          if (e.isShiftDown()) {
            maybeGrabSelection();
            return;
          }
          //          System.err.println("  Clearing selection on mouse press");
          clearSelection();
        }
      });

    // Watch for mouse going out of bounds
    table.addMouseMotionListener(new MouseMotionAdapter() {
        public void mouseDragged(MouseEvent e) {
          if (shouldIgnore(e)) {
            //            System.err.println("  (Ignoring consumed mouse event)");
            return;
          }

          // Look for drag events outside table and scroll if necessary
          Point p = e.getPoint();
          if (table.rowAtPoint(p) == -1) {
            // See whether we are above or below the table
            Rectangle rect = new Rectangle();
            getBounds(rect);
            beginUpdate();
            if (p.y < rect.y) {
              //              System.err.println("  Scrolling up due to mouse event");
              // Scroll up
              scrollBar.scrollUpOrLeft();
              setSelection(getRowAnchor(), 0, getColAnchor(), getColLead());
            } else {
              //              System.err.println("  Scrolling down due to mouse event");
              // Scroll down
              scrollBar.scrollDownOrRight();
              setSelection(getRowAnchor(), numUsableRows, getColAnchor(), getColLead());
            }
            //            printSelection();
            endUpdate();
          } else {
            maybeGrabSelection();
          }
        }
      });


    add(table, BorderLayout.CENTER);

    // Make sure we recompute number of visible rows
    addComponentListener(new ComponentAdapter() {
        public void componentResized(ComponentEvent e) {
          recomputeNumVisibleRows();
          constrain();
        }
      });
    addHierarchyListener(new HierarchyListener() {
        public void hierarchyChanged(HierarchyEvent e) {
          recomputeNumVisibleRows();
          constrain();
        }
      });
    updateFromScrollBar();
  }

  /** Makes the given address visible somewhere in the window */
  public void makeVisible(Address addr) {
    BigInteger bi = addressToBigInt(addr);
    scrollBar.setValueHP(bi);
  }

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

  private void setupScrollBar() {
    if (is64Bit) {
      // 64-bit mode
      scrollBar =
        new HighPrecisionJScrollBar(
          Scrollbar.VERTICAL,
          new BigInteger(1, new byte[] {
            (byte) 0x80, (byte) 0x00, (byte) 0x00, (byte) 0x00,
            (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00}),
          new BigInteger(1, new byte[] {
            (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00,
            (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00}),
          new BigInteger(1, new byte[] {
            (byte) 0xFF, (byte) 0xFF, (byte) 0xFF, (byte) 0xFF,
            (byte) 0xFF, (byte) 0xFF, (byte) 0xFF, (byte) 0xFC}));
      scrollBar.setUnitIncrementHP(new BigInteger(1, new byte[] {
        (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00,
        (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x08}));
      scrollBar.setBlockIncrementHP(new BigInteger(1, new byte[] {
        (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00,
        (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x40}));
    } else {
      // 32-bit mode
      scrollBar=
        new HighPrecisionJScrollBar(
          Scrollbar.VERTICAL,
          new BigInteger(1, new byte[] {
            (byte) 0x80, (byte) 0x00, (byte) 0x00, (byte) 0x00}),
          new BigInteger(1, new byte[] {
            (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00}),
          new BigInteger(1, new byte[] {
            (byte) 0xFF, (byte) 0xFF, (byte) 0xFF, (byte) 0xFC}));
      scrollBar.setUnitIncrementHP(new BigInteger(1, new byte[] {
        (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x04}));
      scrollBar.setBlockIncrementHP(new BigInteger(1, new byte[] {
        (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x20}));
    }
    scrollBar.addChangeListener(new ChangeListener() {
        public void stateChanged(ChangeEvent e) {
          updateFromScrollBar();
        }
      });
  }

  private void updateFromScrollBar() {
    beginUpdate();
    BigInteger oldStartVal = startVal;
    startVal = scrollBar.getValueHP();
    constrain();
    model.fireTableDataChanged();
    if (oldStartVal != null) {
      modifySelection(oldStartVal.subtract(startVal).intValue() / addressSize);
    }
    endUpdate();
  }

  private void constrain() {
    BigInteger offset = new BigInteger(Integer.toString(addressSize * (numUsableRows)));
    BigInteger endVal = startVal.add(offset);
    if (endVal.compareTo(scrollBar.getMaximumHP()) > 0) {
      startVal = scrollBar.getMaximumHP().subtract(offset);
      endVal   = scrollBar.getMaximumHP();
      scrollBar.setValueHP(startVal);
      model.fireTableDataChanged();
    }
  }

  private void recomputeNumVisibleRows() {
    Rectangle rect = new Rectangle();
    getBounds(rect);
    int h = table.getRowHeight();
    numVisibleRows = (rect.height + (h - 1)) / h;
    numUsableRows  = numVisibleRows - 2;
    scrollBar.setBlockIncrementHP(new BigInteger(Integer.toString(addressSize * (numUsableRows))));
    model.fireTableDataChanged();
    // FIXME: refresh selection
  }

  private String bigIntToHexString(BigInteger bi) {
    StringBuffer buf = new StringBuffer();
    buf.append("0x");
    String val = bi.toString(16);
    for (int i = 0; i < ((2 * addressSize) - val.length()); i++) {
      buf.append('0');
    }
    buf.append(val);
    return buf.toString();
  }

  private Address bigIntToAddress(BigInteger i) {
    String s = bigIntToHexString(i);
    return debugger.parseAddress(s);
  }

  private BigInteger addressToBigInt(Address a) {
    String s = addressToString(a);
    if (!s.startsWith("0x")) {
      throw new NumberFormatException(s);
    }
    return new BigInteger(s.substring(2), 16);
  }

  private String addressToString(Address a) {
    if (a == null) {
      if (is64Bit) {
        return "0x0000000000000000";
      } else {
        return "0x00000000";
      }
    }
    return a.toString();
  }

  private static void installActionWrapper(ActionMap map,
                                           String actionName,
                                           ActionWrapper wrapper) {
    wrapper.setParent(map.get(actionName));
    map.put(actionName, wrapper);
  }

  private boolean shouldIgnore(MouseEvent e) {
    return e.isConsumed() || (!(SwingUtilities.isLeftMouseButton(e) && table.isEnabled()));
  }

  private void clearSelection() {
    haveAnchor = false;
    haveLead = false;
  }

  private int updateLevel;
  private boolean updating()         { return updateLevel > 0; }
  private void    beginUpdate()      { ++updateLevel;          }
  private void    endUpdate()        { --updateLevel;          }

  private boolean haveAnchor()       { return haveAnchor;  }
  private boolean haveLead()         { return haveLead;    }
  private boolean haveSelection()    { return haveAnchor() && haveLead(); }
  private int     getRowAnchor()     { return rowAnchorIndex; }
  private int     getColAnchor()     { return colAnchorIndex; }
  private int     getRowLead()       { return rowLeadIndex;   }
  private int     getColLead()       { return colLeadIndex;   }

  private void setAnchorFromTable() {
    setAnchor(table.getSelectionModel().getAnchorSelectionIndex(),
              table.getColumnModel().getSelectionModel().getAnchorSelectionIndex());
  }
  private void setLeadFromTable() {
    setLead(table.getSelectionModel().getAnchorSelectionIndex(),
            table.getColumnModel().getSelectionModel().getAnchorSelectionIndex());
  }
  private void setAnchor(int row, int col) {
    rowAnchorIndex = row;
    colAnchorIndex = col;
    haveAnchor = true;
  }
  private void setLead(int row, int col) {
    rowLeadIndex = row;
    colLeadIndex = col;
    haveLead = true;
  }
  private int clamp(int val, int min, int max) {
    return Math.max(Math.min(val, max), min);
  }
  private void maybeGrabSelection() {
    if (table.getSelectedRow() != -1) {
      // Grab selection
      ListSelectionModel rowSel = table.getSelectionModel();
      ListSelectionModel colSel = table.getColumnModel().getSelectionModel();
      if (!haveAnchor()) {
        //        System.err.println("Updating from table's selection");
        setSelection(rowSel.getAnchorSelectionIndex(), rowSel.getLeadSelectionIndex(),
                     colSel.getAnchorSelectionIndex(), colSel.getLeadSelectionIndex());
      } else {
        //        System.err.println("Updating lead from table's selection");
        setSelection(getRowAnchor(), rowSel.getLeadSelectionIndex(),
                     getColAnchor(), colSel.getLeadSelectionIndex());
      }
      //      printSelection();
    }
  }
  private void setSelection(int rowAnchor, int rowLead, int colAnchor, int colLead) {
    setAnchor(rowAnchor, colAnchor);
    setLead(rowLead, colLead);
    table.setRowSelectionInterval(clamp(rowAnchor, 0, numUsableRows),
                                  clamp(rowLead, 0, numUsableRows));
    table.setColumnSelectionInterval(colAnchor, colLead);
  }
  private void modifySelection(int amount) {
    if (haveSelection()) {
      setSelection(getRowAnchor() + amount, getRowLead() + amount,
                   getColAnchor(), getColLead());
    }
  }
  private void printSelection() {
    System.err.println("Selection updated to (" +
                       model.getValueAt(getRowAnchor(), getColAnchor()) +
                       ", " +
                       model.getValueAt(getRowLead(), getColLead()) + ") [(" +
                       getRowAnchor() + ", " + getColAnchor() + "), (" +
                       getRowLead() + ", " + getColLead() + ")]");
  }
}
