/*
 *
 *  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 org.apache.flex.forks.batik.ext.awt.g2d.TransformStackElement;
import org.apache.flex.forks.batik.ext.awt.RenderingHintsKeyExt;

import java.awt.*;
import java.awt.font.FontRenderContext;
import java.awt.geom.AffineTransform;
import java.awt.geom.Area;
import java.awt.geom.GeneralPath;
import java.awt.geom.NoninvertibleTransformException;
import java.awt.geom.Point2D;
import java.awt.image.BufferedImage;
import java.awt.image.ColorModel;
import java.util.Map;
import java.util.Vector;
import java.lang.ref.WeakReference;

/**
 * A modified version of Apache Batik's GraphicsContext, used to store
 * state between successive Graphics2D calls.
 *
 * @version 1.0
 */
public final class GraphicContext implements Cloneable
{
	/**
	 * Call this optimized Constructor for faster instantiation, but without FontMetrics support.
	 */
	public GraphicContext()
	{
		bufferedImage = null;

		init();
	}

	/**
	 * Constructor. Used by clone() too.
	 */
	public GraphicContext(int width, int height)
	{
		this.width = width;
		this.height = height;

		bufferedImage = new BufferedImage(width, height, BufferedImage.TYPE_INT_ARGB);
		bufferedImageGraphics = bufferedImage.createGraphics(); //Keep in sync with current transforms

		hints.put(RenderingHintsKeyExt.KEY_BUFFERED_IMAGE, new WeakReference<BufferedImage>(bufferedImage));

		init();
	}

	private void init()
	{
		// Noted from Apache Batik - supposedly to workaround a JDK bug
		hints.put(RenderingHints.KEY_RENDERING, RenderingHints.VALUE_RENDER_DEFAULT);

		transform = new AffineTransform(defaultTransform);
	}

	/**
	 * Returns the current paint if an instance of <code>Color</code>, otherwise the default paint
	 * is returned, which is <code>Color.black</code>.
	 */
	public Color getColor()
	{
		if (paint instanceof Color)
			return (Color)paint;
		else
			return defaultPaint;
	}

	/**
	 * Returns the current Composite of the graphic context.
	 * @return the Composite
	 */
	public Composite getComposite()
	{
		return composite;
	}

	/**
	 * Sets the <code>Composite</code> for the <code>Graphics2D</code> context.
     * The <code>Composite</code> is used in all drawing methods such as
     * <code>drawImage</code>, <code>drawString</code>, <code>draw</code>,
     * and <code>fill</code>.  It specifies how new pixels are to be combined
     * with the existing pixels on the graphics device during the rendering
     * process.
	 * @param comp
	 */
	public void setComposite(Composite comp)
	{
		this.composite = comp;

		if (bufferedImageGraphics != null)
			bufferedImageGraphics.setComposite(comp);
	}

    /**
	 * Gets the current font of this graphic context.
	 * @return
	 */
	public Font getFont()
	{
		return font;
	}

	public void setFont(Font f)
	{
		if (f == null)
			return;

		this.font = f;

		if (bufferedImageGraphics != null)
			bufferedImageGraphics.setFont(f);
	}

	public FontRenderContext getFontRenderContext()
	{
		// Find if antialiasing should be used.
		Object antialiasingHint = hints.get(RenderingHints.KEY_TEXT_ANTIALIASING);
		boolean isAntialiased = true;
		if (antialiasingHint != RenderingHints.VALUE_TEXT_ANTIALIAS_ON &&
				antialiasingHint != RenderingHints.VALUE_TEXT_ANTIALIAS_DEFAULT)
		{

			// If antialias was not turned off, then use the general rendering hint.
			if (antialiasingHint != RenderingHints.VALUE_TEXT_ANTIALIAS_OFF)
			{
				antialiasingHint = hints.get(RenderingHints.KEY_ANTIALIASING);

				// Test general hint
				if (antialiasingHint != RenderingHints.VALUE_ANTIALIAS_ON &&
						antialiasingHint != RenderingHints.VALUE_ANTIALIAS_DEFAULT)
				{
					// Antialiasing was not requested. However, if it was not turned
					// off explicitly, use it.
					if (antialiasingHint == RenderingHints.VALUE_ANTIALIAS_OFF)
						isAntialiased = false;
				}
			}
			else
				isAntialiased = false;

		}

		// Find out whether fractional metrics should be used.
		boolean useFractionalMetrics = true;
		if (hints.get(RenderingHints.KEY_FRACTIONALMETRICS)
				== RenderingHints.VALUE_FRACTIONALMETRICS_OFF)
			useFractionalMetrics = false;

		FontRenderContext frc = new FontRenderContext(null, isAntialiased, useFractionalMetrics);

		return frc;
	}

	public GraphicsConfiguration getDeviceConfiguration()
	{
		if (bufferedImageGraphics != null)
			return bufferedImageGraphics.getDeviceConfiguration();
		else
			return null;
	}

	public Paint getPaint()
	{
		return this.paint;
	}

	public void setPaint(Paint paint)
	{
		this.paint = paint;

		if (bufferedImageGraphics != null)
			bufferedImageGraphics.setPaint(paint);
	}

	public Stroke getStroke()
	{
		return this.stroke;
	}

	public void setStroke(Stroke s)
	{
		this.stroke = s;

		if (bufferedImageGraphics != null)
			bufferedImageGraphics.setStroke(s);
	}

	public Color getBackground()
	{
		return this.background;
	}

	public void setBackground(Color color)
	{
		this.background = color;

		if (bufferedImageGraphics != null)
			bufferedImageGraphics.setBackground(color);
	}

	public Point2D getPen()
	{
		return pen;
	}

	public Point2D setPen(Point2D pen)
	{
		Point2D old = this.pen;
		this.pen = pen;
		return old;
	}

	public void setRenderingHint(RenderingHints.Key hintKey, Object hintValue)
	{
		hints.put(hintKey, hintValue);

		if (bufferedImageGraphics != null)
			bufferedImageGraphics.setRenderingHint(hintKey, hintValue);
	}

	public Object getRenderingHint(RenderingHints.Key hintKey)
	{
		return hints.get(hintKey);
	}

	public RenderingHints getRenderingHints()
	{
		return hints;
	}

	public void addRenderingHints(Map hints)
	{
		this.hints.putAll(hints);

		if (bufferedImageGraphics != null)
			bufferedImageGraphics.addRenderingHints(hints);
	}

	public void setRenderingHints(Map hints)
	{
		RenderingHints h = new RenderingHints(hints);
		this.hints = h;

		if (bufferedImageGraphics != null)
			bufferedImageGraphics.setRenderingHints(h);
	}

	public void clip(Shape s)
	{
		if (s != null)
			s = transform.createTransformedShape(s);

		if (clip != null)
		{
			Area newClip = new Area(clip);
			newClip.intersect(new Area(s));
			clip = new GeneralPath(newClip);
		}
		else
		{
			clip = s;
		}
	}

    public Rectangle getClipBounds()
	{
        Shape c = getClip();
        if (c == null)
            return null;
        else
            return c.getBounds();
    }

	public void clipRect(int x, int y, int width, int height)
	{
		clip(new Rectangle(x, y, width, height));
	}

	public void setClip(int x, int y, int width, int height)
	{
		setClip(new Rectangle(x, y, width, height));
	}

	public void setClip(Shape clip)
	{
		Shape s = null;

		if (clip != null)
		{
			s = transform.createTransformedShape(clip);
			this.clip = s;
		}
		else
		{
			this.clip = null;
		}

		if (bufferedImageGraphics != null)
			bufferedImageGraphics.setClip(s);
	}

	public Shape getClip()
	{
		try
		{
			return transform.createInverse().createTransformedShape(clip);
		}
		catch (NoninvertibleTransformException e)
		{
			return null;
		}
	}

	public FontMetrics getFontMetrics(Font f)
	{
		if (bufferedImageGraphics != null)
			return bufferedImageGraphics.getFontMetrics(f);
		else
			return null;
	}

	public ColorModel getColorModel()
	{
		if (bufferedImage != null)
			return bufferedImage.getColorModel();
		else
			return null;
	}

    public void rotate(double theta)
	{
        transform.rotate(theta);
        transformStack.addElement(TransformStackElement.createRotateElement(theta));

		if (bufferedImageGraphics != null)
			bufferedImageGraphics.rotate(theta);
    }

    public void rotate(double theta, double x, double y)
	{
        transform.rotate(theta, x, y);
        transformStack.addElement(TransformStackElement.createTranslateElement(x, y));
        transformStack.addElement(TransformStackElement.createRotateElement(theta));
        transformStack.addElement(TransformStackElement.createTranslateElement(-x, -y));

		if (bufferedImageGraphics != null)
			bufferedImageGraphics.rotate(theta, x, y);
    }

    public void scale(double sx, double sy)
	{
        transform.scale(sx, sy);
        transformStack.addElement(TransformStackElement.createScaleElement(sx, sy));

		if (bufferedImageGraphics != null)
			bufferedImageGraphics.scale(sx, sy);
    }

    public void shear(double shx, double shy)
	{
        transform.shear(shx, shy);
        transformStack.addElement(TransformStackElement.createShearElement(shx, shy));

		if (bufferedImageGraphics != null)
			bufferedImageGraphics.shear(shx, shy);
    }

    public void translate(double tx, double ty)
	{
        transform.translate(tx, ty);
        transformStack.addElement(TransformStackElement.createTranslateElement(tx, ty));

		if (bufferedImageGraphics != null)
			bufferedImageGraphics.translate(tx, ty);
    }

	public void translate(int x, int y)
	{
        if(x!=0 || y!=0)
		{
            transform.translate(x, y);
            transformStack.addElement(TransformStackElement.createTranslateElement(x, y));
        }

		if (bufferedImageGraphics != null)
			bufferedImageGraphics.translate(x, y);
    }

	public void transform(AffineTransform tx)
	{
		transform.concatenate(tx);
		transformStack.addElement(TransformStackElement.createGeneralTransformElement(tx));

		if (bufferedImageGraphics != null)
			bufferedImageGraphics.transform(tx);
	}

    public AffineTransform getTransform()
	{
        return new AffineTransform(transform);
    }

    public void setTransform(AffineTransform Tx)
	{
        transform = new AffineTransform(Tx);
        invalidateTransformStack();
        if(!Tx.isIdentity())
		{
            transformStack.addElement(TransformStackElement.createGeneralTransformElement(Tx));
		}

		if (bufferedImageGraphics != null)
			bufferedImageGraphics.setTransform(Tx);
    }

	public AffineTransform getDefaultTransform()
	{
		return defaultTransform;
	}

    public void validateTransformStack()
	{
        transformStackValid = true;
    }

    public boolean isTransformStackValid()
	{
        return transformStackValid;
    }

    void invalidateTransformStack()
	{
        transformStack.removeAllElements();
        transformStackValid = false;
    }


    /**
     * Creates a deep copy of a <code>SWFGraphicContext</code> instance.
	 *
	 * @return a deep copy of this context
     */
    public Object clone()
	{
        GraphicContext copy = new GraphicContext(width, height);

        // BufferedImage (used to calculate font metrics - DON'T CLONE)
		copy.bufferedImageGraphics = this.bufferedImageGraphics;

		// Transform
        copy.setTransform(this.transform);

        // Paint (immutable by requirement)
        copy.setPaint(this.paint);

        // Stroke (immutable by requirement)
        copy.setStroke(this.stroke);

        // Composite (immutable by requirement)
        copy.setComposite(this.composite);

        // Clip
        if(clip != null)
            copy.clip = new GeneralPath(clip);
        else
            copy.clip=null;

        // RenderingHints
        copy.setRenderingHints((RenderingHints)this.hints.clone());

        // Font (immutable)
        copy.setFont(this.font);

        // Background, Foreground (immutable)
        copy.setBackground(this.background);

        return copy;
    }

	private final BufferedImage bufferedImage;

	private Graphics2D bufferedImageGraphics;

	private Font font = new Font("Dialog", Font.PLAIN, 12);

	private final static AffineTransform defaultTransform = new AffineTransform();

	private AffineTransform transform = new AffineTransform();

	private Vector<TransformStackElement> transformStack = new Vector<TransformStackElement>();

	private boolean transformStackValid = true;

	private Composite composite = AlphaComposite.SrcOver;

	private Point2D pen = new Point2D.Double(0.0, 0.0);

	private Paint paint = Color.black;

	private final static Color defaultPaint = Color.black;

	private Stroke stroke = new BasicStroke();

	private Color background = new Color(255, 255, 255, 0);

	private Shape clip = null;

	private RenderingHints hints = new RenderingHints(null);

	private int width;

	private int height;
}
