/** Represents information about the specular properties of a
 * surface, including how reflective or refractive the surface
 * is. */
public class Material {
	public static final Material BRASS = new Material("brass",
			new ColorVector(0.329412, 0.223529, 0.027451),
			new ColorVector(0.780392, 0.568627, 0.113725),
			new ColorVector(0.992157, 0.941176, 0.807843), 32, 0.3,
			ColorVector.ZERO, 1.0);
	public static final Material GOLD = new Material("gold",
			new ColorVector(0.24725, 0.1995, 0.0745),
			new ColorVector(0.75164, 0.60648, 0.22648),
			new ColorVector(0.628281, 0.555802, 0.366065), 51.2, 0.3,
			ColorVector.ZERO, 1.0);
	public static final Material SILVER = new Material("silver",
			ColorVector.ONE.scale(0.23125),
			ColorVector.ONE.scale(0.2775),
			ColorVector.ONE.scale(0.773911), 89.6, 0.8,
			ColorVector.ZERO, 1.0);
	public static final Material BLACK_PLASTIC = new Material("black",
			new ColorVector(0.0, 0.0, 0.0),
			new ColorVector(0.01, 0.01, 0.01),
			new ColorVector(0.50, 0.50, 0.50), 32, 0.1,
			ColorVector.ZERO, 1.0);
	public static final Material WHITE_PLASTIC = new Material("white",
			new ColorVector(0.8, 0.8, 0.8),
			new ColorVector(0.8, 0.8, 0.8),
			new ColorVector(0.50, 0.50, 0.50), 32, 0.1,
			ColorVector.ZERO, 1.0);
	public static final Material GLASS = new Material("glass",
			ColorVector.ZERO,
			ColorVector.ZERO,
			ColorVector.ONE.scale(0.3), 32, 0.4,
			ColorVector.ONE, 0.8);

	private String descriptor = "??";
	private ColorVector amb  = null;
	private ColorVector diff = null;
	private ColorVector spec = null;
	private double specExp   = 1.0;
	private ColorVector reflectivity = null;
	private ColorVector refractivity = null;
	private double refractiveIndex = 1.0;
	
	private Material(String desc,
			ColorVector amb,
			ColorVector diff,
			ColorVector spec, double specExp, double reflectProportion,
			ColorVector refractivity, double refractiveIndex) {
		this.amb  = amb;
		this.diff = diff;
		this.spec = spec;
		this.specExp = specExp;
		this.reflectivity = spec.scale(reflectProportion);
		this.refractivity = refractivity;
		this.refractiveIndex = refractiveIndex;
	}

	public Material() { }

	/** Returns a color vector representing how reflective this
	 * material is for the three color components. */
	public ColorVector getReflectivity() {
		return reflectivity;
	}

	/** Returns a color vector representing how refractive this
	 * material is for the three color components. */
	public ColorVector getRefractivity() {
		return refractivity;
	}

	/** Returns this material's refractive index, a number
	 * between 0.0 and 1.0, with a vacuum being 1.0. */
	public double getRefractiveIndex() {
		return refractiveIndex;
	}
	
	/** Returns this material's specular exponent, as per
	 * Blinn's alternative to the Phong model. */
	public double getSpecularExponent() { return specExp; }

	/** Returns the color of this surface given the amount of
	 * ambient, diffuse, and specular light computed to fall on
	 * the surface. */
	public Color getColor(double ambAmt, double diffAmt, double specAmt) {
		Color ret = amb.scale(ambAmt)
			.add(diff.scale(diffAmt))
			.add(spec.scale(specAmt))
			.scale(Color.WHITE);
		return ret;
	}
}
