/*
 * Created on 11.07.2004 17:53:04
 *
 * Multimediale Algorithmen und Datenstrukturen Assessments
 */
package mauda;

import jedas.CompObj;
import jedas.DPair;
import jedas.Item;
import jedas.Jedas;
import mauda.plugin.JedasMainCompObj;

/**
 * Handles an automatically zoom for the jedas-panel.
 * 
 * @author Markus Krebs
 */
public class AutomaticZoomThread extends Thread {
	
	private static int updateInterval = 1000;	// in ms
	private static int currentTime;
	private static int sleepTime = 100;			// in ms
	
	private static Exercise exercise;
	private boolean stopThread;
	private static boolean enabled = false;	// Default
	
	/**
	 * Creates a thread that adjust the zoom of the jedas-panel automatically.
	 */
	public AutomaticZoomThread() {
		exercise = null;
		stopThread = false;
		//enabled = false;
	}
	
	/* (non-Javadoc)
	 * @see java.lang.Runnable#run()
	 */
	public void run() {
		//System.out.println("AutomaticZoomThread.run() running...");
		while(!stopThread) {
			currentTime = 0;
			forceZoom(exercise);
			while(currentTime<=updateInterval) {
				if(stopThread) break;
				currentTime+=sleepTime;
				try { sleep(sleepTime); }
				catch(Exception ex) {
					System.err.println("AutomaticZoomThread.run(): sleep-Exception");
				}
			}
		}
		forceZoom(exercise);
		//System.out.println("AutomaticZoomThread.run() stopped!");
	}
	
	/**
	 * Starts the automatic zoom.
	 * @param ex The current exercise.
	 */
	public void startZooming(Exercise ex) {
		//System.out.println("AutomaticZoomThread.startZooming(): enabled="+enabled+" stop="+stopThread);
		exercise = ex;
		stopThread = false;
		start();
	}
	
	/**
	 * Stops the automatic zoom.
	 */
	public void stopZooming() {
		//System.out.println("AutomaticZoomThread.stopZooming()");
		stopThread = true;
		/*
		try{ join(); }
		catch(Exception ex) {
			System.err.println("AutomaticZoomThread.stopZooming(): join-Exception");			
		}*/
	}
	
	/**
	 * Perform an automatic zoom immediately.
	 * @param ex The current exercise.
	 */
	public static void forceZoom(Exercise ex) {
		if(!enabled) return;
		//System.out.println("AutomaticZoomThread.forceZoom(..)");
		exercise = ex;
		if(exercise==null) return;
		// Da beim Pause-Modus der Scheduler angehalten wird, darf dies beim Zoom
		// nicht nochmal gemacht werden, da ansonsten beim resume die Aufnahme trotz
		// Pause wieder gestartet wird!
		boolean running = false;
		if(Exercise.scheduler.isRunning()) running = true;
		if(running) Exercise.scheduler.suspend();
		adjustZoom();
		Jedas.updateDisplay();
		if(running) Exercise.scheduler.resume();
		currentTime = 0;
	}
	
	/**
	 * Enables or disables the automatic zoom. The Thread is still alive.
	 * @param en true=enabled, false=disabled
	 */
	public static void setEnabled(boolean en) {
		enabled = en;
		if(!enabled) {
			Exercise.compPanel.setZoom(1.0);
			Exercise.compPanel.setHotSpot(new DPair(0.5,0.5));
			Jedas.updateDisplay();
		}
	}
	/**
	 * Returns the enabled-State of the automatic zoom.
	 * @return true if enabled, false otherwise
	 */
	public static boolean isEnabled() {
		return enabled;
	}
		
	// Ab hier ADJUST-ZOOM-Routinen
	private static double minx;
	private static double miny;
	private static double maxx;
	private static double maxy;
	private static int itemCounter;
	private static void adjustZoom() {
		CompObj compObj = ((JedasMainCompObj)exercise.getDSObject()).getMainCompObj();
		// Leider liefert folgender Aufruf nicht die korrekte Bounding-Box (siehe JEDAS-Doku)
		//BBox bBox = compObj.getBBox();
		long timeMillis = System.currentTimeMillis();
		minx = Double.MAX_VALUE; miny = Double.MAX_VALUE;
		maxx = Double.MIN_VALUE; maxy = Double.MIN_VALUE;
		itemCounter = 0;
		calculateBBox(0, 0, compObj);
		
		minx-=0.05; miny-=0.05;
		maxx+=0.05; maxy+=0.05;
		DPair pos = new DPair(minx,miny);
		DPair size = new DPair(maxx-minx,maxy-miny);
		//System.out.println("#Items = "+itemCounter+" / Pos = "+pos+" / Size = "+size);
		//RectObj rectObj = new RectObj(pos, size);
		//compPanel.addItem(rectObj);
		//rectObj.show();
		
		double dx = maxx-minx;
		double dy = maxy-miny;
		double x = dx/2+minx;
		double y = dy/2+miny;
		double zoom = 0;
		if(dx>dy) zoom = 1.0/dx;
		else zoom = 1.0/dy;
		
		//if(zoom == Exercise.compPanel.getZoom()) System.out.println("No zoom necessary");
		Exercise.compPanel.setZoom(zoom);
		Exercise.compPanel.setHotSpot(new DPair(x,y));
		timeMillis = System.currentTimeMillis()-timeMillis;
		//System.out.println("Time: "+timeMillis+"ms");
	}
	private static void calculateBBox(double ox, double oy, CompObj co) {
		DPair copos = co.getPos();
		double cox = copos.get(0);
		double coy = copos.get(1);
		//updateBBox(ox + cox, oy + coy);
		Item item = co.getFirstItem();
		while(item!=null) {
			if(item instanceof CompObj) {
				calculateBBox(ox + cox, oy + coy, (CompObj)item);
			} 
			else {
				//if(item.isVisible()) {
					DPair p = item.getPos();
					updateBBox(ox + p.get(0), oy + p.get(1));
					DPair s = item.getSize();
					double x = p.get(0) + s.get(0);
					double y = p.get(1) + s.get(1);
					updateBBox(ox + x, oy + y);
				//}
			}			
			item = co.getNextItem();
		}
	}
	private static void updateBBox(double x, double y) {
		itemCounter++;
		//System.out.println("Pos: "+pos);
		if(x<minx) minx = x;
		if(y<miny) miny = y;
		if(x>maxx) maxx = x;
		if(y>maxy) maxy = y;
	}
}
