/*
 *
 *  Licensed to the Apache Software Foundation (ASF) under one or more
 *  contributor license agreements.  See the NOTICE file distributed with
 *  this work for additional information regarding copyright ownership.
 *  The ASF licenses this file to You under the Apache License, Version 2.0
 *  (the "License"); you may not use this file except in compliance with
 *  the License.  You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 *  Unless required by applicable law or agreed to in writing, software
 *  distributed under the License is distributed on an "AS IS" BASIS,
 *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 *  See the License for the specific language governing permissions and
 *  limitations under the License.
 *
 */

package flash.graphics.g2d;

import flash.swf.tags.DefineShape;
import flash.swf.tags.PlaceObject;
import flash.swf.tags.DefineSprite;
import flash.swf.tags.DefineBits;
import flash.swf.tags.DefineBitsLossless;
import flash.swf.builder.tags.DefineShapeBuilder;
import flash.swf.builder.tags.DefineBitsLosslessBuilder;
import flash.swf.builder.tags.DefineBitsBuilder;
import flash.swf.builder.tags.ImageShapeBuilder;
import flash.swf.builder.types.MatrixBuilder;
import flash.swf.types.TagList;
import flash.swf.types.Rect;
import flash.swf.types.Matrix;
import flash.swf.Tag;
import flash.graphics.images.LosslessImage;
import flash.graphics.images.JPEGImage;

import java.awt.Shape;
import java.awt.Graphics;
import java.awt.Image;
import java.awt.Paint;
import java.awt.GradientPaint;
import java.awt.image.ImageObserver;
import java.awt.geom.AffineTransform;
import java.awt.geom.Point2D;
import java.awt.geom.Rectangle2D;
import java.io.InputStream;
import java.io.IOException;

/**
 * A SWF specific implementation of Java2D's <code>Graphics2D</code>
 * API. Calls to this class are converted into a <code>TagList</code>
 * that can be used to construct a SWF Sprite.
 */
public class SpriteGraphics2D extends AbstractGraphics2D
{
	/**
	 * Constructor.
	 * Initializes a new GraphicContext and TagList.
	 *
	 * @param width
	 * @param height
	 */
	public SpriteGraphics2D(int width, int height)
	{
		super(new GraphicContext(width, height));
		this.width = width;
		this.height = height;
		init();
	}

	/**
	 * Optimized Constructor.
	 * Initializes a smaller GraphicContext and TagList, without FontMetrics support.
	 */
	public SpriteGraphics2D()
	{
		super(new GraphicContext());
		init();
	}

	private void init()
	{
		defineTags = new TagList();
		graphicContext.validateTransformStack();
		bounds = new Rect();
	}

	/**
	 * Private Constructor - used by create().
	 * @param swf2d
	 * @see #create()
	 */
	private SpriteGraphics2D(SpriteGraphics2D swf2d)
	{
		super((GraphicContext)swf2d.graphicContext.clone());
		bounds = new Rect();
		defineTags = swf2d.getTags();
	}

	/**
	 * Draws only the outline of an AWT Shape in SWF vectors using the settings of the
	 * current graphics context and places it on the SWF display list. The current
	 * stroke and paint colors are used to render the shape.
	 * @param shape the shape to be drawn
	 * @see java.awt.Graphics2D#draw(java.awt.Shape)
	 */
	public void draw(Shape shape)
	{
		defineShape(shape, true, false);
	}

	/**
	 * Draws only the center of a closed AWT shape in SWF vectors using the settings of the
	 * current graphic context and places it on the SWF display list. The current paint
	 * is used to render the shape.
	 * @param shape
	 * @see java.awt.Graphics2D#fill(java.awt.Shape)
	 */
	public void fill(Shape shape)
	{
		defineShape(shape, false, true);
	}

	/**
	 * This method converts an AWT Shape into a SWF Shape and creates a DefineShape3 instance
	 * with an accompanying PlaceObject2 instance.
	 * <p>
	 * Two non-standard operations are performed to work around unavoidable issues. The first
	 * is to apply the current AffineTransform before rendering and moving the drawing pen
	 * origin to the first move command's location. The shape is correctly translated
	 * to its intended location on the client by using the PlaceObject2's matrix.
	 * </p>
	 * <p>
	 * The second issue is to deal with the incompatibility of SVGs viewport dimensions and
	 * SWF Sprite auto-scaling. We have to keep track of the minimum area required to contain
	 * the sprites manually, as using the viewport dimensions will produce unexpected scaling
	 * for developers.
	 * </p>
	 * @param shape
	 * @param draw
	 * @param fill
	 */
	private void defineShape(Shape shape, boolean draw, boolean fill)
	{
		Point2D oldPen = null;
		boolean isGradient = false;

		if (fill && isGradientFill(graphicContext.getPaint()))
			isGradient = true;

		if (isGradient)
		{
			shape = graphicContext.getTransform().createTransformedShape(shape);
			oldPen = graphicContext.setPen(getShapeStart(shape));
		}

		DefineShapeBuilder builder = new DefineShapeBuilder(shape, graphicContext, draw, fill);

		DefineShape ds3 = (DefineShape)builder.build();
		defineTags.defineShape3(ds3);

		Matrix matrix;

		if (isGradient)
		{
			double originX = graphicContext.getPen().getX();
			double originY = graphicContext.getPen().getY();
			matrix = MatrixBuilder.getTranslateInstance(originX, originY);
		}
		else
		{
		 	matrix = MatrixBuilder.build(graphicContext.getTransform());
		}

		applyBounds(ds3.bounds.xMin + matrix.translateX,
				ds3.bounds.yMin + matrix.translateY,
				ds3.bounds.xMax + matrix.translateX,
				ds3.bounds.yMax + matrix.translateY);

		PlaceObject po2 = new PlaceObject(Tag.stagPlaceObject2);
		po2.setMatrix(matrix);
		po2.setRef(ds3);
        po2.depth = depth++;

		if (isGradient)
			graphicContext.setPen(oldPen);

		defineTags.placeObject2(po2);
	}

	/**
	 * <b style="color:orange">NOT YET IMPLEMENTED AS DEFINED BELOW, CURRENTLY USING drawStringAsShape()</b><br />
	 * Renders the text specified as a series of SWF character glyphs,
	 * using the current graphic context to control anti-aliasing and color.
	 * Unique glyphs are stored in a SWF font definition, and the defined text
	 * references this by index.
	 * <p>
	 * The baseline of the first character is at position (<i>x</i>, <i>y</i>)
	 * in the User Space.
	 * </p>
	 * @param str the text to be rendered
	 * @param x baseline x co-ordinate
	 * @param y baseline y co-ordinate
	 * @see java.awt.Graphics2D#drawString(java.lang.String, float, float)
	 */
	public void drawString(String str, float x, float y)
	{
		drawStringAsShape(str, x, y);
	}

	public void drawString(String str, int x, int y)
	{
		super.drawString(str, x, y);
	}

	public boolean drawImage(Image image, AffineTransform at, ImageObserver obs)
	{
		if (image != null)
		{
		    LosslessImage losslessImage = new LosslessImage(image);
		    int width = losslessImage.getWidth();
		    int height = losslessImage.getHeight();
			DefineBitsLossless defineBits = DefineBitsLosslessBuilder.build(losslessImage.getPixels(), width, height);
			defineTags.defineBitsLossless2(defineBits);

			DefineShape ds3 = ImageShapeBuilder.buildImage(defineBits, defineBits.width, defineBits.height);
			defineTags.defineShape3(ds3);
			applyBounds(ds3.bounds.xMin, ds3.bounds.yMin, ds3.bounds.xMax, ds3.bounds.yMax);

			PlaceObject po2 = new PlaceObject(Tag.stagPlaceObject2);
			po2.setMatrix(MatrixBuilder.build(at));
			po2.setRef(ds3);
			po2.depth = depth++;

			defineTags.placeObject2(po2);
		}

		return false;
	}

	public boolean drawImage(Image image, int x, int y, ImageObserver observer)
	{
		AffineTransform at = graphicContext.getTransform();
		at.translate(x, y);
		return drawImage(image, at, observer);
	}

	public boolean drawImage(Image image, int x, int y, int width, int height, ImageObserver observer)
	{
		AffineTransform at = graphicContext.getTransform();
		at.translate(x, y);
		double sx = (double)width/(double)image.getWidth(observer);
		double sy = (double)height/(double)image.getHeight(observer);
		at.scale(sx, sy);
		return drawImage(image, at, observer);
	}

    /**
	 * Converts an AWT image into a SWF <code>DefineBitsLossless</code> tag and adds it to
	 * the Sprite <code>TagList</code> context.
	 *
	 * @param image - an AWT bitmapped image
	 * @param name - name to use in the corresponding <code>PlaceObject</code> tag
	 */
	public void drawNamedImage(Image image, String name)
	{
		if (image != null)
		{
            LosslessImage losslessImage = new LosslessImage(image);
            int width = losslessImage.getWidth();
            int height = losslessImage.getHeight();
            DefineBitsLossless defineBits = DefineBitsLosslessBuilder.build(losslessImage.getPixels(), width, height);
			defineTags.defineBitsLossless2(defineBits);

			DefineShape ds3 = ImageShapeBuilder.buildImage(defineBits, defineBits.width, defineBits.height);
			defineTags.defineShape3(ds3);
            applyBounds(ds3.bounds.xMin, ds3.bounds.yMin, ds3.bounds.xMax, ds3.bounds.yMax);

			PlaceObject po2 = new PlaceObject(ds3, depth++);
            po2.setMatrix(MatrixBuilder.build(graphicContext.getTransform()));
            po2.setName(name);

			defineTags.placeObject2(po2);
		}
	}


	/**
	 * Converts a JPEG binary input stream into a SWF <code>DefineBits</code> tag and adds it
	 * to the Sprite <code>TagList</code> context.
	 *
	 * @param inputStream - the raw JPEG binary stream
	 * @param length - number of bits to read from the stream
	 * @param width - width of the JPEG image in pixels
	 * @param height - height of the JPEG image in pixels
	 * @param name - name to use in the corresponding <code>PlaceObject</code> tag
	 * @throws IOException
	 */
	public void drawJPEG(InputStream inputStream, int length, int width, int height, String name) throws IOException
	{
        if (inputStream != null)
		{
			try
			{
                JPEGImage image = new JPEGImage(inputStream, length);
                DefineBits defineBits = new DefineBits(Tag.stagDefineBitsJPEG2);
                defineBits.data = image.getData();
				defineTags.defineBitsJPEG2(defineBits);

				DefineShape ds3 = ImageShapeBuilder.buildImage(defineBits, width, height);
				defineTags.defineShape3(ds3);
				applyBounds(ds3.bounds.xMin, ds3.bounds.yMin, ds3.bounds.xMax, ds3.bounds.yMax);

                PlaceObject po2 = new PlaceObject(ds3, depth++);
                po2.setMatrix(MatrixBuilder.build(graphicContext.getTransform()));
                po2.setName(name);

				defineTags.placeObject2(po2);
			}
			finally
			{
				try
				{
					inputStream.close();
				}
				catch (IOException e)
				{
				}
			}
		}
	}

	/**
	 * Creates a new <code>Graphics</code> object that is a copy of
	 * this <code>SpriteGraphics2D</code> object.
	 * @return a copy of this Graphics2D instance
	 */
	public Graphics create()
	{
		return new SpriteGraphics2D(this);
	}

	public TagList getTags()
	{
		return defineTags;
	}

	public int getWidth()
	{
		return width;
	}

	public int getHeight()
	{
		return height;
	}

	public DefineSprite defineSprite(String name)
	{
		DefineSprite defineSprite = new DefineSprite();
		defineSprite.framecount = 1;
		defineSprite.tagList = defineTags;
		defineSprite.name = name;
		return defineSprite;
	}

	private static boolean isGradientFill(Paint paint)
	{
		return (paint != null
				&& (paint instanceof GradientPaint
						|| paint.getClass().getName().equals("org.apache.flex.forks.batik.ext.awt.MultipleGradientPaint")));
	}

	/**
	 * When trying to negate gradient dilution in filled SWF shapes, it is useful to
	 * know where the left most point of the physical shape as this can be used to change
	 * the drawing origin to minimize non-drawing move commands contributing to the
	 * shape bounds.
	 *
	 * @param shape
	 * @return Point2D the minimum x,y position of this shape's bounds.
	 */
	private static Point2D getShapeStart(Shape shape)
	{
		if (shape != null)
		{
			Rectangle2D bounds = shape.getBounds2D();
			return new Point2D.Double(bounds.getMinX(), bounds.getMinY());
		}

		return new Point2D.Double(0, 0);
	}

	private void applyBounds(int x1, int y1, int x2, int y2)
	{
		if (x1 < bounds.xMin) bounds.xMin = x1;
		if (y1 < bounds.yMin) bounds.yMin = y1;
		if (x1 > bounds.xMax) bounds.xMax = x1;
		if (y1 > bounds.yMax) bounds.yMax = y1;
		if (x2 < bounds.xMin) bounds.xMin = x2;
		if (y2 < bounds.yMin) bounds.yMin = y2;
		if (x2 > bounds.xMax) bounds.xMax = x2;
		if (y2 > bounds.yMax) bounds.yMax = y2;
	}

	public Rect getBounds()
	{
		return bounds;
	}

	protected TagList defineTags;
	protected int depth = 1;
	protected int width;
	protected int height;
	protected Rect bounds;
}
