package j3deditor.bin.hierarchy.util;


import j3deditor.bin.hierarchy.J3DeObject;
import j3deditor.bin.hierarchy.J3DeScene;
import j3deditor.bin.hierarchy.J3DeShape3D;

import j3deditor.bin.util.Utilities;

import com.sun.j3d.loaders.objectfile.ObjectFile;

import java.util.ArrayList;
import java.util.Enumeration;
import java.util.Hashtable;

import javax.media.j3d.BranchGroup;
import javax.media.j3d.Shape3D;


/**
 * Tool for importing objects from OBJ
 * file to specified scene.
 * Uses <code>com.sun.j3d.loaders.objectfile.ObjectFile</code>.
 *
 * @author Risto Seene
 * 
 * @see com.sun.j3d.loaders.objectfile.ObjectFile
 */
public class ObjImporter extends HierarchyWorker{

	/** scene the objects will be imported to */
	private J3DeScene scene;

	private String filePath;


	/**
	 * Creates an instance of <code>ObjLoader</code>
	 * which is able to import objects to the given scene.
	 *
	 * @param scene
	 *	an instance of <code>J3DeScene</code>
	 *	this importer can import to
	 */
	public ObjImporter(J3DeScene scene){
		this.scene = scene;
	}


	/**
	 * Opens the given OBJ file and imports
	 * objects to the scene associated to this importer.
	 *
	 * @param filePath
	 *	path of a OBJ file the objects will be imported from
	 *
	 * @see com.sun.j3d.loaders.objectfile.ObjectFile#load(String filePath)
	 */
	public void loadFile(String filePath){
		this.filePath = filePath;
		this.execute();
	}


	/**
	 * Performes the importation process in a background thread.
	 * 
	 * @return nothing
	 * @throws Exception
	 * 	if unable to import
	 */
	@Override
	protected Void doInBackground() throws Exception{
		ObjectFile obj = new ObjectFile();

		try{
			Hashtable objectTable = obj.load(filePath).getNamedObjects();
			buildScene(objectTable);
		} catch(Throwable t){
			Utilities.out.throwError(t);
		}

		return null;
	}


	/**
	 * Adds the imported objects to the scene.
	 * For every object creates an instance of <code>J3DeShape3D</code>,
	 * applies the loaded object to it and adds it to scene.
	 *
	 * @param objectTable
	 *	hashtable of imported objects and their names
	 */
	private void buildScene(Hashtable objectTable) throws Exception{
		ArrayList<J3DeObject> objects = new ArrayList<J3DeObject>();

		for(Enumeration e = objectTable.keys(); e.hasMoreElements(); ){
			try{
				Object key = e.nextElement();
				Shape3D obj = ((Shape3D)(objectTable.get(key)));
				((BranchGroup)obj.getParent()).removeChild(obj);

				J3DeObject j3deObj = new J3DeShape3D(obj);
				j3deObj.setName((String)key);
				objects.add(j3deObj);
			} catch(Throwable t){
				Utilities.out.throwWarning(t);
			}
		}

		J3DeObject[] j3deobjects = new J3DeObject[objects.size()];
		for(int i = 0; i < objects.size(); i++){
			j3deobjects[i] = objects.get(i);
		}
		scene.addNewObjects(j3deobjects);
	}


	/**
	 * Notifies all listeners that object(s) have been added to the scene.
	 */
	@Override
	protected void done(){
		super.done();
		notifyListeners(new HierarchyEvent(this, HierarchyEvent.OBJECT_ADDITION));
	}
}
