package adecWatt.view;

//import java.awt.RenderingHints;
import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.Graphics2D;
import java.awt.Graphics;
import java.awt.Image;
import java.awt.Shape;
import java.awt.geom.AffineTransform;
import java.awt.image.BufferedImage;
import java.awt.print.PageFormat;
import java.awt.print.Printable;
import java.awt.print.PrinterJob;
import java.util.ArrayList;
import javax.swing.JFrame;
import javax.swing.JOptionPane;
import javax.swing.JPanel;

import misc.DimensionDouble;
import misc.Log;
import misc.OwnFrame;

import adecWatt.model.Prop;
import adecWatt.model.unit.Workspace;

public class PrintWorkspace implements Printable {

    static public final int formatScale = 20;
    static public final int labelSpace = 4;

    // ========================================
    static public void print (OwnFrame controller, PrinterJob printer, Workspace workspace) {
	ArrayList<JPreviewImp> jPreviewImpPtr = new ArrayList<JPreviewImp> ();
	try {
	    PrintWorkspace printWorkspace = new PrintWorkspace (workspace);
	    printWorkspace.resetPrint (controller, jPreviewImpPtr);
	    printer.setPrintable (printWorkspace);
	    printer.print ();
	    if (printWorkspace.canceled) {
		printer.cancel ();
		return;
	    }
	    return;
	} catch (Throwable t) {
	    Log.keepLastException ("Printworkspace::print", t);
	}
    }

    // ========================================
    private Workspace workspace;
    private Image printPage;
    private BufferedImage workspaceImage, workspaceImageNoCircuit, posterImage, patchImage;
    private JPanel patchJPanel;
    private OwnFrame controller;
    ArrayList<JPreviewImp> jPreviewImpPtr;
    boolean canceled;
    
    public PrintWorkspace (Workspace workspace) {
	this.workspace = workspace;
	workspaceImage = getIcon (workspace, 800, true);
	workspaceImageNoCircuit = getIcon (workspace, 800, false);
	try {
	    posterImage = workspace.getIconImage (Prop.PropPoster).reference;
	} catch (Exception e) {
	}
	try {
	    patchJPanel = new JPatch (workspace.getPatch ());
	    JFrame jFrame = new JFrame ();
	    jFrame.setVisible (false);
	    jFrame.getContentPane ().add (patchJPanel, BorderLayout.CENTER);
	    jFrame.pack ();
	    patchImage = new BufferedImage (patchJPanel.getWidth (), patchJPanel.getHeight (), BufferedImage.TYPE_INT_ARGB);
	    patchJPanel.paint (patchImage.getGraphics ());
	} catch (Exception e) {
	}
    }
    public void resetPrint (OwnFrame controller, ArrayList<JPreviewImp> jPreviewImpPtr) {
	this.controller = controller;
	this.jPreviewImpPtr = jPreviewImpPtr;
    }
    public synchronized int print (Graphics g1, PageFormat pf, int pageIndex) {
	if (pageIndex > 0)
	    return NO_SUCH_PAGE;
	if (jPreviewImpPtr.size () < 1) {
	    JPreviewImp jPreviewImp = new JPreviewImp (workspace.getRealSize (),
						       new DimensionDouble (pf.getImageableWidth (),  pf.getImageableHeight ()),
						       workspaceImage, workspaceImageNoCircuit, posterImage, patchImage, 400);
	    jPreviewImpPtr.add (jPreviewImp);
	    if (JOptionPane.showConfirmDialog (controller.getJFrame (), jPreviewImp, misc.Bundle.getTitle ("Layout"), JOptionPane.YES_NO_OPTION)
		!= JOptionPane.YES_OPTION) {
		canceled = true;
		return NO_SUCH_PAGE;
	    }
	}
	Graphics2D printGraphics = (Graphics2D) g1;
	printGraphics.translate ((int) pf.getImageableX ()+1, (int) pf.getImageableY ());
	print (printGraphics, 1, jPreviewImpPtr.get (0));
	return PAGE_EXISTS;
    }

    // ========================================
    public void print (Graphics2D printGraphics, double lineWidth, JPreviewImp jPreviewImp) {
	if (jPreviewImp.preview.zones.size () < 1) {
	    DimensionDouble printSize = jPreviewImp.preview.getRealSize ();
	    DimensionDouble realSize = jPreviewImp.workspace.getRealSize ();
	    double scale = Math.min (printSize.width/realSize.width, printSize.height/realSize.height);
	    printGraphics.scale (scale, scale);
	    workspace.print (printGraphics, lineWidth*scale, null, true);
	    return;
	}
	AffineTransform iat = printGraphics.getTransform ();
	Shape clip = printGraphics.getClip ();
	for (JZones.Zone zone : jPreviewImp.preview.zones) {
	    printGraphics.setTransform (iat);
	    printGraphics.setClip (clip);
	    zone.projection (printGraphics);
	    if (zone.hasPair ()) {
		workspace.print (printGraphics, lineWidth*zone.getScale (), null, !jPreviewImp.noPrintCircuit.contains (zone));
		continue;
	    }
	    if (zone.getImage () == patchImage) {
		patchJPanel.paint (printGraphics);
		continue;
	    }
	    zone.drawImage (printGraphics);
	}
    }

    static public BufferedImage getIcon (Workspace workspace, int maxSide, boolean printCircuit) {
	DimensionDouble realSize = workspace.getRealSize ();
	double rate = realSize.width/realSize.height;
	int width = maxSide, height = maxSide;
	if (rate > 1)
	    height = (int) (width/rate);
	else
	    width = (int) (rate*height);
	BufferedImage result = new BufferedImage (width, height, BufferedImage.TYPE_INT_ARGB);
	Graphics2D printGraphics = (Graphics2D) result.getGraphics ();
	//printGraphics.setRenderingHint (RenderingHints.KEY_RENDERING, RenderingHints.VALUE_RENDER_QUALITY);
	printGraphics.setColor (Color.WHITE);
	printGraphics.fillRect (0, 0, width, height);
	double printScale = Math.min (width/realSize.width, height/realSize.height);
	printGraphics.scale (printScale, printScale);
	workspace.print (printGraphics, printScale, null, printCircuit);
	return result;
    }

    // ========================================
}
