package com.pump.graphics.vector;

import java.awt.Graphics2D;
import java.awt.Shape;
import java.awt.font.TextLayout;
import java.awt.geom.Rectangle2D;
import java.io.IOException;
import java.text.AttributedCharacterIterator;
import java.util.Objects;

import com.pump.graphics.Graphics2DContext;

/**
 * This is an Operation for
 * {@link java.awt.Graphics2D#drawString(AttributedCharacterIterator, float, float)}
 * and
 * {@link java.awt.Graphics2D#drawString(AttributedCharacterIterator, int, int)}.
 * <p>
 * If you don't want to support AttributedCharacterIterators, you can replace a
 * call to <code>myGraphics.drawString(aci, x, y)</code> with: <br>
 * <code>
 * TextLayout layout = new TextLayout(aci, myGraphics.getFontRenderContext());
 * layout.draw(myGraphics, x, y);
 * </code> <br>
 * (... this ultimately calls <code>myGraphics.drawGlyphVector(..)</code>.)
 */
public class AttributedCharacterIteratorOperation extends Operation {
	private static final long serialVersionUID = 1L;

	protected static final String PROPERTY_ITERATOR = "iterator";
	protected static final String PROPERTY_X = "x";
	protected static final String PROPERTY_Y = "y";

	public AttributedCharacterIteratorOperation(Graphics2DContext context,
			AttributedCharacterIterator iter, float x, float y) {
		super(context);
		setAttributedCharacterIterator(iter);
		setX(x);
		setY(y);
	}

	/**
	 * Return the x-coordinate to draw the AttributedCharacterIterator at.
	 */
	public float getX() {
		return ((Number) coreProperties.get(PROPERTY_X)).floatValue();
	}

	/**
	 * Return the y-coordinate to draw the AttributedCharacterIterator at.
	 */
	public float getY() {
		return ((Number) coreProperties.get(PROPERTY_Y)).floatValue();
	}

	/**
	 * Assign the x-coordinate to draw the AttributedCharacterIterator at.
	 */
	public void setX(float x) {
		coreProperties.put(PROPERTY_X, x);
	}

	/**
	 * Assign the x-coordinate to draw the AttributedCharacterIterator at.
	 */
	public void setY(float y) {
		coreProperties.put(PROPERTY_Y, y);
	}

	/**
	 * Return the AttributedCharacterIterator to render.
	 */
	public AttributedCharacterIterator getAttributedCharacterIterator() {
		return (AttributedCharacterIterator) coreProperties
				.get(PROPERTY_ITERATOR);
	}

	/**
	 * Assign the AttributedCharacterIterator to render.
	 */
	public void setAttributedCharacterIterator(
			AttributedCharacterIterator iter) {
		Objects.requireNonNull(iter);
		coreProperties.put(PROPERTY_ITERATOR, iter);
	}

	@Override
	protected void paintOperation(Graphics2D g) {
		g.drawString(getAttributedCharacterIterator(), getX(), getY());
	}

	@Override
	public Shape getUnclippedOutline() {
		TextLayout layout = new TextLayout(getAttributedCharacterIterator(),
				getContext().getFontRenderContext());
		Rectangle2D bounds = layout.getBounds();
		bounds.setFrame(bounds.getX() + getX(), bounds.getY() + getY(),
				bounds.getWidth(), bounds.getHeight());
		return bounds;
	}

	private void writeObject(java.io.ObjectOutputStream out)
			throws IOException {
		out.writeInt(0);
	}

	private void readObject(java.io.ObjectInputStream in)
			throws IOException, ClassNotFoundException {
		int version = in.readInt();
		if (version == 0) {
			// do nothing
		} else {
			throw new IOException("unsupported internal version " + version);
		}
	}

}