package de.woerteler.tree;

import java.awt.Font;
import java.awt.FontMetrics;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.RenderingHints;
import java.awt.geom.Rectangle2D;
import java.awt.image.BufferedImage;

import de.woerteler.charty.ChartParser.Edge;
import de.woerteler.charty.DisplayMethod;
import de.woerteler.tree.render.DefaultRenderer;
import de.woerteler.tree.render.NodeRenderer;

/**
 * Generates a graphical representation of a syntax tree via direct drawing.
 *
 * @author Joschi
 */
public class ImageDisplay implements DisplayMethod {

  /**
   * The renderer that is used to draw the tree.
   */
  public static NodeRenderer RENDERER = new DefaultRenderer();

  /**
   * The font to draw the labels or <code>null</code> if the default font should
   * be used.
   */
  public static Font FONT = Font.decode("times new roman BOLD 12");

  @Override
  public BufferedImage getImage(final Edge e) throws Exception {
    final Node n = generateNodeStructure(e);
    final Rectangle2D bbox = n.getBoundingBox();
    final BufferedImage img = new BufferedImage(
        (int) Math.ceil(bbox.getWidth()) + 1,
        (int) Math.ceil(bbox.getHeight()) + 1, BufferedImage.TYPE_INT_ARGB);
    final Graphics2D gfx = (Graphics2D) img.getGraphics();
    gfx.setRenderingHint(RenderingHints.KEY_ANTIALIASING,
        RenderingHints.VALUE_ANTIALIAS_ON);
    if(FONT != null) {
      gfx.setFont(FONT);
    }
    gfx.translate(-bbox.getMinX(), -bbox.getMinY());
    n.draw(gfx, RENDERER);
    gfx.dispose();
    return img;
  }

  /**
   * Builds a {@link Node} structure out of syntax tree edges.
   *
   * @param e The root node.
   * @return A draw-able node structure.
   */
  protected Node generateNodeStructure(final Edge e) {
    // generate a dummy image to get the font metrics of the font
    final BufferedImage dummy = new BufferedImage(1, 1,
        BufferedImage.TYPE_INT_ARGB);
    final Graphics dummyGfx = dummy.getGraphics();
    if(FONT != null) {
      dummyGfx.setFont(FONT);
    }
    final FontMetrics fm = dummyGfx.getFontMetrics();
    final Node n = generateNodeStructure(e, null, fm);
    dummyGfx.dispose();
    dummy.flush();
    return n;
  }

  /**
   * Builds a {@link Node} structure out of parts of a syntax tree.
   *
   * @param e A syntax tree node.
   * @param parent The parent of the current node.
   * @param fm The font metrics for displaying the labels correctly.
   * @return The node structure.
   */
  private Node generateNodeStructure(final Edge e, final Node parent,
      final FontMetrics fm) {
    final Node n = Node.createNode(parent, e.lhs, fm);
    if(e.hasRealChildren()) {
      for(final Edge c : e) {
        final Node nc = generateNodeStructure(c, n, fm);
        n.addChild(nc);
      }
    } else {
      for(final String label : e.rhs) {
        n.addChild(Node.createNode(n, label, fm));
      }
    }
    return n;
  }

}

@@ -663,24 +663,24 @@
 enderer 
-RENDERER
+renderer
  = new D
@@ -826,20 +826,20 @@
 ic Font 
-FONT
+font
  = Font.
@@ -1377,36 +1377,36 @@
 IAS_ON);%0A    if(
-FONT
+font
  != null) %7B%0A    
@@ -1411,36 +1411,36 @@
     gfx.setFont(
-FONT
+font
 );%0A    %7D%0A    gfx
@@ -1505,16 +1505,16 @@
 fx, 
-RENDERER
+renderer
 );%0A 
@@ -1975,20 +1975,20 @@
 %0A    if(
-FONT
+font
  != null
@@ -2018,12 +2018,12 @@
 ont(
-FONT
+font
 );%0A 

correct static naming