package com.ociweb.pronghorn.iot;

import java.util.ArrayList;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import com.ociweb.gl.api.Behavior;
import com.ociweb.gl.impl.stage.ReactiveManagerPipeConsumer;
import com.ociweb.iot.hardware.HardwareConnection;
import com.ociweb.iot.hardware.HardwareImpl;
import com.ociweb.iot.hardware.impl.grovepi.GrovePiConstants;
import com.ociweb.iot.maker.AnalogListener;
import com.ociweb.iot.maker.DigitalListener;
import com.ociweb.iot.maker.I2CListener;
import com.ociweb.iot.maker.Port;
import com.ociweb.iot.maker.RotaryListener;
import com.ociweb.pronghorn.iot.schema.I2CResponseSchema;
import com.ociweb.pronghorn.pipe.Pipe;
import com.ociweb.pronghorn.pipe.PipeReader;
import com.ociweb.pronghorn.stage.scheduling.GraphManager;
//import com.ociweb.pronghorn.util.ma.MAAvgRollerLongTest;
import com.ociweb.pronghorn.util.ma.MAvgRollerLong;

public class DexterGrovePiReactiveListenerStage extends ReactiveListenerStageIOT{


	private static final Logger logger = LoggerFactory.getLogger(DexterGrovePiReactiveListenerStage.class);

	public DexterGrovePiReactiveListenerStage(GraphManager graphManager, Behavior listener, 
			                                  Pipe<?>[] inputPipes, Pipe<?>[] outputPipes, 
			                                  ArrayList<ReactiveManagerPipeConsumer> consumers,
			                                  HardwareImpl hardware, int parallelInstance) {
		super(graphManager, listener, inputPipes, outputPipes, consumers, hardware, parallelInstance);
	}


	@Override
	protected void processI2CMessage(Object listener, Pipe<I2CResponseSchema> p) {
		if (listener instanceof I2CListener || listener instanceof DigitalListener || listener instanceof AnalogListener) {
			int addr = PipeReader.readInt(p, I2CResponseSchema.MSG_RESPONSE_10_FIELD_ADDRESS_11);
			int register = PipeReader.readInt(p, I2CResponseSchema.MSG_RESPONSE_10_FIELD_REGISTER_14);
			long time = PipeReader.readLong(p, I2CResponseSchema.MSG_RESPONSE_10_FIELD_TIME_13);

			byte[] backing = PipeReader.readBytesBackingArray(p, I2CResponseSchema.MSG_RESPONSE_10_FIELD_BYTEARRAY_12);
			int position = PipeReader.readBytesPosition(p, I2CResponseSchema.MSG_RESPONSE_10_FIELD_BYTEARRAY_12);
			int length = PipeReader.readBytesLength(p, I2CResponseSchema.MSG_RESPONSE_10_FIELD_BYTEARRAY_12);
			int mask = PipeReader.readBytesMask(p, I2CResponseSchema.MSG_RESPONSE_10_FIELD_BYTEARRAY_12);

			
			logger.debug("Pi listener consuming I2C message from addr: {}",addr);

			if(listener instanceof DigitalListener && addr==4 && length==1){
				int tempValue = backing[position&mask];

				int connector = GrovePiConstants.REGISTER_TO_PORT[register];
				assert(connector!=-1);

				commonDigitalEventProcessing(Port.DIGITALS[connector], time, tempValue, (DigitalListener)listener);

			}
			else if(listener instanceof AnalogListener && addr==4 && length==3){

				int high = (int)backing[(position+1)&mask];
				int low = (int)backing[(position+2)&mask];

				if (-1==high && -1==low) {

					//no data was available, we may be polling too fast

				} else {
					int tempValue =  (high<<8) | (0xFF&low);
					int connector = GrovePiConstants.REGISTER_TO_PORT[register];
					assert(connector>=0) :"bad connector "+connector;

					//The dexter grove only has 10 bit analog to digital converter so we should never find a value larger than 1024
					if ((tempValue<0) || (tempValue>1024)) {
						logger.error("connection {} bad i2c result array [{}, {}, {}] ",connector,backing[(position+0)&mask],backing[(position+1)&mask],backing[(position+2)&mask]);
					} else {						
						commonAnalogEventProcessing(Port.ANALOGS[connector], time, tempValue, (AnalogListener)listener);
					}
				}
			}else if(listener instanceof RotaryListener && addr==4 && length==2){
				byte[] tempArray = {backing[(position+0)&mask], backing[(position+1)&mask]};
				int tempValue = (((int)tempArray[0])<<8) | (0xFF&((int)tempArray[1]));
				((RotaryListener)listener).rotaryEvent(Port.DIGITALS[register], time, tempValue, 0, 0);
			} else if (listener instanceof I2CListener){ //must be last so we only do this if one of the more specific conditions were not met first.
				super.commonI2CEventProcessing((I2CListener)listener, addr, register, time, backing, position, length, mask);;
				logger.debug("Creating I2C event");
			}
		}
	}
}


@@ -369,16 +369,202 @@
 stants;%0A
+import com.ociweb.iot.impl.AnalogListenerBase;%0Aimport com.ociweb.iot.impl.DigitalListenerBase;%0Aimport com.ociweb.iot.impl.I2CListenerBase;%0Aimport com.ociweb.iot.impl.RotaryListenerBase;%0A
 import c
@@ -1832,33 +1832,41 @@
 ceof I2CListener
- 
+Base %0A%09%09%09
 %7C%7C listener inst
@@ -1887,17 +1887,25 @@
 Listener
- 
+Base %0A%09%09%09
 %7C%7C liste
@@ -1933,16 +1933,20 @@
 Listener
+Base
 ) %7B%0A%09%09%09i
@@ -2739,32 +2739,36 @@
  DigitalListener
+Base
  && addr==4 && l
@@ -3000,32 +3000,36 @@
 (DigitalListener
+Base
 )listener);%0A%0A%09%09%09
@@ -3067,32 +3067,36 @@
 f AnalogListener
+Base
  && addr==4 && l
@@ -3903,32 +3903,36 @@
  (AnalogListener
+Base
 )listener);%0A%09%09%09%09
@@ -3986,16 +3986,20 @@
 Listener
+Base
  && addr
@@ -4185,32 +4185,36 @@
 ((RotaryListener
+Base
 )listener).rotar
@@ -4314,16 +4314,20 @@
 Listener
+Base
 )%7B //mus
@@ -4461,16 +4461,20 @@
 Listener
+Base
 )listene

fix listeners usages