package j3deditor.bin.hierarchy;


import j3deditor.bin.hierarchy.util.HNodeType;

import java.awt.Color;

import javax.media.j3d.Appearance;
import javax.media.j3d.Material;

import javax.vecmath.Color3f;


/**
 * Contains and manages an instance of
 * <code>javax.media.j3d.Material</code>.
 *
 * @author Risto Seene
 * 
 * @see javax.media.j3d.Material
 */
public class J3DeMaterial extends HierarchyNode{

	/** number of <code>J3DeMaterial</code> nodes */
	private static long numOfNodes = 0;

	/** actual <code>Material</code> object */
	private Material material;


	/**
	 * Creates an instance of <code>J3DeMaterial</code>
	 * with the <code>Material</code> object from the
	 * given <code>Appearance</code> object.
	 *
	 * @param appearance
	 *	an instance of <code>Appearance</code> which
	 *	material component is not <code>null</code>
	 */
	public J3DeMaterial(Appearance appearance){
		super("Material", HNodeType.MATERIAL, numOfNodes);
		numOfNodes++;

		if(appearance.getMaterial() != null){
			material = appearance.getMaterial();
			setCapabilities();
		} else {
			material = new Material();
			setCapabilities();
			appearance.setMaterial(material);
		}
	}


	/**
	 * sets the capabilities for the <code>Material</code> object.
	 *
	 * <br><ul><li><code>Material.ALLOW_COMPONENT_READ</code></li>
	 * <li><code>Material.ALLOW_COMPONENT_WRITE</code></li></ul>
	 *
	 * @see javax.media.j3d.Material#setCapability(int capability)
	 */
	private void setCapabilities(){
		material.setCapability(Material.ALLOW_COMPONENT_READ);
		material.setCapability(Material.ALLOW_COMPONENT_WRITE);
	}


	/**
	 * Tests if light is used to calculate the appearance of the object
	 * this material describes.
	 *
	 * @return Returns <code>true</code> if lighting is used,
	 *	otherwise <code>false</code>
	 *
	 * @see javax.media.j3d.Material#getLightingEnable()
	 */
	public boolean getLightingEnable(){
		return material.getLightingEnable();
	}


	/**
	 * Specifies if light is used to calculate the appearance of the object
	 * this material describes.
	 *
	 * @param state
	 *	<code>true</code> if lighting is used,
	 *	otherwise <code>false</code>
	 *
	 * @see javax.media.j3d.Material#setLightingEnable(boolean state)
	 */
	public void setLightingEnable(boolean state){
		material.setLightingEnable(state);
	}


	/**
	 * Returns the array of color target names.
	 *
	 * @return Returns the array of color target names
	 */
	public String[] getColorTargetItems(){
		String[] items = new String[5];
		items[0] = "AMBIENT";
		items[1] = "EMISSIVE";
		items[2] = "DIFFUSE";
		items[3] = "SPECULAR";
		items[4] = "AMBIENT AND DIFFUSE";
		return items;
	}


	/**
	 * Returns the current color target of the <code>Material</code> object.
	 *
	 * @return Returns the current color target
	 *
	 * @see javax.media.j3d.Material#getColorTarget()
	 */
	public int getColorTarget(){
		return material.getColorTarget();
	}


	/**
	 * Applies the given color target to the <code>Material</code> object.
	 *
	 * @param colorTarget
	 *	new color target
	 *
	 * @see javax.media.j3d.Material#setColorTarget(int target)
	 */
	public void setColorTarget(int colorTarget){
		material.setColorTarget(colorTarget);
	}


	/**
	 * Returns the diffuse color of the <code>Material</code> object.
	 *
	 * @return Returns the diffuse color
	 *
	 * @see javax.media.j3d.Material#getDiffuseColor(Color3f color)
	 */
	public Color getDiffuseColor(){
		Color3f color = new Color3f();
		material.getDiffuseColor(color);

		return color.get();
	}


	/**
	 * Applies the given diffuse color to the <code>Material</code> object.
	 *
	 * @param color
	 *	new color
	 *
	 * @see javax.media.j3d.Material#setDiffuseColor(Color3f color)
	 */
	public void setDiffuseColor(Color color){
		if(color != null){
			material.setDiffuseColor(new Color3f(color));
		}
	}


	/**
	 * Returns the ambient color of the <code>Material</code> object.
	 *
	 * @return Returns the ambient color
	 *
	 * @see javax.media.j3d.Material#getAmbientColor(Color3f color)
	 */
	public Color getAmbientColor(){
		Color3f color = new Color3f();
		material.getAmbientColor(color);

		return color.get();
	}


	/**
	 * Applies the given ambient color to the <code>Material</code> object.
	 *
	 * @param color
	 *	new color
	 *
	 * @see javax.media.j3d.Material#setAmbientColor(Color3f color)
	 */
	public void setAmbientColor(Color color){
		if(color != null){
			material.setAmbientColor(new Color3f(color));
		}
	}


	/**
	 * Returns the specular color of the <code>Material</code> object.
	 *
	 * @return Returns the specular color
	 *
	 * @see javax.media.j3d.Material#getSpecularColor(Color3f color)
	 */
	public Color getSpecularColor(){
		Color3f color = new Color3f();
		material.getSpecularColor(color);

		return color.get();
	}


	/**
	 * Applies the given specular color to the <code>Material</code> object.
	 *
	 * @param color
	 *	new color
	 *
	 * @see javax.media.j3d.Material#setSpecularColor(Color3f color)
	 */
	public void setSpecularColor(Color color){
		if(color != null){
			material.setSpecularColor(new Color3f(color));
		}
	}


	/**
	 * Returns the emissive color of the <code>Material</code> object.
	 *
	 * @return Returns the emissive color
	 *
	 * @see javax.media.j3d.Material#getEmissiveColor(Color3f color)
	 */
	public Color getEmissiveColor(){
		Color3f color = new Color3f();
		material.getEmissiveColor(color);

		return color.get();
	}


	/**
	 * Applies the given emissive color to the <code>Material</code> object.
	 *
	 * @param color
	 *	new color
	 *
	 * @see javax.media.j3d.Material#setEmissiveColor(Color3f color)
	 */
	public void setEmissiveColor(Color color){
		if(color != null){
			material.setEmissiveColor(new Color3f(color));
		}
	}


	/**
	 * Returns the shininess of the <code>Material</code> object.
	 *
	 * @return Returns the shininess
	 *
	 * @see javax.media.j3d.Material#getShininess()
	 */
	public int getShininess(){
		return (int)(10 * material.getShininess());
	}


	/**
	 * Applies the given shininess to the <code>Material</code> object.
	 *
	 * @param value
	 *	new value shininess
	 *
	 * @see javax.media.j3d.Material#setShininess(float s)
	 */
	public void setShininess(int value){
		material.setShininess(((float)value / 10));
	}

}
