// PhongMaterial.java -- defines a Phong-illuminated material

package scene.illumination;

import java.awt.*;
import geometry.*;
import java.util.*;
import scene.basicTypes.*;

public class PhongMaterial extends Material {
    Colour kd;          // Diffuse colour (and also its ambient colour)
    Colour ks;          // Colour of specular highlight
    float n;            // phong "power" (as in ks * H.V^n).
    float transparency; // Transparency in range 0 (opaque) to 1 (transparent)
    Colour km;          // Mirror colour, i.e. the multiplier for the mirror reflection
    boolean isReflective = false; // True if any components of km non-zero
    
    public PhongMaterial(Colour kd, Colour ks, float n, Colour km, float transparency) {
        this.kd = kd;
        this.ks = ks;
        this.n = n;
        this.transparency = transparency;
        this.km = km;
        isReflective = (km.red != 0) || (km.green != 0) || (km.blue != 0);
    }
     
    public Colour litColour(Point3f pt, Vector3f normal, Vector3f v, Vector lights) {
        Colour totalColour = new Colour(0,0,0);
        for (Enumeration e = lights.elements(); e.hasMoreElements(); ) { // For each light ...
            Light light = (Light) e.nextElement();
            LightFlux flux = light.illumination(pt);
            totalColour.add(kd.times(flux.ambient));
            if (flux.colour != null) {  				// If the light is not casting a shadow
                float lightFactor = flux.direction.dot(normal);
                if (lightFactor > 0) {					// ... and the surface is facing towards the light
                    if (isReflective == true) {
                    	v = v.negated();
                    	float temp = 2 * normal.dot(v);
                    	Vector3f dir = v.minus(normal.times(temp));
                    	Ray ray = new Ray(pt.minus(dir.times(0.0001f)), dir); 
                    	totalColour.add(km.times(scene.colourAlongRay(ray)));
                    }
                    totalColour.add(kd.times(flux.colour).times(lightFactor));
                    Vector3f h = v.plus(flux.direction).normalised();
                    float specFactor = (float) Math.pow(h.dot(normal), n);
                    totalColour.add(ks.times(flux.colour).times(specFactor));
                }
            }
        }
        return totalColour;
   }
}