package ij.plugin.filter;
import ij.*;
import ij.gui.*;
import ij.process.*;
import ij.measure.Calibration;
import java.awt.*;
import java.util.Properties;
import java.awt.print.*;

/** This plugin implements the File/Page Setup and File/Print commands. */
public class Printer implements PlugInFilter, Printable {
	private ImagePlus imp;
	private static double scaling = 100.0;
	private static boolean drawBorder;
	private static boolean center = true;
	private static boolean label;
	private static boolean printSelection;
	private static boolean rotate;
	private static boolean actualSize;
	private static int fontSize = 12;

	public int setup(String arg, ImagePlus imp) {
		if (arg.equals("setup"))
			{pageSetup(); return DONE;}
		this.imp = imp;
		IJ.register(Printer.class);
		return DOES_ALL+NO_CHANGES;
	}

	public void run(ImageProcessor ip) {
		print(imp);
	}
	
	void pageSetup() {
		ImagePlus imp = WindowManager.getCurrentImage();
		Roi roi = imp!=null?imp.getRoi():null;
		boolean isRoi = roi!=null && roi.isArea();
		GenericDialog gd = new GenericDialog("Page Setup");
		gd.addNumericField("Scale:", scaling, 0, 3, "%");
		gd.addCheckbox("Draw border", drawBorder);
		gd.addCheckbox("Center on page", center);
		gd.addCheckbox("Print title", label);
		if (isRoi)
			gd.addCheckbox("Selection only", printSelection);
		gd.addCheckbox("Rotate 90"+IJ.degreeSymbol, rotate);
		gd.addCheckbox("Print_actual size", actualSize);
		if (imp!=null)
			gd.enableYesNoCancel(" OK ", "Print");
		gd.showDialog();
		if (gd.wasCanceled())
			return;
		scaling = gd.getNextNumber();
		if (scaling<5.0) scaling = 5;
		drawBorder = gd.getNextBoolean();
		center = gd.getNextBoolean();
		label = gd.getNextBoolean();
		if (isRoi)
			printSelection = gd.getNextBoolean();
		else
			printSelection = false;
		rotate = gd.getNextBoolean();
		actualSize = gd.getNextBoolean();
		if (!gd.wasOKed() && imp!=null) {
			this.imp = imp;
			print(imp);
		}
	}

	void print(ImagePlus imp) {
		PrinterJob pj = PrinterJob.getPrinterJob();
		pj.setPrintable(this);
		//pj.pageDialog(pj.defaultPage());
		if (IJ.macroRunning() || pj.printDialog()) {
			imp.startTiming();
			try {pj.print(); }
			catch (PrinterException e) {
				IJ.log(""+e);
			}
		}
	}
	
	@Override
	public int print(Graphics g, PageFormat pf, int pageIndex) {
		if (pageIndex != 0) return NO_SUCH_PAGE;
		Roi roi = imp.getRoi();
		ImagePlus imp2 = imp;
		if (imp2.getOverlay()!=null && !imp2.getHideOverlay()) {
			imp2.deleteRoi();
			imp2 = imp2.flatten();
		}
		ImageProcessor ip = imp2.getProcessor();
		if (printSelection && roi!=null && roi.isArea() )
			ip.setRoi(roi);
			ip = ip.crop();
		if (rotate)
			ip = ip.rotateLeft();
		int width = ip.getWidth();
		int height = ip.getHeight();
		int margin = 0;
		if (drawBorder) margin = 1;
		double scale = scaling/100.0;
		int dstWidth = (int)(width*scale);
		int dstHeight = (int)(height*scale);
		int pageX = (int)pf.getImageableX();
		int pageY = (int)pf.getImageableY();
		int dstX = pageX+margin;
		int dstY = pageY+margin;
		Image img = ip.createImage();
		double pageWidth = pf.getImageableWidth()-2*margin;
		double pageHeight = pf.getImageableHeight()-2*margin;
		if (label && pageWidth-dstWidth<fontSize+5) {
			dstY += fontSize+5;
			pageHeight -= fontSize+5;
		}
		if (actualSize) {
			Calibration cal = imp.getCalibration();
			int unitIndex = ImageProperties.getUnitIndex(cal.getUnit());
			if (unitIndex!=ImageProperties.OTHER_UNIT) {
				double unitsPerCm = ImageProperties.getUnitsPerCm(unitIndex);
				double widthInCm = width*cal.pixelWidth/unitsPerCm;
				double heightInCm = height*cal.pixelHeight/unitsPerCm;
				dstWidth = (int)((widthInCm*(72*0.3937))*scale);
				dstHeight = (int)((heightInCm*(72*0.3937))*scale);
			}
			if (center && dstWidth<pageWidth && dstHeight<pageHeight) {
				dstX += (pageWidth-dstWidth)/2;
				dstY += (pageHeight-dstHeight)/2;
			}
		} else if (dstWidth>pageWidth || dstHeight>pageHeight) {
			// scale to fit page
			double hscale = pageWidth/dstWidth;
			double vscale = pageHeight/dstHeight;
			double scale2 = hscale<=vscale?hscale:vscale;
			dstWidth = (int)(dstWidth*scale2);
			dstHeight = (int)(dstHeight*scale2);
		} else if (center) {
			dstX += (pageWidth-dstWidth)/2;
			dstY += (pageHeight-dstHeight)/2;
		}
		g.drawImage(img, 
			dstX, dstY, dstX+dstWidth, dstY+dstHeight,
			0, 0, width, height, 
			null);
		if (drawBorder)
			g.drawRect(dstX-1, dstY-1, dstWidth+1, dstHeight+1);
		if (label) {
			g.setFont(new Font("SanSerif", Font.PLAIN, fontSize));
			g.setColor(Color.black);
			g.drawString(imp.getTitle(), pageX+5, pageY+fontSize);
		}
		return PAGE_EXISTS;
	}

}
