/*
 * Copyright (c) 2000, 2008, 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.math.*;
import java.awt.*;
import java.awt.font.*;
import java.awt.geom.*;
import java.awt.event.*;
import java.io.*;
import javax.swing.*;
import javax.swing.event.*;
import java.util.*;

import sun.jvm.hotspot.debugger.*;
import sun.jvm.hotspot.debugger.dummy.*;
import sun.jvm.hotspot.utilities.*;

/** A subclass of JPanel which displays a hex dump of memory along
    with annotations describing the significance of various
    pieces. This can be used to implement either a stack or heap
    inspector. */

public class AnnotatedMemoryPanel extends JPanel {
  private boolean is64Bit;
  private Debugger debugger;
  private long    addressSize;
  private HighPrecisionJScrollBar scrollBar;
  private Font font;
  private int bytesPerLine;
  private int paintCount;
  private String unmappedAddrString;
  // Type of this is an IntervalTree indexed by Interval<Address> and
  // with user data of type Annotation
  private IntervalTree annotations =
    new IntervalTree(new Comparator() {
        public int compare(Object o1, Object o2) {
          Address a1 = (Address) o1;
          Address a2 = (Address) o2;

          if ((a1 == null) && (a2 == null)) {
            return 0;
          } else if (a1 == null) {
            return -1;
          } else if (a2 == null) {
            return 1;
          }

          if (a1.equals(a2)) {
            return 0;
          } else if (a1.lessThan(a2)) {
            return -1;
          }
          return 1;
        }
      });
  // Keep track of the last start address at which we painted, so we
  // can scroll annotations
  private Address lastStartAddr;
  // This contains the list of currently-visible IntervalNodes, in
  // sorted order by their low endpoint, in the form of a
  // List<Annotation>. These annotations have already been laid out.
  private java.util.List visibleAnnotations;
  // Darker colors than defaults for better readability
  private static Color[] colors = {
    new Color(0.0f, 0.0f, 0.6f), // blue
    new Color(0.6f, 0.0f, 0.6f), // magenta
    new Color(0.0f, 0.8f, 0.0f), // green
    new Color(0.8f, 0.3f, 0.0f), // orange
    new Color(0.0f, 0.6f, 0.8f), // cyan
    new Color(0.2f, 0.2f, 0.2f), // dark gray
  };

  /** Default is 32-bit mode */
  public AnnotatedMemoryPanel(Debugger debugger) {
    this(debugger, false);
  }

  public AnnotatedMemoryPanel(Debugger debugger, boolean is64Bit, Address addrValue, Address addrLow, Address addrHigh) {
    super();
    init(debugger, is64Bit, addressToBigInt(addrValue), addressToBigInt(addrLow), addressToBigInt(addrHigh));
  }

  public AnnotatedMemoryPanel(Debugger debugger, boolean is64Bit ) {
    super();
    init(debugger, is64Bit, defaultMemoryLocation(is64Bit), defaultMemoryLow(is64Bit), defaultMemoryHigh(is64Bit));
  }

  static class AnnoX {
    int     lineX;
    Address highBound;

    public AnnoX(int lineX, Address highBound) {
      this.lineX = lineX;
      this.highBound = highBound;
    }
  }

  public synchronized void paintComponent(Graphics g) {
    //    System.err.println("AnnotatedMemoryPanel.paintComponent() " + ++paintCount);
    super.paintComponent(g);

    // Clone the Graphics so we don't screw up its state for Swing
    // drawing (as this code otherwise does)
    g = g.create();

    g.setFont(font);
    g.setColor(Color.black);
    Rectangle rect = new Rectangle();
    getBounds(rect);
    String firstAddressString = null;
    int lineHeight;
    int addrWidth;
    {
      Rectangle2D bounds = GraphicsUtilities.getStringBounds(unmappedAddrString, g);
      lineHeight = (int) bounds.getHeight();
      addrWidth  = (int) bounds.getWidth();
    }
    int addrX = (int) (0.25 * addrWidth);
    int dataX = (int) (addrX + (1.5 * addrWidth));
    int lineStartX = dataX + addrWidth + 5;
    int annoStartX = (int) (lineStartX + (0.75 * addrWidth));

    int numLines = rect.height / lineHeight;

    BigInteger startVal  = scrollBar.getValueHP();
    BigInteger perLine = new BigInteger(Integer.toString((int) addressSize));
    // lineCount and maxLines are both 1 less than expected
    BigInteger lineCount = new BigInteger(Integer.toString((int) (numLines - 1)));
    BigInteger maxLines = scrollBar.getMaximumHP().subtract(scrollBar.getMinimumHP()).divide(perLine);
    if (lineCount.compareTo(maxLines) > 0) {
      lineCount = maxLines;
    }
    BigInteger offsetVal = lineCount.multiply(perLine);
    BigInteger endVal    = startVal.add(offsetVal);
    if (endVal.compareTo(scrollBar.getMaximumHP()) > 0) {
      startVal = scrollBar.getMaximumHP().subtract(offsetVal);
      endVal   = scrollBar.getMaximumHP();
      // Sure seems like this call will cause us to immediately redraw...
      scrollBar.setValueHP(startVal);
    }
    scrollBar.setVisibleAmountHP(offsetVal.add(perLine));
    scrollBar.setBlockIncrementHP(offsetVal);

    Address startAddr = bigIntToAddress(startVal);
    Address endAddr   = bigIntToAddress(endVal);

    // Scroll last-known annotations
    int scrollOffset = 0;
    if (lastStartAddr != null) {
      scrollOffset = (int) lastStartAddr.minus(startAddr);
    } else {
      if (startAddr != null) {
        scrollOffset = (int) (-1 * startAddr.minus(lastStartAddr));
      }
    }
    scrollOffset = scrollOffset * lineHeight / (int) addressSize;
    scrollAnnotations(scrollOffset);
    lastStartAddr = startAddr;

    int curY = lineHeight;
    Address curAddr = startAddr;
    for (int i = 0; i < numLines; i++) {
      String s = bigIntToHexString(startVal);
      g.drawString(s, addrX, curY);
      try {
        s = addressToString(startAddr.getAddressAt(i * addressSize));
      }
      catch (UnmappedAddressException e) {
        s = unmappedAddrString;
      }
      g.drawString(s, dataX, curY);
      curY += lineHeight;
      startVal = startVal.add(perLine);
    }

    // Query for visible annotations (little slop to ensure we get the
    // top and bottom)
    // FIXME: it would be nice to have a more static layout; that is,
    // if something scrolls off the bottom of the screen, other
    // annotations still visible shouldn't change position
    java.util.List va =
      annotations.findAllNodesIntersecting(new Interval(startAddr.addOffsetTo(-addressSize),
                                                        endAddr.addOffsetTo(2 * addressSize)));

    // Render them
    int curLineX = lineStartX;
    int curTextX = annoStartX;
    int curColorIdx = 0;
    if (g instanceof Graphics2D) {
      Stroke stroke = new BasicStroke(3.0f);
      ((Graphics2D) g).setStroke(stroke);
    }

    Stack drawStack = new Stack();

    layoutAnnotations(va, g, curTextX, startAddr, lineHeight);

    for (Iterator iter = visibleAnnotations.iterator(); iter.hasNext(); ) {
      Annotation anno   = (Annotation) iter.next();
      Interval interval = anno.getInterval();

      if (!drawStack.empty()) {
        // See whether we can pop any items off the stack
        boolean shouldContinue = true;
        do {
          AnnoX annoX = (AnnoX) drawStack.peek();
          if (annoX.highBound.lessThanOrEqual((Address) interval.getLowEndpoint())) {
            curLineX = annoX.lineX;
            drawStack.pop();
            shouldContinue = !drawStack.empty();
          } else {
            shouldContinue = false;
          }
        } while (shouldContinue);
      }

      // Draw a line covering the interval
      Address lineStartAddr = (Address) interval.getLowEndpoint();
      // Give it a little slop
      int lineStartY = (int) (lineStartAddr.minus(startAddr) * lineHeight / addressSize) +
        (lineHeight / 3);
      Address lineEndAddr = (Address) interval.getHighEndpoint();
      drawStack.push(new AnnoX(curLineX, lineEndAddr));
      int lineEndY = (int) (lineEndAddr.minus(startAddr) * lineHeight / addressSize);
      g.setColor(anno.getColor());
      g.drawLine(curLineX, lineStartY, curLineX, lineEndY);
      // Draw line to text
      g.drawLine(curLineX, lineStartY, curTextX - 10, anno.getY() - (lineHeight / 2));
      curLineX += 8;
      anno.draw(g);
      ++curColorIdx;
    }
  }

  /** Add an annotation covering the address range [annotation.lowAddress,
      annotation.highAddress); that is, it includes the low address and does not
      include the high address. */
  public synchronized void addAnnotation(Annotation annotation) {
    annotations.insert(annotation.getInterval(), annotation);
  }

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

  public void print() {
    printOn(System.out);
  }

  public void printOn(PrintStream tty) {
    annotations.printOn(tty);
  }

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

  private void init(Debugger debugger, boolean is64Bit, BigInteger addrValue, BigInteger addrLow, BigInteger addrHigh) {
    this.is64Bit = is64Bit;
    this.debugger = debugger;
    if (is64Bit) {
      addressSize = 8;
      unmappedAddrString = "??????????????????";
    } else {
      addressSize = 4;
      unmappedAddrString = "??????????";
    }
    setLayout(new BorderLayout());
    setupScrollBar(addrValue, addrLow, addrHigh);
    add(scrollBar, BorderLayout.EAST);
    visibleAnnotations = new ArrayList();
    setBackground(Color.white);
    addHierarchyBoundsListener(new HierarchyBoundsListener() {
        public void ancestorMoved(HierarchyEvent e) {
        }

        public void ancestorResized(HierarchyEvent e) {
          // FIXME: should perform incremental layout
          //          System.err.println("Ancestor resized");
        }
      });

    if (font == null) {
      font = GraphicsUtilities.lookupFont("Courier");
    }
    if (font == null) {
      throw new RuntimeException("Error looking up monospace font Courier");
    }
    getInputMap(WHEN_IN_FOCUSED_WINDOW).put(KeyStroke.getKeyStroke(KeyEvent.VK_PAGE_DOWN, 0), "PageDown");
    getActionMap().put("PageDown", new AbstractAction() {
        public void actionPerformed(ActionEvent e) {
          scrollBar.setValueHP(scrollBar.getValueHP().add(scrollBar.getBlockIncrementHP()));
        }
      });
    getInputMap(WHEN_IN_FOCUSED_WINDOW).put(KeyStroke.getKeyStroke(KeyEvent.VK_PAGE_UP, 0), "PageUp");
    getActionMap().put("PageUp", new AbstractAction() {
        public void actionPerformed(ActionEvent e) {
          scrollBar.setValueHP(scrollBar.getValueHP().subtract(scrollBar.getBlockIncrementHP()));
        }
      });
    getInputMap(WHEN_IN_FOCUSED_WINDOW).put(KeyStroke.getKeyStroke(KeyEvent.VK_DOWN, 0), "Down");
    getActionMap().put("Down", new AbstractAction() {
        public void actionPerformed(ActionEvent e) {
          scrollBar.setValueHP(scrollBar.getValueHP().add(scrollBar.getUnitIncrementHP()));
        }
      });
    getInputMap(WHEN_IN_FOCUSED_WINDOW).put(KeyStroke.getKeyStroke(KeyEvent.VK_UP, 0), "Up");
    getActionMap().put("Up", new AbstractAction() {
        public void actionPerformed(ActionEvent e) {
          scrollBar.setValueHP(scrollBar.getValueHP().subtract(scrollBar.getUnitIncrementHP()));
        }
      });
    setEnabled(true);
  }

  private void setupScrollBar(BigInteger value, BigInteger min, BigInteger max) {
    scrollBar = new HighPrecisionJScrollBar( Scrollbar.VERTICAL, value, min, max);
    if (is64Bit) {
      bytesPerLine = 8;
      // 64-bit mode
      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
      bytesPerLine = 4;
      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) {
          HighPrecisionJScrollBar h = (HighPrecisionJScrollBar) e.getSource();
          repaint();
        }
      });
  }

  private static BigInteger defaultMemoryLocation(boolean is64Bit) {
    if (is64Bit) {
      return new BigInteger(1, new byte[] {
                           (byte) 0x80, (byte) 0x00, (byte) 0x00, (byte) 0x00,
                           (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00});
    } else {
      return new BigInteger(1, new byte[] { (byte) 0x80, (byte) 0x00, (byte) 0x00, (byte) 0x00});
    }
  }

  private static BigInteger defaultMemoryLow(boolean is64Bit) {
    if (is64Bit) {
      return new BigInteger(1, new byte[] {
                 (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00,
                 (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00});
    } else {
      return new BigInteger(1, new byte[] { (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00});
    }
  }

  private static BigInteger defaultMemoryHigh(boolean is64Bit) {
    if (is64Bit) {
      return new BigInteger(1, new byte[] {
                 (byte) 0xFF, (byte) 0xFF, (byte) 0xFF, (byte) 0xFF,
                 (byte) 0xFF, (byte) 0xFF, (byte) 0xFF, (byte) 0xFC});
    } else {
      return new BigInteger(1, new byte[] { (byte) 0xFF, (byte) 0xFF, (byte) 0xFF, (byte) 0xFC});
    }
  }

  private void setupScrollBar() {
    setupScrollBar(defaultMemoryLocation(is64Bit),
                   defaultMemoryLow(is64Bit),
                   defaultMemoryHigh(is64Bit));
  }

  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();
  }

  /** Scrolls the visible annotations by the given Y amount */
  private void scrollAnnotations(int y) {
    for (Iterator iter = visibleAnnotations.iterator(); iter.hasNext(); ) {
      Annotation anno = (Annotation) iter.next();
      anno.setY(anno.getY() + y);
    }
  }

  /** Takes the list of currently-visible annotations (in the form of
      a List<IntervalNode>) and lays them out given the current
      visible position and the already-visible annotations. Does not
      perturb the layouts of the currently-visible annotations. */
  private void layoutAnnotations(java.util.List va,
                                 Graphics g,
                                 int x,
                                 Address startAddr,
                                 int lineHeight) {
    // Handle degenerate case early: no visible annotations.
    if (va.size() == 0) {
      visibleAnnotations.clear();
      return;
    }

    // We have two ranges of visible annotations: the one from the
    // last repaint and the currently visible set. We want to preserve
    // the layouts of the previously-visible annotations that are
    // currently visible (to avoid color flashing, jumping, etc.)
    // while making the coloring of the new annotations fit as well as
    // possible. Note that annotations may appear and disappear from
    // any point in the previously-visible list, but the ordering of
    // the visible annotations is always the same.

    // This is really a constrained graph-coloring problem. This
    // simple algorithm only takes into account half of the
    // constraints (for example, the layout of the previous
    // annotation, where it should be taking into account the layout
    // of the previous and next annotations that were in the
    // previously-visible list). There are situations where it can
    // generate overlapping annotations and adjacent annotations with
    // the same color; generally visible when scrolling line-by-line
    // rather than page-by-page. In some of these situations, will
    // have to move previously laid-out annotations. FIXME: revisit
    // this.

    // Index of last annotation which we didn't know how to lay out
    int deferredIndex = -1;
    // We "lay out after" this one
    Annotation constraintAnnotation = null;
    // The first constraint annotation
    Annotation firstConstraintAnnotation = null;
    // The index from which we search forward in the
    // visibleAnnotations list. This reduces the amount of work we do.
    int searchIndex = 0;
    // The new set of annotations
    java.util.List newAnnos = new ArrayList();

    for (Iterator iter = va.iterator(); iter.hasNext(); ) {
      Annotation anno = (Annotation) ((IntervalNode) iter.next()).getData();

      // Search forward for this one
      boolean found = false;
      for (int i = searchIndex; i < visibleAnnotations.size(); i++) {
        Annotation el = (Annotation) visibleAnnotations.get(i);
        // See whether we can abort the search unsuccessfully because
        // we went forward too far
        if (el.getLowAddress().greaterThan(anno.getLowAddress())) {
          break;
        }
        if (el == anno) {
          // Found successfully.
          found = true;
          searchIndex = i;
          constraintAnnotation = anno;
          if (firstConstraintAnnotation == null) {
            firstConstraintAnnotation = constraintAnnotation;
          }
          break;
        }
      }

      if (!found) {
        if (constraintAnnotation != null) {
          layoutAfter(anno, constraintAnnotation, g, x, startAddr, lineHeight);
          constraintAnnotation = anno;
        } else {
          // Defer layout of this annotation until later
          ++deferredIndex;
        }
      }

      newAnnos.add(anno);
    }

    if (firstConstraintAnnotation != null) {
      // Go back and lay out deferred annotations
      for (int i = deferredIndex; i >= 0; i--) {
        Annotation anno = (Annotation) newAnnos.get(i);
        layoutBefore(anno, firstConstraintAnnotation, g, x, startAddr, lineHeight);
        firstConstraintAnnotation = anno;
      }
    } else {
      // Didn't find any overlap between the old and new annotations.
      // Lay out in a feed-forward fashion.
      if (Assert.ASSERTS_ENABLED) {
        Assert.that(constraintAnnotation == null, "logic error in layout code");
      }
      for (Iterator iter = newAnnos.iterator(); iter.hasNext(); ) {
        Annotation anno = (Annotation) iter.next();
        layoutAfter(anno, constraintAnnotation, g, x, startAddr, lineHeight);
        constraintAnnotation = anno;
      }
    }

    visibleAnnotations = newAnnos;
  }

  /** Lays out the given annotation before the optional constraint
      annotation, obeying constraints imposed by that annotation if it
      is specified. */
  private void layoutBefore(Annotation anno, Annotation constraintAnno,
                            Graphics g, int x,
                            Address startAddr, int lineHeight) {
    anno.computeWidthAndHeight(g);
    // Color
    if (constraintAnno != null) {
      anno.setColor(prevColor(constraintAnno.getColor()));
    } else {
      anno.setColor(colors[0]);
    }
    // X
    anno.setX(x);
    // Tentative Y
    anno.setY((int) (((Address) anno.getInterval().getLowEndpoint()).minus(startAddr) * lineHeight / addressSize) +
              (5 * lineHeight / 6));
    // See whether Y overlaps with last anno's Y; if so, move this one up
    if ((constraintAnno != null) && (anno.getY() + anno.getHeight() > constraintAnno.getY())) {
      anno.setY(constraintAnno.getY() - anno.getHeight());
    }
  }

  /** Lays out the given annotation after the optional constraint
      annotation, obeying constraints imposed by that annotation if it
      is specified. */
  private void layoutAfter(Annotation anno, Annotation constraintAnno,
                           Graphics g, int x,
                           Address startAddr, int lineHeight) {
    anno.computeWidthAndHeight(g);
    // Color
    if (constraintAnno != null) {
      anno.setColor(nextColor(constraintAnno.getColor()));
    } else {
      anno.setColor(colors[0]);
    }
    // X
    anno.setX(x);
    // Tentative Y
    anno.setY((int) (((Address) anno.getInterval().getLowEndpoint()).minus(startAddr) * lineHeight / addressSize) +
              (5 * lineHeight / 6));
    // See whether Y overlaps with last anno's Y; if so, move this one down
    if ((constraintAnno != null) && (anno.getY() < (constraintAnno.getY() + constraintAnno.getHeight()))) {
      anno.setY(constraintAnno.getY() + constraintAnno.getHeight());
    }
  }

  /** Returns previous color in our color palette */
  private Color prevColor(Color c) {
    int i = findColorIndex(c);
    if (i == 0) {
      return colors[colors.length - 1];
    } else {
      return colors[i - 1];
    }
  }

  /** Returns next color in our color palette */
  private Color nextColor(Color c) {
    return colors[(findColorIndex(c) + 1) % colors.length];
  }

  private int findColorIndex(Color c) {
    for (int i = 0; i < colors.length; i++) {
      if (colors[i] == c) {
        return i;
      }
    }
    throw new IllegalArgumentException();
  }

  public static void main(String[] args) {
    JFrame frame = new JFrame();
    DummyDebugger debugger = new DummyDebugger(new MachineDescriptionIntelX86());
    AnnotatedMemoryPanel anno = new AnnotatedMemoryPanel(debugger);
    frame.getContentPane().add(anno);
    anno.addAnnotation(new Annotation(debugger.parseAddress("0x80000000"),
                                      debugger.parseAddress("0x80000040"),
                                      "Stack Frame for \"foo\""));
    anno.addAnnotation(new Annotation(debugger.parseAddress("0x80000010"),
                                      debugger.parseAddress("0x80000020"),
                                      "Locals for \"foo\""));
    anno.addAnnotation(new Annotation(debugger.parseAddress("0x80000020"),
                                      debugger.parseAddress("0x80000030"),
                                      "Expression stack for \"foo\""));

    frame.setSize(400, 300);
    frame.addWindowListener(new WindowAdapter() {
        public void windowClosed(WindowEvent e) {
          System.exit(0);
        }
        public void windowClosing(WindowEvent e) {
          System.exit(0);
        }
      });
    frame.setVisible(true);
  }
}
