// (C)2007 Attila Kovacs <attila@submm.caltech.edu>

public class LabocaFrame {
	LabocaScan scan;
	double MJD, RA, DEC, LST, AZ, EL, dX, dY, PA, cosPA, sinPA, cosDEC, cosEL, he3Temp, chopperPosition;
	double transmission = 1.0;
	double relativeWeight = 1.0;
	double dependents = 0.0;
	double lastDependents = 0.0;
	double temp;
	double dof = 1.0;
	float[] data;
	byte[] sampleFlag;
	int flag = 0;
	int chopperPhase;
	
	public LabocaFrame(LabocaScan parent) { scan = parent; }

	static double longitude;
	static double latitude;
	static double skydipFactor = 1.0;

	double zenithTau = 0.0;

	public void slim(LabocaPixel[] newPixels) {
		float[] reduced = new float[newPixels.length];
		byte[] newSampleFlag = new byte[newPixels.length];

		for(int k=0; k<newPixels.length; k++) {
			reduced[k] = data[newPixels[k].index];
			newSampleFlag[k] = sampleFlag[newPixels[k].index];
		}
			
		data = reduced;
		sampleFlag = newSampleFlag;
	}


	public void calc() {
		sampleFlag = new byte[data.length];

		if(LST < -900.0*Unit.deg) flag |= SKIP_SOURCE;
		else if(RA < -900.0*Unit.deg) flag |= SKIP_SOURCE;
		else if(DEC < -900.0*Unit.deg) flag |= SKIP_SOURCE;
		else if(AZ < -900.0*Unit.deg) flag |= SKIP_SOURCE;
		else if(EL < -900.0*Unit.deg) flag |= SKIP_SOURCE;
		else if(dX < -900.0*Unit.deg) flag |= SKIP_SOURCE;
		else if(dY < -900.0*Unit.deg) flag |= SKIP_SOURCE;
		else {
			cosDEC = Math.cos(DEC); 
			cosEL = Math.cos(EL);

			sinPA = Math.sin(AZ) * Math.cos(latitude) / cosDEC;
			cosPA = (Math.sin(latitude) - Math.sin(DEC)*Math.sin(EL))/(cosDEC * cosEL);
			
			PA = Math.atan2(sinPA, cosPA);
		}
		
		if(scan.isNativeEquatorial) {
			// Assuming that dX and dY are in RADEC...
			double dAZ = -dX * cosPA - dY * sinPA;
			double dEL = dY * cosPA - dX * sinPA;
			dX = dAZ;
			dY = dEL;
		}
			
		setZenithTau(zenithTau);

	}
	
	public void setZenithTau(double value) {
		zenithTau = value;
		transmission = Math.exp(-skydipFactor * zenithTau/Math.sin(EL));		
	}

	private Vector2D offsets = new Vector2D();
	private SphericalCoordinates coords = new SphericalCoordinates();
	
	public final synchronized SphericalCoordinates getCoords(LabocaPixel pixel) {
		// The proper GLS convention uses actual cos(DEC)
		//coords.setLongitude(-RA + (cosPA * pixel.position.x + sinPA * pixel.position.y) / scan.equatorial.cosLat);
		// However, APECS uses cos(DEC0)
		coords.setLongitude(-RA + (cosPA * pixel.position.x + sinPA * pixel.position.y) / scan.equatorial.cosLat);
		coords.setLatitude(DEC + (cosPA * pixel.position.y - sinPA * pixel.position.x));
		return coords;
	}

	
	public final synchronized Vector2D getdAZdEL(LabocaPixel pixel) {
		offsets.x = dX + pixel.position.x;
		offsets.y = dY + pixel.position.y;
		return offsets;
	}
	
	public static byte SAMPLE_SOURCE_BLANK = 1<<0;
	public static byte SAMPLE_SPIKE = 1<<1;
	public static byte SAMPLE_SPIKY_NEIGHBOUR = 1<<2;
	public static byte SAMPLE_SPIKY_FEATURE = 1<<3;
	public static byte SAMPLE_SPIKE_FLAGS = (byte) (SAMPLE_SPIKE | SAMPLE_SPIKY_NEIGHBOUR | SAMPLE_SPIKY_FEATURE);
	public static byte SAMPLE_SKIP = 1<<4;
	
	public static int FLAG_DISCARD = 1<<0;
	public static int FLAG_SPIKY = 1<<1;
	public static int FLAG_DOF = 1<<2;
	public static int FLAG_WEIGHT = 1<<3;

	public static int SKIP_SOURCE = 1<<8;
	public static int SKIP_MODELS = 1<<9;
	public static int SKIP_WEIGHTING = 1<<10;
	//public static int SKIP_SYNCHING = 1<<11;
	

	public static int BAD_DATA = FLAG_SPIKY | FLAG_DISCARD;
	public static int MODELING_FLAGS = SKIP_MODELS | BAD_DATA | FLAG_DOF | FLAG_WEIGHT;
	public static int SOURCE_FLAGS = SKIP_SOURCE | MODELING_FLAGS;
	public static int WEIGHTING_FLAGS = SKIP_WEIGHTING | MODELING_FLAGS;
	
	
}