package eu.greenlightning.hypercubepdf.text;

import java.awt.Color;
import java.io.IOException;
import java.util.Objects;

import org.apache.pdfbox.pdmodel.common.PDRectangle;
import org.apache.pdfbox.pdmodel.edit.PDPageContentStream;

import eu.greenlightning.hypercubepdf.HCPElement;

public abstract class HCPAbstractText implements HCPElement {

	private static final boolean DEBUG = false;

	protected final String text;
	protected final HCPStyle style;

	public HCPAbstractText(String text, HCPStyle style) {
		this.text = Objects.requireNonNull(text, "Text must not be null.");
		this.style = Objects.requireNonNull(style, "Style must not be null.");
	}

	@Override
	public final void paint(PDPageContentStream content, PDRectangle shape) throws IOException {
		float x = shape.getLowerLeftX() + (shape.getWidth() - getWidth()) / 2;
		float y = shape.getLowerLeftY() + (shape.getHeight() - getHeight()) / 2;
		paintDebug(content, x, y);
		paintText(content, x, y);
	}

	private void paintDebug(PDPageContentStream content, float x, float y) throws IOException {
		if (DEBUG) {
			content.setNonStrokingColor(invert(style.getColor()));
			content.fillRect(x, y, getWidth(), getHeight());
		}
	}

	private Color invert(Color color) {
		Color result = new Color(255 - color.getRed(), 255 - color.getGreen(), 255 - color.getBlue());
		if (inRange(result, 120, 128))
			return result.darker();
		if (inRange(result, 128, 136))
			return result.brighter();
		return result;
	}

	private boolean inRange(Color color, int start, int end) {
		return inRange(color.getRed(), start, end) && inRange(color.getGreen(), start, end)
				&& inRange(color.getBlue(), start, end);
	}

	private boolean inRange(int value, int start, int end) {
		return value >= start && value < end;
	}

	protected abstract void paintText(PDPageContentStream content, float x, float y) throws IOException;

}

@@ -285,180 +285,777 @@
 t;%0A%0A
-public abstract class HCPAbstractText implements HCPElement %7B%0A%0A%09private static final boolean DEBUG = false;%0A%0A%09protected final String text;%0A%09protected final HCPStyle style;%0A
+/**%0A * Base class for text elements. The text is always painted in the center of the element.%0A * %3Cp%3E%0A * This class is immutable.%0A *%0A * @author Green Lightning%0A */%0Apublic abstract class HCPAbstractText implements HCPElement %7B%0A%0A%09private static final boolean DEBUG = false;%0A%0A%09/**%0A%09 * The text that this text element should paint. May include line breaks. This field is never %7B@code null%7D.%0A%09 */%0A%09protected final String text;%0A%0A%09/**%0A%09 * The style to use for painting. This field is never %7B@code null%7D.%0A%09 */%0A%09protected final HCPStyle style;%0A%0A%09/**%0A%09 * Creates a new %7B@link HCPAbstractText%7D instance using the specified text and style.%0A%09 * %0A%09 * @param text not %7B@code null%7D%0A%09 * @param style not %7B@code null%7D%0A%09 * @throws NullPointerException if text or style is %7B@code null%7D%0A%09 */
 %0A%09pu
@@ -2219,13 +2219,9 @@
 end)
-%0A%09%09%09%09
+ 
 && i
@@ -2243,17 +2243,20 @@
 tBlue(),
- 
+%0A%09%09%09
 start, e
@@ -2366,16 +2366,267 @@
 nd;%0A%09%7D%0A%0A
+%09/**%0A%09 * Paints the text of this element at the specified position.%0A%09 * %0A%09 * @param content not %7B@code null%7D%0A%09 * @param x the x position to use%0A%09 * @param y the y position to use%0A%09 * @throws IOException if there is an error writing to the stream%0A%09 */%0A
 %09protect

Document HCPAbstractText.