/*
 *  Draco Econometrics
 *  Copyright (C) 2006-2007 Approximatrix, LLC
 *  http://www.approximatrix.com
 *  
 *  This program is free software: you can redistribute it and/or modify
 *  it under the terms of the GNU General Public License as published by
 *  the Free Software Foundation, either version 3 of the License, or
 *  (at your option) any later version.
 *
 *  This program is distributed in the hope that it will be useful,
 *  but WITHOUT ANY WARRANTY; without even the implied warranty of
 *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 *  GNU General Public License for more details.
 *
 *  You should have received a copy of the GNU General Public License
 *  along with this program.  If not, see <http://www.gnu.org/licenses/>.
 */

package com.approximatrix.draco.general.ui;

import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.RenderingHints;
import java.awt.geom.AffineTransform;
import java.awt.geom.Rectangle2D;
import java.awt.Dimension;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.InputStream;
import java.net.URI;

import com.kitfox.svg.SVGDiagram;
import com.kitfox.svg.SVGException;
import com.kitfox.svg.SVGUniverse;
import com.kitfox.svg.app.beans.SVGPanel;

public class VectorGraphicsPanel extends SVGPanel {

	private static final String SVG_ID = "svg0"; 
	
	private boolean center_x = true;
	private boolean center_y = false;
	
	public VectorGraphicsPanel(String path, boolean file) {
		super();
		InputStream svg_file = null;
		if(file) 
			svg_file = getFileInputStream(path);
		else
			svg_file = getResourceInputStream(path);
		
		if(svg_file != null)
			this.loadSVG(svg_file);
	}
	
	public VectorGraphicsPanel(String resource) {
		this(resource,false);
	}
	
	private InputStream getFileInputStream(String filename) {
		FileInputStream svg_file = null;
		try {
			svg_file = new FileInputStream(new File(filename));
		} catch(FileNotFoundException fnfe) {
			System.err.println("File not found: "+filename);
			fnfe.printStackTrace();
			return null;
		}
		return svg_file;
	}
	
	private InputStream getResourceInputStream(String resource_path) {
		return SVGPanel.class.getResourceAsStream(resource_path);
	}
	
	private void loadSVG(InputStream is) {
		
		SVGUniverse universe = new SVGUniverse();
		URI uri = universe.loadSVG(is,SVG_ID);
		
		this.setSvgUniverse(universe);
		this.setSvgURI(uri);
		this.setScaleToFit(true);
		this.setAntiAlias(true);
		
		this.setSvgURI(uri);
		
	}
	
	public void setCenterX(boolean value) {
		center_x = value;
	}
	
	public void setCenterY(boolean value) {
		center_y = value;
	}
	
	/** Overrides the SVGPanel paint routines to allow 
	 * autofit painting to maintain aspect ratio
	 * 
	 * @param gg the graphics on which to paint
	 */
	public void paintComponent(Graphics gg) {

		// if not scaled to fit, just use the original
		// SVGPanel to draw.
		if(!this.isScaleToFit()) {
			super.paintComponent(gg);
			return;
		}
		
		gg.setColor(this.getBackground());
		gg.fillRect(this.getBounds().x, 
				this.getBounds().y, 
				this.getBounds().width, 
				this.getBounds().height);
		
		Graphics2D g = (Graphics2D)gg;
		SVGDiagram diagram = this.getSvgUniverse().getDiagram(this.getSvgURI());
		if (diagram == null) return;
				
        Object oldAliasHint = g.getRenderingHint(RenderingHints.KEY_ANTIALIASING);
        g.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);

        Dimension dim = getSize();
        final int width = dim.width;
        final int height = dim.height;
        
        final Rectangle2D.Double rect = new Rectangle2D.Double();
        diagram.getViewRect(rect);

        // Transform
		AffineTransform scaleXform = new AffineTransform();
		double scale_x = width / rect.width;
		double scale_y = height / rect.height;
		double scale = Math.min(scale_x, scale_y);
		scaleXform.setToScale(scale, scale);
		
		double trans_x=0; double trans_y = 0;
		
		// Center in x
		if(!(scale_x == scale) && center_x) {
			trans_x = ((width/scale)-rect.width)/2.0;
		}
		
		// Center in y
		if(!(scale_y == scale) && center_y) {
			trans_y = ((height/scale)-rect.height)/2.0;
		}
		scaleXform.translate(trans_x, trans_y);

        AffineTransform oldXform = g.getTransform();
        g.transform(scaleXform);

        try
        {
            diagram.render(g);
        }
        catch (SVGException e)
        {
            throw new RuntimeException(e);
        }

        g.setTransform(oldXform);
        g.setRenderingHint(RenderingHints.KEY_ANTIALIASING, oldAliasHint);
        
	}

}
