/** Represents a factor by which to multiply a color's components,
 * including different factors for each component. */
public class ColorVector {
	public static final ColorVector ZERO = new ColorVector(0.0f, 0.0f, 0.0f);
	public static final ColorVector ONE = new ColorVector(1.0f, 1.0f, 1.0f);

	private float r;
	private float g;
	private float b;
	private double norm = -1.0;

	/** Constructs a color vector with the given component
	 * multipliers. */
	public ColorVector(double r, double g, double b) {
		this((float) r, (float) g, (float) b);
	}

	/** Constructs a color vector with the given component
	 * multipliers. */
	public ColorVector(float r, float g, float b) {
		this.r = clamp(r, 0.0f, 1.0f);
		this.g = clamp(g, 0.0f, 1.0f);
		this.b = clamp(b, 0.0f, 1.0f);
	}

	/** Returns the norm - ie, length - of this color vector.  */
	public double getNorm() {
		if(norm < 0) {
			norm = Math.sqrt(r * r + g * g + b * b);
		}
		return norm;
	}

	public String toString() {
		return "ColorVector[" + r + "," + g + "," + b + "]";
	}

	/** Returns the red color muliplier. */
	public float getRed()   { return r; }
	/** Returns the green color muliplier. */
	public float getGreen() { return g; }
	/** Returns the blue color muliplier. */
	public float getBlue()  { return b; }

	/** Returns a color vector whose multipliers are the sum of
	 * this color's multipliers and the parametere color's
	 * multipliers. */
	public ColorVector add(ColorVector other) {
		return new ColorVector(this.r + other.r,
				this.g + other.g,
				this.b + other.b);
	}

	/** Returns a color vector whose multipliers are all scaled
	 * by the given scalar. */
	public ColorVector scale(double scalar) {
		return new ColorVector(this.r * scalar,
				this.g * scalar,
				this.b * scalar);
	}

	/** Returns a color vector whose multipliers are the product of
	 * this color's multipliers and the parameter color's
	 * multipliers. */
	public ColorVector scale(ColorVector other) {
		return new ColorVector(this.r * other.r,
				this.g * other.g,
				this.b * other.b);
	}

	/** Returns a color whose components have been scaled by
	 * this color vector's multipliers. */
	public Color scale(Color other) {
		return new Color(this.r * other.getRed(),
				this.g * other.getGreen(),
				this.b * other.getBlue());
	}

	private static float clamp(float value, float min, float max) {
		if(value < min) return min;
		if(value > max) return max;
		return value;
	}
}
