


/* Feel free to read this struct's members. Feel free to alter the contents of 
the isometry and the data. */
typedef struct lightLight lightLight;
struct lightLight {
    isoIsometry isometry;
    int dataSize;
    void *data;
	/* Given a light with the specified modeling isometry and data. Given a ray 
	x(t) = p + t * u in world coordinates. Given that ray's intersection with a 
	body. Outputs the light's lighting at the point corresponding to the 
	intersection's start time. */
    void (*getLighting)(
        const isoIsometry *isom, const void *data, const double p[3], 
        const double u[3], const rayIntersection *inter, rayLighting *lighting);
};

/* Initializes the light, returning an error code (0 on success). On success, 
don't forget to lightFinalize when you're done. The isometry is initialized to 
the trivial isometry. The data are allocated but not initialized. */
int lightInitialize(
        lightLight *light, int dataSize, 
        void (*getLighting)(
        	const isoIsometry *isom, const void *data, const double p[3], 
        	const double u[3], const rayIntersection *inter, 
        	rayLighting *lighting)) {
    if (dataSize > 0) {
		light->data = malloc(dataSize);
		if (light->data == NULL) {
			fprintf(stderr, "error: lightInitialize: malloc failed\n");
			return 1;
		}
    }
    light->dataSize = dataSize;
    light->getLighting = getLighting;
    double transl[3] = {0.0, 0.0, 0.0};
    isoSetTranslation(&(light->isometry), transl);
    double rot[3][3] = {{1.0, 0.0, 0.0}, {0.0, 1.0, 0.0}, {0.0, 0.0, 1.0}};
    isoSetRotation(&(light->isometry), rot);
    return 0;
}

/* Releases the resources backing the light. */
void lightFinalize(lightLight *light) {
	if (light->dataSize > 0)
		free(light->data);
}

/* Using the light's properties, outputs the appropriate rayLighting. */
void lightGetLighting(
        const lightLight *light, const double p[3], const double u[3], 
        const rayIntersection *inter, rayLighting *lighting) {
    light->getLighting(&(light->isometry), light->data, p, u, inter, lighting);
}

/* Computes the diffuse and specular terms for this material at this 
intersection result, for a single light. Outputs, in the diffSpec argument, the 
sum of the diffuse and specular terms. */
void lightGetDiffuseSpecular(
        const rayIntersection *inter, const rayMaterial *mater, 
        const rayLighting *lighting, const double uCamera[3], 
        double diffSpec[3]) {
    
}


