package org.workcraft.dom.visual;

import org.workcraft.plugins.builtin.settings.VisualCommonSettings;

import java.awt.*;
import java.awt.font.FontRenderContext;
import java.awt.font.GlyphVector;
import java.awt.geom.AffineTransform;
import java.awt.geom.Point2D;
import java.awt.geom.Rectangle2D;
import java.util.LinkedList;

public class RenderedText {
    private final double spacingRatio = VisualCommonSettings.getLineSpacing();
    private final String text;
    private final Font font;
    private final Positioning positioning;
    private final double xOffset;
    private final double yOffset;
    private final LinkedList<GlyphVector> glyphVectors;
    private final Rectangle2D boundingBox;
    private final double spacing;

    public RenderedText(String text, Font font, Positioning positioning, Point2D offset) {
        this.text = text;
        this.font = font;
        this.positioning = positioning;
        this.xOffset = offset.getX();
        this.yOffset = offset.getY();

        Rectangle2D textBounds = null;
        glyphVectors = new LinkedList<>();
        String[] lines = {""};
        if (text != null) {
            lines = text.split("\\|");
        }
        for (String line : lines) {
            final FontRenderContext context = new FontRenderContext(AffineTransform.getScaleInstance(1000.0, 1000.0), true, true);
            final GlyphVector glyphVector = font.createGlyphVector(context, line.trim());
            glyphVectors.add(glyphVector);
            Rectangle2D lineBounds = glyphVector.getVisualBounds();
            if (textBounds != null) {
                textBounds = BoundingBoxHelper.move(textBounds, 0.0, -lineBounds.getHeight());
            }
            textBounds = BoundingBoxHelper.union(textBounds, lineBounds);
        }
        if (textBounds == null) {
            textBounds = new Rectangle2D.Double(0.0, 0.0, 0.0, 0.0);
        }
        int lineCount = lines.length;
        spacing = (lineCount < 2) ? 0.0 : (spacingRatio * textBounds.getHeight() / (lineCount - 1));
        textBounds = BoundingBoxHelper.transform(textBounds, AffineTransform.getScaleInstance(1.0, 1.0 + spacingRatio));
        double x = xOffset + positioning.xOffset + 0.5 * positioning.xSign * textBounds.getWidth() - textBounds.getCenterX();
        double y = yOffset + positioning.yOffset + 0.5 * positioning.ySign * textBounds.getHeight() - textBounds.getCenterY();
        boundingBox = BoundingBoxHelper.move(textBounds, x, y);
    }

    public boolean isDifferent(String text, Font font, Positioning positioning, Point2D offset) {
        if (text == null) {
            text = "";
        }
        return !text.equals(this.text) || !font.equals(this.font) || positioning != this.positioning
                || offset.getX() != this.xOffset || offset.getY() != this.yOffset;
    }

    public void draw(Graphics2D g) {
        draw(g, Alignment.LEFT);
    }

    public void draw(Graphics2D g, Alignment alignment) {
        g.setFont(font);
        float y = (float) boundingBox.getMinY();
        for (GlyphVector glyphVector: glyphVectors) {
            final Rectangle2D lineBoundingBox = glyphVector.getVisualBounds();
            double xMargin = 0.0;
            switch (alignment) {
            case CENTER :
                xMargin = (boundingBox.getWidth() - lineBoundingBox.getWidth()) / 2.0;
                break;
            case RIGHT:
                xMargin = boundingBox.getWidth() - lineBoundingBox.getWidth();
                break;
            default:
                xMargin = 0.0;
                break;
            }
            double x = boundingBox.getX() - lineBoundingBox.getX() + xMargin * (1.0 - positioning.xSign);
            y += lineBoundingBox.getHeight();
            g.drawGlyphVector(glyphVector, (float) x, y);
            y += spacing;
        }
    }

    public boolean hitTest(Point2D point) {
        return boundingBox.contains(point);
    }

    public Rectangle2D getBoundingBox() {
        return boundingBox;
    }

    public boolean isEmpty() {
        return (text == null) || text.isEmpty();
    }

}

@@ -350,16 +350,17 @@
 dText %7B%0A
+%0A
     priv
@@ -355,32 +355,39 @@
  %7B%0A%0A    private 
+static 
 final double spa
@@ -387,61 +387,32 @@
 ble 
-spacingRatio = VisualCommonSettings.getLineSpacing();
+MIN_LINE_HEIGHT = 0.35;%0A
 %0A   
@@ -1493,20 +1493,17 @@
 D lineBo
-unds
+x
  = glyph
@@ -1636,26 +1636,32 @@
 , 0.0, -
+Math.max(
 lineBo
-unds
+x
 .getHeig
@@ -1664,16 +1664,34 @@
 Height()
+, MIN_LINE_HEIGHT)
 );%0A     
@@ -1766,20 +1766,17 @@
 , lineBo
-unds
+x
 );%0A     
@@ -1931,16 +1931,85 @@
 length;%0A
+        double spacingRatio = VisualCommonSettings.getLineSpacing();%0A
         
@@ -3141,16 +3141,17 @@
 phVector
+ 
 : glyphV
@@ -3196,24 +3196,16 @@
 D lineBo
-undingBo
 x = glyp
@@ -3249,38 +3249,32 @@
   double xMargin
- = 0.0
 ;%0A            sw
@@ -3372,32 +3372,24 @@
 h() - lineBo
-undingBo
 x.getWidth()
@@ -3497,32 +3497,24 @@
 h() - lineBo
-undingBo
 x.getWidth()
@@ -3673,32 +3673,24 @@
 X() - lineBo
-undingBo
 x.getX() + x
@@ -3746,20 +3746,21 @@
  += 
-lineBounding
+Math.max(line
 Box.
@@ -3770,16 +3770,34 @@
 Height()
+, MIN_LINE_HEIGHT)
 ;%0A      

Use min line height in rendering of comments