/*
 * Created on 28.06.2004 11:05:55
 *
 * Multimediale Algorithmen und Datenstrukturen Assessments
 */
package mauda.jedasnew;

/*
package jedas.io;

import jedas.*;
import jedas.utils.UserDialog;
import java.io.ObjectInputStream;
import java.io.FileInputStream;
import java.util.zip.InflaterInputStream;
import java.util.Hashtable;
import java.util.Enumeration;
import java.util.Vector;
import java.awt.*;
*/

import java.util.*;
import java.util.zip.*;
import java.awt.*;
import java.io.*;

import jedas.*;
import jedas.io.*;
import jedas.utils.UserDialog;

/**
 * <b>Relevance:</b> <font color=ff0000></font><br>
 * <b>Since:</b> 0.99rc1, version 1.11<br>
 * <b>Class status:</b> Single instance<br>
 *
 * <h1><tt>jedas.io.JedasPlayer</tt></h1>
 *
 * <p>This class is used for playback of recorded <i>JEDAS</i> animations
 * (normally <tt>*.jea</tt> files). Usage is simple:
 * <pre>
 * [cmd line input:] java jedas.io.JedasPlayer [animation.jea]
 * </pre>
 *
 * @author Martin Danielsson
 */
public class JedasPlayer {

	private Jedas2Animation jedasAnim;
	private PlayerScheduler playerScheduler;

	private static JedasPlayer jedasPlayerInstance;
	private static boolean instanciated = false;

	/**
	 * <b>Relevance:</b> <font color=ff0000>Debugging</font><br>
	 * <b>Since:</b> 0.99rc1<br>
	 * Toggle the debug mode. Default is <i>false</i>.
	 */
	public static boolean DEBUGMODE = false;

	/**
	 * <b>Relevance:</b> <font color=ff0000>Animation programmer</font><br>
	 * <b>Since:</b> 0.951<br>
	 * The <tt>main()</tt> method of <tt>JedasPlayer</tt>. This is called by the
	 * <tt>java</tt> interpreter. First argument is animation file.
	 */
	public static void main( String[] args ) {
		if ( args.length < 1 ) {
			System.out.println( "Usage: java jedas.io.JedasPlayer <jedas anim file>" );	
			System.exit(0);
		}

		if ( args.length > 1 )
			if ( args[1].equals( "debug" ) )
			DEBUGMODE = true;

		Jedas.setPlayerMode( true );

		System.out.println( "jedas.io.JedasPlayer v" + Jedas.VERSION );
		System.out.println();
		System.out.println( "This program is part of the JEDAS package." );
		System.out.println( "(c) 2000 Rainer Mueller & Martin Danielsson" );
		System.out.println();
		System.out.println( "http://ad.informatik.uni-freiburg.de/~rmueller/jedas" );
		System.out.println( "eMail: rmueller@informatik.uni-freiburg.de" );
		System.out.println( "       martin@danielsson.de" );

		new JedasPlayer( args[0], true );
	}

	/**
	 * <b>Relevance:</b> <font color=ff0000>Lib programmer</font><br>
	 * <b>Since:</b> 0.951<br>
	 * Creates a <tt>JedasPlayer</tt> which loads the <i>JEDAS</i> animation
	 * the file called <tt>filename</tt>. This constructor is invoked from
	 * the <tt>main()</tt> method.<br><br>
	 * If the parameter <code>createGUIs</code> is false, the Animation-CompPanels should
	 * be called by getCompPanels()!
	 *
	 * @param filename Jedas-Animation-Filename
	 * @param createGUIs true if GUIs should be created, false means no GUI-Creation
	 * @see #main(String[])
	 */
	public JedasPlayer( String filename, boolean createGUIs ) {
	
		//if ( instanciated )
		//	throw new Error( "JedasPlayer::already instanciated in this session!" );

		instanciated = true;
		jedasPlayerInstance = this;

		if ( !readAnimation( filename ) )
			System.exit(1);

		System.out.println( "===================================" );
		System.out.println( "Jedas version of saving instance: v" + jedasAnim.jedasVersion );
		System.out.println( "   Length of animation: " + jedasAnim.animLength );
		System.out.println( "   TAS entries        : " + jedasAnim.transitionAccessStream.size() );
		System.out.println( "   PAS entries        : " + jedasAnim.propertyAccessStream.size() );

		//	Vector trList = jedasAnim.trList;
		//	TrListEntry trE;
		//	TransStub tmp;

		// JedasPlayer: rausgenommen (wird beim originalen JedasPlayer aufgerufen)
		if(createGUIs) initItems();

		System.out.println();
		System.out.println( "Starting application..." );

		if(createGUIs) {
			// XXX: JEDAS-Update: Folgende 2 Zeilen funktionieren erst beim Einfügen in Jedas-Bibliothek
			// Falls gewünscht: neue JedasPlayer-Klasse in die Jedas-Bibliothek einfügen
			// Achtung: Bug-Freiheit beim Einfügen ev. nicht gewährleistet
			//PlayerControlFrame pcf = new PlayerControlFrame( jedasAnim.animLength );
			//playerScheduler = new PlayerScheduler( jedasAnim, pcf.pcp );
		} else {
			PlayerControlPanel pcp = new PlayerControlPanel(jedasAnim.animLength);
			playerScheduler = new PlayerScheduler( jedasAnim, pcp );
		}

		playerScheduler.jumpToTime( 0L );
		Jedas.updateDisplay();
	}

	/**
	 * <b>Relevance:</b> <font color=ff0000>Lib programmer</font><br>
	 * <b>Since:</b> 0.99rc1<br>
	 * @return a reference to the <tt>JedasPlayer</tt> instance, or <tt>null</tt> if
	 *         such an instance does not exist.
	 */
	public static JedasPlayer getInstance() {
		return jedasPlayerInstance;
	}

	/**
	 * <b>Relevance:</b> <font color=ff0000>Lib programmer</font><br>
	 * <b>Since:</b> 0.951<br>
	 * @return the <tt>Jedas2Animation</tt> that has been loaded by
	 * @see Jedas2Animation
	 */
	public Jedas2Animation getJedasAnimation() {
		return jedasAnim;
	}

	/**
	 * <b>Relevance:</b> <font color=ff0000>Lib programmer</font><br>
	 * <b>Since:</b> 0.951<br>
	 * @return a reference to the <tt>PlayerScheduler</tt>
	 * @see PlayerScheduler
	 */
	public PlayerScheduler getPlayerScheduler() {
		return playerScheduler;
	}

	/**
	 * <b>Relevance:</b> <font color=ff0000>Lib internal</font><br>
	 * <b>Since:</b> 0.951, version 1.03<br>
	 * Initialise all items to their initial state. This simply applies
	 * the first <tt>PrListEntry</tt> to the owners.
	 */
	private void initItems() {
	
		//	System.out.println( "===================================" );
		//	System.out.print( "Setting initial properties... " );
		//	System.out.flush();
	
		//	PrListEntry firstEntry = (PrListEntry) jedasAnim.prList.firstElement();

		//	if ( DEBUGMODE ) 
		//		for ( int i=0; i<firstEntry.properties.length; i++ ) {
		//		System.out.println( " Prop["+i+"]: " + firstEntry.properties[i] );
		//		}

		//	for ( int i=0; i<firstEntry.properties.length; i++ ) {
		//		Recordable rec = firstEntry.properties[i].owner;
		//		if ( DEBUGMODE )
		//		System.out.println( " > " + rec );
		//		rec.setProperties( firstEntry.properties[i] );
		//	}

		//	System.out.println( "ready!" );
		//	System.out.println( "===================================" );
		//	System.out.println( "Checking for CompPanels..." );

		Vector compPanels = getCompPanels();
		Enumeration enu = compPanels.elements();
		int upperX = 0, upperY = 90;

		while ( enu.hasMoreElements() ) {
			CompPanel cp = (CompPanel)enu.nextElement();
			cp.setPreferredSize(new Dimension(400, 400));
			Frame frT = new Frame( cp.getPanelName() );
			frT.setLayout( new BorderLayout() );
			frT.add( cp.getDrawPanel(), "Center" );
			//frT.add( new jedas.utils.ZoomSetPanel(cp), "Center" );
			//cp.getDrawPanel().setSize( new Dimension( 400, 400 ) );
			//frT.setSize( 400, 400 );
			frT.setVisible( true );
			frT.setLocation( upperX, upperY );
			frT.setSize( new Dimension( 400, 400 ) );
			upperY += 100;
			upperX += 100;
			frT.pack();
		}

		//	if ( DEBUGMODE ) {
		//		System.out.println( "===================================" );
	    
		//		System.out.println( "Checking init status of Items:" );
	    
		//		enum = jedasAnim.recordableTable.elements();
		//		while ( enum.hasMoreElements() ) {
		//		tmp = (Recordable) enum.nextElement();
		//		System.out.print( " > " + tmp.getClass().getName() + ": " );
		//		if ( tmp.isInitialised() )
		//			System.out.println( "yes" );
		//		else
		//			System.out.println( "no" );
		//		}
		//	}
	}
	
	// Holt alle CompPanels der Aufzeichnung (normalerweise nur einer)
	public Vector getCompPanels() {
		Vector compPanels = new Vector();
		
		Enumeration enu = jedasAnim.recordableTable.elements();
		Recordable tmp;
		while ( enu.hasMoreElements() ) {
			tmp = (Recordable) enu.nextElement();
			if ( tmp instanceof jedas.CompPanel ) {
				System.out.println( " --> " + tmp.getName() );
				CompPanel cp = (CompPanel) tmp;
				cp.initOnPlay();
				compPanels.add(cp);
			}
		}
		return compPanels;
	}
	/**
	 * <b>Relevance:</b> <font color=ff0000>Lib programmer</font><br>
	 * <b>Since:</b> 0.951<br>
	 * Invokes <tt>PlayerScheduler.jumpToTime(long)</tt>.
	 * @see PlayerScheduler#jumpToTime(long)
	 * @deprecated as of version 2.00, replaced by same method in 
	 *   <tt>PlayerScheduler</tt>.
	 */
	public void jumpToTime( long timeStamp ) {
		playerScheduler.jumpToTime( timeStamp );
	}

	/**
	 * <b>Relevance:</b> <font color=ff0000>Lib internal</font><br>
	 * <b>Since:</b> 0.951<br>
	 * @deprecated
	 */
	protected void quitNotify() {
		// ?
		//playerScheduler.quitNotify();
	}

	/* ============================= */

	/**
	 * <b>Relevance:</b> <font color=ff0000>Lib internal</font><br>
	 * <b>Since:</b> 0.951<br>
	 * Loads the <tt>JedasAnimation</tt> in <tt>fileName</tt> into the
	 * memory. This is done in the constructor of <tt>JedasPlayer</tt>
	 * @see #getJedasAnimation()
	 * @author Martin Danielsson
	 */
	boolean readAnimation( String fileName ) {

		boolean back = true;

		//PleaseWaitFrame pwf = new PleaseWaitFrame( "Reading animation..." );
		//pwf.repaint();

		try {
			Object readObject = null;
			try {
				ObjectInputStream in = new ObjectInputStream
					( new InflaterInputStream( new FileInputStream( fileName ) ) );
		
				readObject = in.readObject();
			} catch ( java.util.zip.ZipException e ) {
				// input stream uncompressed?
				ObjectInputStream in = new ObjectInputStream
					( new FileInputStream( fileName ) );
		
				readObject = in.readObject();
			}

			if ( readObject instanceof Jedas2Animation )
				jedasAnim = (Jedas2Animation) readObject;
			else
				throw new JedasError( "This version does not support recorded animations of versions less than 2.00!" );

		} catch (Exception e) {
			String text[] = {"While reading the animation, the following",
					 "java exception was thrown:", "",
					 e.toString()};
			String bts[]  = {"OK"};
			new UserDialog( text, bts, null );	

			e.printStackTrace();
	    
			back = false;
		}

		//pwf.dispose();

		return back;
	}
}
