/**
 * MapGenerator Sample Extensions
 */
package mycompany.graphics.shapes.simple;

import java.awt.Color;
import java.awt.Font;
import java.awt.Graphics2D;
import java.awt.Paint;
import java.awt.Shape;
import java.awt.font.GlyphVector;
import java.awt.geom.AffineTransform;

import org.w3c.dom.Element;

import idea.geographic.coordsys.orthogonal2d.CartesianGeoPosition;
import idea.geometry.CartesianPosition;
import idea.graphics.map.GeographicImageMap.ImageMapParameters;
import idea.graphics.shapes.simple.SimpleSolidShape;
import idea.map.runset.CreateXmlBeanException;
import idea.map.runset.XmlBeanFactory;
import idea.mapgen.editor.Property;
import idea.mapgen.editor.XmlBean;


/**
 * Text with shadow shape
 * 
 * @author Lumir Vanek, vanek@idea-envi.cz
 *
 */
@XmlBean(icon="TextWithShadow.png")
public class TextWithShadow extends SimpleSolidShape 
{
	/**
	 * The position (x, y) in pixels
	 */
	private final CartesianPosition cartesianPosition;
	
	/**
	 * Text
	 */
	@Property(name="text", mandatory=true)
	private final String text;
	
	/**
	 * Font for drawing text
	 */
	@Property(name="font", mandatory=false)
	private final Font font;
		
	/**
	 * Constructor
	 * 
	 * @param cartesianPosition The position (x, y) in pixels
	 * @param text The text
	 */
	public TextWithShadow(CartesianPosition cartesianPosition, String text)
	{
		super();
		this.cartesianPosition = cartesianPosition;
		this.text = text;
		this.font = null;
	}
	
	/**
	 * Constructor
	 * 
	 * @param cartesianPosition The position (x, y) in pixels
	 * @param text The text
	 * @param font Font for text
	 */
	public TextWithShadow(CartesianPosition cartesianPosition, String text, Font font)
	{
		super();
		this.cartesianPosition = cartesianPosition;
		this.text = text;
		this.font = font;
	}
	
	/**
	 * Constructor
	 * 
	 * @param cartesianPosition The position (x, y) in pixels
	 * @param text The text
	 * @param font Font for text
	 * @param drawColor Shape color for drawing shape outline
	 * @param fillColor Shape color for drawing shape solid 
	 * @param lineWidth Line width 
	 */
	public TextWithShadow(CartesianPosition cartesianPosition, String text, Font font, Color drawColor, Color fillColor, Float lineWidth)
	{
		super(lineWidth, drawColor, fillColor);
		this.cartesianPosition = cartesianPosition;
		this.text = text;
		this.font = font;
	}
	
	/**
	 * XML Runset constructor, initialize yourself from given DOM element
	 * 
	 * @param domElement DOM element
 	 * @param factory  Factory, that create beans
 	 * @throws CreateXmlBeanException When dynamic creation using class loader fails 
	 */
	public TextWithShadow(Element domElement, XmlBeanFactory factory) throws CreateXmlBeanException
	{
		super(domElement);
		
		if(!domElement.hasAttribute("text"))
		{
			throw new RuntimeException("Missing text attribute for " + getXmlElementName());
		}
		
		text = domElement.getAttribute("text");
				
		font = createFont(domElement);
		
		cartesianPosition = createPosition(domElement, "position", factory);
	}
	
	/**
	 * Constructor
	 * 
	 * @param position The Cartesian position (x, y)
	 * @param text The text
	 * @param mapParameters General parameters of the image map
	 */
	public TextWithShadow(CartesianGeoPosition position, String text, ImageMapParameters mapParameters)
	{
		this(position.convertToPixels(mapParameters), text);
	}

	/**
	 * @return The position (x, y) in pixels
	 */
	public CartesianPosition getPosition() {
		return cartesianPosition;
	}
	
	/**
	 * @return The text
	 */
	public String getText() {
		return text;
	}

	/**
	 * @return the Font for drawing text
	 */
	public Font getFont() {
		return font;
	}
	
	/**
	 * Draw the shape to given graphics
	 * 
	 * @param graphics Graphics to draw
	 */
	public void draw(Graphics2D graphics)
	{
		if(!isRendered()) return;
		
		super.draw(graphics);
		
		if(font != null)
		{
			graphics.setFont(font);
		}
										
		GlyphVector gv = graphics.getFont().createGlyphVector(graphics.getFontRenderContext(), text);
			    
		// We're going to fake shadows for the letters using the
	    // following Paint and AffineTransform objects
	    Paint shadowPaint = new Color(0, 0, 0, 100); // Translucent black
	    AffineTransform shadowTransform = AffineTransform.getShearInstance(-1.0, 0.0); // Shear to the right
	    shadowTransform.scale(1.0, 0.5); // Scale height by 1/2
	    
	    
	    graphics.translate(cartesianPosition.getX(), cartesianPosition.getY()); // Compensate for the descender of the J
	    	    
		for(int i = 0; i < text.length(); i++)
		{
			Shape shape = gv.getGlyphOutline(i); // Shape of letter text[i]
			
		    // Draw the shadow of the shape
			graphics.setPaint(shadowPaint);
			
			// transform letter into the shape of its shadow, and fill it
			graphics.fill(shadowTransform.createTransformedShape(shape));
			
			graphics.setPaint(getFillColor()); // Fill letter with solid
			graphics.fill(shape); // Fill the shape
			
			graphics.setPaint(getDrawColor()); // Switch to fill color
			graphics.draw(shape); // And draw the outline of the letter
			
		}
		
		graphics.translate(- cartesianPosition.getX(), -cartesianPosition.getY()); // Undo the translation above
	}
}