/*
 * OverlayGraphics.java
 *
 * Created on March 1, 2002, 4:06 AM
 */

package Astroblocks.Application.GUIParts.Overlay;

import java.awt.*;
import java.awt.image.*;
import java.awt.image.renderable.RenderableImage;
import java.awt.geom.AffineTransform;
import java.util.*;
import java.text.AttributedCharacterIterator;
import java.awt.RenderingHints.Key;
import java.awt.font.FontRenderContext;
import java.awt.font.GlyphVector;
import javax.media.j3d.*;
/**
 *
 * @author  Ian Nieves
 * @version 
 */
public class OverlayGraphics extends java.awt.Graphics {


    

    private J3DGraphics2D canvas3DGraphics;     // need this to paint on the 3D canvas
    private Rectangle clipRect;                 // need this for clipping
    private Canvas3D canvas3D;                  // need this to get the canvas3DGraphics from above
    private int translateX, translateY;         // stores the current translation
    private Rectangle savedRect;                // saves the canvas3D state
    private int savedX, savedY;                 // saves the canvas3D state
    
    public OverlayGraphics(Canvas3D inCanvas3D){
        canvas3D = inCanvas3D;
        canvas3DGraphics = inCanvas3D.getGraphics2D();
        translateX = 0;
        translateY = 0;
    }
    
    
    // before we draw to the canvas3D (or change translation or clip), we save its state, so we can restore it later.
    private void updateCanvas3DGraphicsBefore(){

        savedX = (int) canvas3DGraphics.getTransform().getTranslateX();
        savedY = (int) canvas3DGraphics.getTransform().getTranslateY();
        savedRect = canvas3DGraphics.getClipBounds();


        
        if( (canvas3DGraphics.getTransform().getTranslateX() != this.translateX) || (canvas3DGraphics.getTransform().getTranslateY() != this.translateY) )
            canvas3DGraphics.translate( (int) -canvas3DGraphics.getTransform().getTranslateX() + this.translateX, (int) -canvas3DGraphics.getTransform().getTranslateY() + this.translateY );
                
        if( (canvas3DGraphics.getClipBounds() == null) && (clipRect == null)){
            // do nothing
        }
        else if( (canvas3DGraphics.getClipBounds() == null) || (clipRect == null)){
            canvas3DGraphics.setClip(clipRect);
        }
        else{
            if( !canvas3DGraphics.getClipBounds().equals(clipRect) )
                canvas3DGraphics.setClip(clipRect);
        }
           
        
        
    }
    

    // restore the state from before we made changes
    private void updateCanvas3DGraphicsAfter(){
        canvas3DGraphics.translate( (int) -canvas3DGraphics.getTransform().getTranslateX() + this.savedX, (int) -canvas3DGraphics.getTransform().getTranslateY() + this.savedY );
        canvas3DGraphics.setClip(savedRect);
    }
    
    public void flush(boolean doFlush){
        canvas3DGraphics.flush(doFlush);
    }
    

    public Graphics create() {
        //System.out.println("create");
        OverlayGraphics newOverlayGraphics = new OverlayGraphics(canvas3D);
        newOverlayGraphics.setClip(this.getClip());
        newOverlayGraphics.translate(this.translateX, this.translateY);
        return newOverlayGraphics;
    }
    

    
    /////////////////// draw & fill
    public void drawRoundRect( int x, int  y, int  width, int height, int arcWidth, int arcHeight) {
        //System.out.println("drawRoundRect");
        updateCanvas3DGraphicsBefore();
        canvas3DGraphics.drawRoundRect( x,  y,  width,  height,  arcWidth,  arcHeight);
        updateCanvas3DGraphicsAfter();
    }
      
    public void drawArc(int x, int y, int width, int height, int startAngle, int arcAngle) {
        //System.out.println("drawArc");
        updateCanvas3DGraphicsBefore();
        canvas3DGraphics.drawArc( x,  y,  width,  height,  startAngle,  arcAngle);
        updateCanvas3DGraphicsAfter();
    }
    
    public void drawOval(int x, int y, int width, int height) {
        //System.out.println("drawOval");
        updateCanvas3DGraphicsBefore();
        canvas3DGraphics.drawOval( x,  y,  width,  height);
        updateCanvas3DGraphicsAfter();
    }
    
    public void drawPolygon(int[] xPoints, int[] yPoints, int nPoints) {
        //System.out.println("drawPolygon");
        updateCanvas3DGraphicsBefore();
        canvas3DGraphics.drawPolygon( xPoints,  yPoints,  nPoints);
        updateCanvas3DGraphicsAfter();
    }
    
    public void drawPolyline(int[] xPoints, int[] yPoints, int nPoints) {
        //System.out.println("drawPolyline");
        updateCanvas3DGraphicsBefore();
        canvas3DGraphics.drawPolyline( xPoints,  yPoints,  nPoints);
        updateCanvas3DGraphicsAfter();
    }
    
    public void drawString(AttributedCharacterIterator iterator, int x, int y) {
        //System.out.println("drawString");
        updateCanvas3DGraphicsBefore();
        canvas3DGraphics.drawString( iterator,  x,  y);      
        updateCanvas3DGraphicsAfter();
    }
      
    public void drawString(String str, int x, int y) {
        //System.out.println("drawString");
        //canvas3DGraphics.flush(false);
        updateCanvas3DGraphicsBefore();
        canvas3DGraphics.drawString( str,  x,  y);
        updateCanvas3DGraphicsAfter();
        
    }

    public boolean drawImage(Image img, int dx1, int dy1, int dx2, int dy2, int sx1, int sy1, int sx2, int sy2, Color bgcolor, ImageObserver observer) {
        //System.out.println("drawImage 1");
        updateCanvas3DGraphicsBefore();
        boolean returnVal = canvas3DGraphics.drawImage( img,  dx1,  dy1,  dx2,  dy2,  sx1,  sy1,  sx2,  sy2,  bgcolor,  observer);
        updateCanvas3DGraphicsAfter();
        return returnVal;
    }
    
    public boolean drawImage(Image img, int dx1, int dy1, int dx2, int dy2, int sx1, int sy1, int sx2, int sy2, ImageObserver observer) {
        //System.out.println("drawImage 2");
        //canvas3DGraphics.flush(false);
        updateCanvas3DGraphicsBefore();
        boolean returnVal = canvas3DGraphics.drawImage( img,  dx1,  dy1,  dx2,  dy2,  sx1,  sy1,  sx2,  sy2,  observer);
        updateCanvas3DGraphicsAfter();
        return returnVal;
    }
    
    public boolean drawImage(Image img, int x, int y, int width, int height, Color bgcolor, ImageObserver observer) {
        //System.out.println("drawImage 3");
        updateCanvas3DGraphicsBefore();
        boolean returnVal = canvas3DGraphics.drawImage( img,  x,  y,  width,  height,  bgcolor,  observer);
        updateCanvas3DGraphicsAfter();
        return returnVal;
    }
    
    public boolean drawImage(Image img, int x, int y, Color bgcolor, ImageObserver observer) {
        //System.out.println("drawImage 4");
        updateCanvas3DGraphicsBefore();
        boolean returnVal = canvas3DGraphics.drawImage( img,  x,  y,  bgcolor,  observer);
        updateCanvas3DGraphicsAfter();
        return returnVal;
    }
    
    public boolean drawImage(Image img, int x, int y, int width, int height, ImageObserver observer) {
        //System.out.println("drawImage 5");
        updateCanvas3DGraphicsBefore();
        boolean returnVal = canvas3DGraphics.drawImage( img,  x,  y,  width,  height,  observer);
        updateCanvas3DGraphicsAfter();
        return returnVal;
    }
    
    public boolean drawImage(Image img, int x, int y, ImageObserver observer) {
        //System.out.println("drawImage 6 ->" + x + " " + y);
        //canvas3DGraphics.flush(false);
        updateCanvas3DGraphicsBefore();
        boolean returnVal = canvas3DGraphics.drawImage( img,  x,  y,  observer);
        updateCanvas3DGraphicsAfter();
        return returnVal;
    }
  
    public void drawLine(int x1, int y1, int x2, int y2) {
        //System.out.println("drawLine ->" + x1 + " " + y1 + " " + x2 + " " + y2);
        //canvas3DGraphics.flush(false);
        updateCanvas3DGraphicsBefore();
        canvas3DGraphics.drawLine( x1,  y1,  x2,  y2);
        updateCanvas3DGraphicsAfter();
    }
    
    public void fillRect(int x, int y, int width, int height) {
        
        //System.out.println("fillRect -> " + x + " " + y + " " + width + " " + height);
        //canvas3DGraphics.flush(false);
        updateCanvas3DGraphicsBefore();
        canvas3DGraphics.fillRect( x,  y,  width,  height);
        updateCanvas3DGraphicsAfter();
    }
    
    public void fillArc(int x, int y, int width, int height, int startAngle, int arcAngle) {
        //System.out.println("fillArc");
        updateCanvas3DGraphicsBefore();
        canvas3DGraphics.fillArc( x,  y,  width,  height,  startAngle,  arcAngle);
        updateCanvas3DGraphicsAfter();
    }
    
    public void fillPolygon(int[] xPoints, int[] yPoints, int nPoints) {
        //System.out.println("fillPolygon");
        updateCanvas3DGraphicsBefore();
        canvas3DGraphics.fillPolygon( xPoints,  yPoints,  nPoints);
        updateCanvas3DGraphicsAfter();
    }
    
    public void fillOval(int x, int y, int width, int height) {
        //System.out.println("fillOval");
        updateCanvas3DGraphicsBefore();
        canvas3DGraphics.fillOval( x,  y,  width,  height);
        updateCanvas3DGraphicsAfter();
    }
        
    public void fillRoundRect(int x, int y, int width, int height, int arcWidth, int arcHeight) {
        //System.out.println("fillRoundRect");
        updateCanvas3DGraphicsBefore();
        canvas3DGraphics.fillRoundRect( x,  y,  width,  height,  arcWidth,  arcHeight);
        updateCanvas3DGraphicsAfter();
    }

    public void copyArea(int x, int y, int width, int height, int dx, int dy) {
        //System.out.println("copyArea");
        updateCanvas3DGraphicsBefore();
        canvas3DGraphics.copyArea(x, y, width, height, dx, dy);
        updateCanvas3DGraphicsAfter();
    }
    /////////////////////////////// clip
    
    public Shape getClip() {
        //System.out.println("getClip -> " + clipRect);
        if(clipRect != null)
            return new Rectangle(clipRect);
        else
            return null;
    }
    
    public Rectangle getClipBounds() {
        //System.out.println("getClipBounds -> " + clipRect);
        if(clipRect != null)
            return new Rectangle(clipRect);
        else
            return null;
    }
    
    public void setClip(int x, int y, int width, int height) {
        //System.out.println("setClip -> " + x + " " + y + " " + width + " " + height);
        clipRect = new Rectangle(x, y, width, height);
    }
    
    public void clipRect(int x, int y, int width, int height) {
        //System.out.println("clipRect -> " + x + " " + y + " " + width + " " + height);
        //System.out.println("before -> " + clipRect);
        Rectangle tempRect = new Rectangle(x,y,width,height);
        clipRect = tempRect.intersection(clipRect);
        //System.out.println("after ->" + clipRect);
    }
    
    public void setClip(Shape clip) {
        //System.out.println("setClip -> " + clip);
        if(clip != null)
            clipRect = clip.getBounds();
        else
            clipRect = null;
    }
    
    //////////////////////////////// misc.
    
    public void setXORMode(Color c) {
        //System.out.println("setXORMode");
        //xorColor = new Color(c.getRed(), c.getGreen(), c.getBlue(), c.getAlpha());
        //dirty = true;
        canvas3DGraphics.setXORMode(c);
    }
    
    public Font getFont() {
        //System.out.println("getFont");
        return canvas3DGraphics.getFont();
        //return textFont;
    }
    
    public void setPaintMode() {
        //System.out.println("setPaingMode");
        //paintMode = true;
        //d/rty = true;
        canvas3DGraphics.setPaintMode();
    }
    
    public void setColor(Color c) {
        ////System.out.println("setColor");
        //paintColor = new Color(c.getRed(), c.getGreen(), c.getBlue(), c.getAlpha());
        //dirty = true;
        canvas3DGraphics.setColor(c);
    }
    
    public void dispose() {
        ////System.out.println("DISPOSE");
    }
    
    public Color getColor() {
        //System.out.println("getColor");
        //return paintColor;
        return canvas3DGraphics.getColor();
    }
    
    public void clearRect(int x, int y, int width, int height) {
        // do nothing
        System.out.println("clearRect -> Should not be calling this");
    }
   
    public void setFont(Font font) {
        ////System.out.println("setFont");
        //textFont = font;
        //dirty = true;
        canvas3DGraphics.setFont(font);
    }
    
    public void translate(int x, int y) {
        //System.out.println("translate -> " + x + " " + y);
        translateX += x;
        translateY += y;
        
    }

    public FontMetrics getFontMetrics(Font f) {
        return canvas3DGraphics.getFontMetrics(f);
    }
    

    
}
 