package seed.minerva.optics.collection;

import binaryMatrixFile.BinaryMatrixWriter;
import jafama.FastMath;
import seed.minerva.optics.Util;
import seed.minerva.optics.surfaces.Plane;
import seed.minerva.optics.types.Intersection;

/** Collects statistics of the angle of rays through a given surface */
public class PlaneAngleInfo implements IntersectionProcessor {
	private Plane targetPlane;
	
	private double sumN, sumU, sumR, sumI;
	BinaryMatrixWriter dbgOut = null;
	
	public PlaneAngleInfo(Plane target) {
		this.targetPlane = target;
	}
	
	@Override
	public void nextIntersection(Intersection hit) {
		Intersection targetHit = hit.incidentRay.findFirstEarlierIntersection(targetPlane);
		if(targetHit == null)
			return;
		
		double I = hit.incidentRay.endIntensity();
		double N = Util.dot(targetHit.incidentRay.dir, targetPlane.getNormal());
		double U = Util.dot(targetHit.incidentRay.dir, targetPlane.getUp());
		double R = Util.dot(targetHit.incidentRay.dir, targetPlane.getRight());
		sumN += I * N;
		sumU += I * U;
		sumR += I * R;
		sumI += I;
		
		if(dbgOut != null)
			dbgOut.writeRow(I, N, U, R, targetHit.incidentRay.dir);
		
	}
	
	public void dump() {
		System.out.println("Angles through plane '"+targetPlane.getName()+"': mean = " 
						+ getMeanAngle()*180/Math.PI + "°");
				
	}
	
	public double getMeanAngle() {
		return FastMath.atan2(FastMath.sqrt(sumU*sumU + sumR*sumR), sumN);
	}
	
	/** @return the mean vector at the intersection, in cartesian space */
	public double[] getMeanVector() {
		double N[] = targetPlane.getNormal();
		double U[] = targetPlane.getUp();
		double R[] = targetPlane.getRight();
		
		return Util.reNorm(new double[]{
				sumN/sumI * N[0] + sumU/sumI * U[0] + sumR/sumI * R[0],
				sumN/sumI * N[1] + sumU/sumI * U[1] + sumR/sumI * R[1],
				sumN/sumI * N[2] + sumU/sumI * U[2] + sumR/sumI * R[2]  
		});
		
	}
	
	public void reset(){
		sumN = 0;
		sumU = 0;
		sumR = 0;
		sumI = 0;
	}
	
	public void setDbgOut(String fileName) {
		if(this.dbgOut != null)
			this.dbgOut.close();
		this.dbgOut = new BinaryMatrixWriter(fileName, 7);
	}
	
}
