import de.grogra.imp3d.*;
import de.grogra.ray2.tracing.*;
import de.grogra.rgg.*;
import de.grogra.imp.*;
import de.grogra.math.*;
import de.grogra.vecmath.*;
import de.grogra.vecmath.geom.*;
import de.grogra.imp3d.ray2.*;
import de.grogra.pf.registry.expr.*;
import de.grogra.pf.registry.Item;
import de.grogra.util.*;
import de.grogra.pf.ui.util.*;
import java.awt.image.*;
import java.awt.*;
import java.io.*;
import javax.vecmath.*;
import de.grogra.imp3d.objects.*;

class VRMLGridBillboards extends Billboarder {

	private int stepCount			= 0;
	private int steps				= 0;
	private float boxWidth			= 0;
	private float stepWidth			= 0;
	
	public VRMLGridBillboards(RotationCamera camera)
	{		
		super.camera 				= camera;	
		super.view3d				= camera.getView3D();
		
		this.setRunLater();
	}
	
	public void initialize(double distance, double zOfsset, int sides, int steps, float boxWidth)
	{
		this.steps 		= steps;
		this.boxWidth 	= boxWidth;
		this.stepWidth	= boxWidth/steps;
		
		//RotationAngle	= Math.round(360/sides);
		
		super.initialize(distance, zOfsset, sides > 2 ? 4 : 2);
		griding();
	}
	
	public void griding(int step)
	{
		this.stepCount = step%steps;
		griding();
	}
	
	private void griding()
	{		
		// Das ganze wird von 2 oder 4 Seiten gemacht.
		//println(currentSide);
		if(!(this.stepCount < this.steps))
		{
			if(!(currentSide < sides))
				return;
			
			camera.moveArroundZ(RotationAngle);
			currentSide++;
			this.stepCount = 0;
			
			
		}
		
		final HalfSpace hs1	= new HalfSpace();
		final HalfSpace hs2	= new HalfSpace();
		
		float pos1		= (float)(((stepCount++) - Math.ceil(steps/2)) * stepWidth);
		float pos2		= pos1 - stepWidth;
		
		//println(pos1 + " " + pos2);
		
		//println((curStep * stepWidth));
		
		Point3d origin1		= new Point3d(0.0, 0.0, 0.0);
		Point3d origin2		= new Point3d(0.0, 0.0, 0.0);
		TVector3d axis		= new TVector3d(0, 0, 0);
		
		switch (currentSide)
		{
			case 0 :		// Front
				origin1 	= new Point3d(0.0, -pos1, 0.0);
				origin2 	= new Point3d(0.0, -pos2, 0.0);
				axis 		= new TVector3d(0, -1, 0);
				break;
			case 1 :		// Left
				origin1 	= new Point3d(-pos1, 0.0, 0.0);
				origin2 	= new Point3d(-pos2, 0.0, 0.0);
				axis 		= new TVector3d(-1, 0, 0);
				break;
			case 2 :		// Back
				origin1 	= new Point3d(0.0,pos1,0.0);
				origin2 	= new Point3d(0.0,pos2,0.0);
				axis 		= new TVector3d(0, 1, 0);
				break;
			case 3 :		// Right
				origin1 	= new Point3d(pos1, 0.0, 0.0);
				origin2 	= new Point3d(pos2, 0.0, 0.0);
				axis 		= new TVector3d(1, 0, 0);
				break;
		}
		
		hs1.setTransformation(origin1, axis);
		hs2.setTransformation(origin2, axis);
		
		synthesize((* ^ -minDescendants-> Null *),
		
			Null n => Null*
			(* n -minDescendants-> Null *),
		
			BooleanSynth syn => boolean
			(boolean v = (
							((Volume) hs1).contains(location(((Null) syn.object)), true) &&
							!((Volume) hs2).contains(location(((Null) syn.object)), true)
						),
				((Null) syn.object)[layer] = v ? 4 : 15,
			 v)
		);
		derive();
	}
	
	public void billboarding()
	{
		super.pathAndFileName = targetFolder + targetFileTmpl + currentSide + "_" + stepCount + fileExt;
		super.billboarding();
	}
	
	protected void setRunLater()
	{
		LockProtectedCommand lpc = new LockProtectedCommand(view3d.getGraph(),true,0)
		{
			protected void runImpl(Object arg, de.grogra.pf.ui.Context c)
			{
				// This is the main Thread
				//println("Fertig");
									
				// Only invoke new render-thread, when not all sides are rendered
				if(currentSide < sides && !(stepCount == steps && (currentSide+1) == sides))
				{
					// Rotate the camera to the next viewpoint
					//camera.moveArroundZ(RotationAngle);
					griding();						
					// Invoke next render-thread
					billboarding();
				} else {									
					//writeVRML()	;
				}
				// Writes the VRML-file
				//prepareVRML(targetFileTmpl + currentSide + fileExt);
			}
		};
		super.lpc = lpc;
	}
	
	public void writeVRML()
	{
		//if(mode == "dynamic")
		
		String wrlTempl = "";
		
		wrlTempl = "billboard_dynamisch";
		
		Object f = Library.workbench().getRegistry ().getProjectFile ("pfs:" + wrlTempl +".wrl");
	
		String str = f.toString();
		
		int i = 0;
		float angle = 0;
		
		double rel		= (((double) super.imgHeight) / ((double)super.imgWidth));
		double vrmlDist	= rel / steps;
		
		while(i<sides)
		{
			int e = 1;
			while(e <= steps)
			{
				this.vrmlBB += "PngFrame { url \"bill_" + i + ".png\" }\n\t\t";	
				e++;
			}
			i++;
		}
			
		str	=	str.replaceAll("::REL_HEIGHT::", rel);
		str	=	str.replaceAll("::PNG_PROTO_CALL::", vrmlBB);
		str	=	str.replaceAll("::BILL_NUM::", sides);
		
		FileWriter outputStream 	= new FileWriter("c:/billboard-test/bb.wrl");
		BufferedWriter  outputObj	= new BufferedWriter(outputStream);

		try 
		{
			outputObj.write(str);
		} catch (ClassNotFoundException ex)
		{
			println("Fehler: " + ex.getMessage());
		}
	
		outputObj.flush();
		outputStream.close();
	}
		
	
}