package imseProc.aqui;

import java.nio.DoubleBuffer;
import java.util.Arrays;

import oneLiners.OneLiners;
import org.eclipse.swt.widgets.Composite;
import otherSupport.SettingsManager;
import simpleScope.DoubleBufferDataset;
import sun.reflect.generics.reflectiveObjects.NotImplementedException;
import comedi.ComediDataView;
import comedi.ComediRawDataStore;
import comedi.ComediAsyncReader;
import comedi.ComediRawReadBuffer;
import comedi.DataViewChangedNotification;
import comedi.RawStoreChangedNotification;
import comediJNI.ComediDef;
import imseProc.core.IMSEProc;
import imseProc.core.ImagePipeController;
import imseProc.core.Img;
import imseProc.core.ImgPipe;
import imseProc.core.ImgSink;
import imseProc.core.Triggerable;
import imseProc.graph.GraphUtilSWTControl;

public class AquisitionHanger extends ImgPipe implements ImgSink, Triggerable, RawStoreChangedNotification {

	private ComediAsyncReader comediReader;

	private AquisitionSWTController swtScopeControl;
	
	private String statusText;
	
	private int subDev;
	private int chans[];
	private int range[];
	private int aref;
	private int nScans;
	private int periodNS;
	private int bufLenInScans;

	private String saveSyncObject = "saveSyncObject";
	
	public AquisitionHanger() {
        statusText = "Init OK";        
        updateAllControllers();
	}
	
	public void setAquiParams(int subDev, int chans[], int range[], int aref, int nScans, int periodNS, int bufLenInScans) {
		this.subDev = subDev;
		this.chans = chans;
		this.range = range;
		this.aref = aref;
		this.nScans = nScans;
		this.periodNS = periodNS;
		this.bufLenInScans = bufLenInScans;
	}
	
	
	public void start(){
		
		try{
			String deviceFileName = SettingsManager.defaultGlobal().getProperty("comedi.device", "/dev/comedi0_subd" + subDev);			
			comediReader = new ComediAsyncReader(deviceFileName, subDev, chans, range, aref, nScans, periodNS, bufLenInScans);
			
			statusText = "Started.";
		        
			getStore().setNotify(this);
		        
		}catch(RuntimeException err){
			err.printStackTrace();
			statusText = "Start failed: " + err.getMessage();
		}
		
		
		
		updateAllControllers();
	}
	
	@Override
	public ImagePipeController createPipeController(Class interfacingClass, Object args[], boolean asSink) {
		if(interfacingClass == Composite.class){
			if(swtScopeControl == null){
				swtScopeControl = new AquisitionSWTController(this, (Composite)args[0], (Integer)args[1]);
				controllers.add(swtScopeControl);
			}
			return swtScopeControl;
		}else
			return null;
	}

	public String getStatusText() { return statusText;  }
	
	@Override
	public void destroy() {
		super.destroy();

		if(comediReader != null)
			comediReader.abort(false);		
	}

	public boolean isActive() { return comediReader != null && comediReader.isActive(); }
	
	@Override
	public void triggerStart() {
		start();		
	}

	@Override
	public void triggerAbort() {
		abort();
	}

	public ComediRawReadBuffer getStore() {
		return (comediReader != null) ? comediReader.getStore() : null;
	}

	public void abort() {
		comediReader.abort(false);
	}

	/** Convert all the data and hang it on the source */
	public void storeData(){
		IMSEProc.ensureFinalUpdate(saveSyncObject, new Runnable() { @Override public void run() { doStoreData(); } });	
	}
	
	private void doStoreData() {
		ComediRawDataStore store = getStore();
		if(store == null)
			return;
		
		ComediDataView fullView = new ComediDataView(store, null);
		fullView.setRestrictions(-1, -1, -1, 1);
		fullView.forceUpdate();
		
		double data[];
		synchronized (fullView) {
			DoubleBuffer buf = fullView.getBuffer();
			buf.rewind();
			data = new double[buf.capacity()];
			buf.get(data);			
		}
		
		connectedSource.setSeriesMetaData("aqui/data", data);
		connectedSource.setSeriesMetaData("aqui/chans", store.chans);
		connectedSource.setSeriesMetaData("aqui/periodNS", store.periodNS);		
	}
	
	public ComediDataView getFullDataView(){
		ComediRawDataStore store = getStore();
		if(store == null)
			return null;
		
		ComediDataView fullView = new ComediDataView(store, null);
		fullView.setRestrictions(-1, -1, -1, 1);
		fullView.forceUpdate();
		return fullView;
	}

	@Override
	public void rawStoreChanged() {
		ComediRawReadBuffer rawStore = getStore();
		if(rawStore == null)
			statusText = "No data store";
		else
			statusText = "Running: " + rawStore.nChans + " chans. Scans " +
						rawStore.firstScanNum + " - " + (rawStore.nextScanNum-1) + "\n";
	
		updateAllControllers();
	}

 	@Override
	public void imageChanged(int idx) { }		// we don't care		
	
	@Override
	public void readWriteComplete() {
		
	}

	public boolean isIdle(){ return false; }
}
