/*
 * ???: Aug 16, 2005
 *
 */

import java.util.HashMap;
import java.util.Iterator;
import java.util.Vector;

/**
 * @author isomura
 *
 */
public class AclAmpParser {

	// Header
	private int ver;
	private int rbit;
	private int fs;
	private int tb;
	private int sens1;
	private int sens2;
	private int readCycle;
	private int sensorCycle;
	private int compCycle;
	private int ctimeSpan;

	// Current Sensing Value
	private float voltage;
	private int movement;
	private int temperature;
	private int light;
	private int reserve;

	private static final String[] sensorNames = {"No Compressed Data", "Temperature", "Light", "Movement"};
	public static final int NO_COMPRESSED_DATA = 0;
	public static final int TEMPERATURE = 1;
	public static final int LIGHT = 2;
	public static final int MOVEMENT = 3;

	private static final String[] fieldStrength = {"smaller than -12 dBm", "between -12 and -5 dBm","between -4 and 4 dBm","larger than 5 dBm"};

	private HashMap sensorData = new HashMap();
	private Vector history1 = new Vector();
	private Vector history2 = new Vector();

	public class HistoryElement
	{
		private int mean, min, max;

		public int getMean() {
			return mean;
		}

		public int getMin() {
			return min;
		}

		public int getMax() {
			return max;
		}

		public HistoryElement(int data, int last, int sensor) {
			if(sensor == NO_COMPRESSED_DATA) {			// No compressed data
				mean = 0;
				min = 0;
				max = 0;
			} else if(sensor == TEMPERATURE) {	// Temperature
				mean = data;
				min = 0;
				max = 0;
			} else if(sensor == LIGHT) {	// Light
				int meanMSB = (data>>4)&0x0f;
				int minmaxLSB = data&0x0f;

				mean = meanMSB<<4;
				min = mean - (minmaxLSB>>1);
				max = mean + (minmaxLSB>>1);

				//if(meanMSB == last>>4) mean += last&0x0f;	// Add lower bits
			} else if(sensor == MOVEMENT) {	// Movement
				int meanMSB = (data>>4)&0x0f;
				int minmaxMSB = data&0x0f;

				mean = meanMSB<<4;
				min = mean - (minmaxMSB<<3);
				max = mean + (minmaxMSB<<3);

				//if(meanMSB == last>>4) mean += last&0x0f;	// Add lower bits
			} else {

			}
		}

		public HistoryElement(int m, int v, int last, int sensor) {
			mean = m<<4;
			min = mean - (v<<3);
			max = mean + (v<<3);

			if(m == last>>4) mean += last&0x0f;	// Add lower bits
		}
	}


	public Vector getHistory1() {
		return history1;
	}
	public Vector getHistory2() {
		return history2;
	}

	public int getReadCycle() {
		return readCycle;
	}
	public int getSensorCycle() {
		return sensorCycle;
	}
	public int getCompCycle() {
		return compCycle;
	}
	public int getCtimeSpan() {
		return ctimeSpan;
	}

	public int getSens1() {
		return sens1;
	}
	public int getSens2() {
		return sens2;
	}
	public String getConfigSensor1() {
		if(sens1 < sensorNames.length)
			return sensorNames[sens1];
		else
			return null;
	}
	public String getConfigSensor2() {
		if(sens2 < sensorNames.length)
			return sensorNames[sens2];
		else
			return null;
	}

	public int getVer() {
		return ver;
	}
	public int getFs() {
		return fs;
	}
	public String getFieldStrength() {
		if(fs < fieldStrength.length)
			return fieldStrength[fs];
		else
			return null;
	}
	public int getTb() {
		return tb;
	}

	public int getLight() {
		return light;
	}
	public int getMovement() {
		return movement;
	}

	public int getTemperature() {
		return temperature;
	}
	public float getVoltage() {
		return voltage;
	}

	public AclAmpParser(byte[] data) {

		try{
			// Header
			ver = (data[0]>>6)&0x07;
			fs = (data[0]>>3)&0x03;
			tb = 18<<(data[0]&0x07);

			//sens1 = (data[1]>>4)&0x0F;
			sens1 = MOVEMENT;		// uPart sends movement data even if sens1 = 0
			sens2 = data[1]&0x0F;

			readCycle = (data[2]>>4)&0x0F;	//half byte @ 2.5
			sensorCycle = tb<<readCycle;

			compCycle = data[2]&0x0F;	// half byte @ 2
			ctimeSpan = sensorCycle<<compCycle;

			// Current Data
			voltage = (float)(data[3]&0xFF) / 10; //half byte @ 3: fixed point w/ precission 1
			movement = (data[4]&0xFF);
			temperature = (data[5]&0xFF);
			light = (data[6]&0xFF);

			sensorData.put(sensorNames[3], new Integer(movement));
			sensorData.put(sensorNames[1], new Integer(temperature));
			sensorData.put(sensorNames[2], new Integer(light));
			sensorData.put(sensorNames[0], new Integer(0));
			reserve = (data[7]&0xFF);

			// Hisotry Data
			if(sens2 != 0) {
				// save last data in order to smooth curve w/ LSB of last value
				int last1 = 0, last2 = 0;
				if(sens1 < sensorNames.length)
					last1 = ((Integer)sensorData.get(sensorNames[sens1])).intValue();
				if(sens2 < sensorNames.length)
					last2 = ((Integer)sensorData.get(sensorNames[sens2])).intValue();

				for(int i = 8; i + 1 < data.length; i += 2) {
					HistoryElement h1 = new HistoryElement(data[i], last1, sens1);

					HistoryElement h2 = new HistoryElement(data[i+1], last2, sens2);

					history1.add(h1);
					history2.add(h2);

					last1 = h1.getMean();
					last2 = h2.getMean();
				}
			}
		}catch(Exception E){
			for(int i=0 ; i< data.length;i++ )System.err.print(data[i]);
			System.err.print("\n");

		}
	}

/*
	public static void main(String[] args) {
		String data = "19 2 19 29 1 27 244 0 0 95 0 93 0 95 0 95 0 94 0 93 0 94 0 91 0 94 0 95 1 241 1 240";
		//AclAmpParser parser = new AclAmpParser(edu.teco.particle.Utils.stringToByte(data, " "));

		System.out.println(data);
		System.out.println("Ver = " + parser.getVer());
		System.out.println("FieldStrength = " + parser.getFieldStrength());
		System.out.println("TimeBase = " + parser.getTb());
		System.out.println("Sensor1 = " + parser.getConfigSensor1());
		System.out.println("Sensor2 = " + parser.getConfigSensor2());
		System.out.println("ReadCyc = " + parser.getReadCycle());
		System.out.println("SensorCyc = " + parser.getSensorCycle());
		System.out.println("CompCyc = " + parser.getCompCycle());
		System.out.println("CtimeSpan = " + parser.getCtimeSpan());
		System.out.println("Voltage = " + parser.getVoltage());
		System.out.println("Movement = " + parser.getMovement());
		System.out.println("Temperature = " + parser.getTemperature());
		System.out.println("Light = " + parser.getLight());

		System.out.println("History of " + parser.getConfigSensor1());
		Iterator hit = parser.getHistory1().iterator();
		int count = 0;
		while(hit.hasNext()) {
			HistoryElement he = (HistoryElement)hit.next();
			System.out.println(++count + " mean = " + he.getMean() +
					", min = " + he.getMin() +
					", max = " + he.getMax());
		}

		System.out.println("History of " + parser.getConfigSensor2());
		hit = parser.getHistory2().iterator();
		count =0;
		while(hit.hasNext()) {
			HistoryElement he = (HistoryElement)hit.next();
			System.out.println(++count + " mean = " + he.getMean() +
					", min = " + he.getMin() +
					", max = " + he.getMax());
		}
	}
*/
}

