package vgp.tutor.key;

import jv.anim.PsAnimation;
import jv.anim.PsKeyframe;
import jv.loader.PgLoader;
import jv.number.PuString;
import jv.object.PsConfig;
import jv.object.PsDebug;
import jv.object.PsUtil;
import jv.project.PgGeometry;
import jv.project.PjProject;
import jv.project.PvViewerIf;

/**
 * Demo project of keyframe animation of precomputed models.
 * 
 * @author		Konrad Polthier
 * @version		15.02.02, 1.60 revised (kp) Bug removed which restricted numFiles<10.<br>
 *					25.01.02, 1.50 revised (kp) Animation of a set of geometries handled.<br>
 *					16.09.00, 1.20 revised (kp) Register this project as time listener instead of keyframe object.<br>
 *					04.07.00, 1.10 revised (kp) Made keyframe object the dynamic geometry.<br>
 *					00.00.99, 1.00 created (kp)
 */
public class PjKeyframe extends PjProject {
	private		static String			m_defaultModel		= "models/cmc/Lawson_3_90_60_Anim.*.byu";
	private		static int				m_defaultNumKeys	= 5;

	protected	PsKeyframe []			m_keyframe;
	protected	String					m_fileName;
	protected	int						m_numKeys;
	protected	PsAnimation				m_anim;

	public PjKeyframe() {
		super("Keyframe Animation");
		// Show animation panel
		m_anim = new PsAnimation();
		m_anim.enableKeys(true);
		setAnimation(m_anim);

		if (getClass() == PjKeyframe.class)
		  init();
	}
	public void init() {
		super.init();
	}
	public void start() {
		PvViewerIf viewer = getViewer();
		if (m_fileName == null) {
			m_fileName = viewer.getParameter("Model");
			try {
				String num = viewer.getParameter("Number");
				if (num != null)
					m_numKeys = Integer.parseInt(num);
			} catch (NumberFormatException e) {
				m_numKeys = 1;
			}
		}
		if (m_fileName == null)
			setFileName(PsConfig.getCodeBase()+m_defaultModel, m_defaultNumKeys);
		if (load()) {
			// If applet parameter does not forbid showing of animation panel
			// then show it now:
			String panelVis	= viewer.getParameter("Animation");
			if (panelVis==null || panelVis.equalsIgnoreCase("show"))
				m_anim.getAnimationPanel().setVisible(true);
		}
		super.start();
	}
	public String getFileName()		{ return m_fileName; }
	public void setFileName(String fileName, int numKeys) {
		if (fileName != null) {
			m_fileName	= fileName;
			m_numKeys	= numKeys;
		} else {
			m_fileName	= PsConfig.getCodeBase()+m_defaultModel;
			m_numKeys	= m_defaultNumKeys;
		}
	}
	public boolean load() {
		if (m_fileName == null) {
			if (PsDebug.WARNING) PsDebug.warning("missing file name to load");
			return false;
		}
		PgGeometry geom;
		if (m_keyframe != null) {
			for (int i=0; i<m_keyframe.length; i++) {
				geom = m_keyframe[i].getDynamic();
				removeGeometry(geom);
				m_anim.removeTimeListener(m_keyframe[i]);
				// Reset the keyframe object
				m_keyframe[i].init();
			}
			m_keyframe = null;
		}
		
		double startTime	= 0.;
		double endTime		= 100.;
		double time			= startTime;
		double timeIncr	= (endTime - startTime)/(m_numKeys - 1.);
		String baseName	= PsUtil.getFileName(m_fileName);
		
		String [] comp		= PuString.splitString(m_fileName, '*');
		if (comp==null || comp.length!=2) {
			if (PsDebug.WARNING) PsDebug.warning("wrong syntax, fileName = "+m_fileName);
			return false;
		}
		int maxLen	= String.valueOf(m_numKeys).length();
		int numAnim	= -1;
		for (int i=0; i<m_numKeys; i++) {
			String num	= String.valueOf(i+1);
			for (int k=num.length(); k<maxLen; k++)
				num = "0"+num;
			String name = comp[0]+num+comp[1];
			PgLoader loader = new PgLoader();
			PgGeometry [] geomArr = loader.loadGeometry((PgGeometry [])null, name);
			if (geomArr==null || geomArr.length==0) {
				if (PsDebug.WARNING) PsDebug.warning("failed loading file = "+name);
				return false;
			}
			// Do initialization after geometries of first keyframe are loaded.
			if (i == 0) {
				numAnim		= geomArr.length;
				m_keyframe	= new PsKeyframe[numAnim];
				for (int j=0; j<numAnim; j++)
					m_keyframe[j] = new PsKeyframe();
			} else if (numAnim != geomArr.length) {
				if (PsDebug.WARNING) PsDebug.warning("different number of geometries in file = "+name);
				return false;
			}
			for (int j=0; j<numAnim; j++) {
				int pos = m_keyframe[j].addKey(geomArr[j], time);
				// Check if i-th geometries are of same type in each frame.
				if (pos == -1) {
					if (PsDebug.WARNING) PsDebug.warning("geometry of different type: key="+i+", geom="+j);
					return false;
				}
			}
			time += timeIncr;
		}

		for (int j=0; j<numAnim; j++) {
			m_keyframe[j].setTime(startTime);
			if (numAnim == 1)
				m_keyframe[j].setName(baseName);
			else
				m_keyframe[j].setName(baseName+"["+j+"]");
			// Register the keyframe as time listener.
			m_anim.addTimeListener(m_keyframe[j]);
			// Add dynamic geometry to project and display.
			addGeometry(m_keyframe[j].getDynamic());
		}
		// Select the dynamic geometry of the first keyframe.
		selectGeometry(m_keyframe[0].getDynamic());
		
		m_anim.setName(baseName);
		m_anim.update(m_anim);
		return true;
	}

	/** Update this project. */
	public boolean update(Object object) {
		if (PsDebug.NOTIFY) PsDebug.notify("called");
		return super.update(object);
	}
}
