package com.android.Stimuli;

import java.io.IOException;
import java.io.InputStream;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.util.UUID;

import android.bluetooth.BluetoothAdapter;
import android.bluetooth.BluetoothDevice;
import android.bluetooth.BluetoothServerSocket;
import android.bluetooth.BluetoothSocket;
import android.os.Handler;
import android.util.Log;
import android.widget.Toast;
import com.android.main.*;
public class ReceivingThread_test extends Thread {
	private final String TAG = "ReceivingThread_test";
    private static final boolean D = true;
	private BluetoothAdapter mBluetoothAdapter = null;
    //private BluetoothServerSocket btSocket = null;
    private BluetoothSocket btSPPSocket = null;
    private BluetoothDevice device;
    //private OutputStream outStream = null;
    private InputStream inStream = null;
    // Well known SPP UUID (will *probably* map to
    // RFCOMM channel 1 (default) if not in use);
    // see comments in onResume().
    private static final UUID MY_UUID = UUID.fromString("00001101-0000-1000-8000-00805F9B34FB");//channel 1
    //private static final UUID MY_UUID = UUID.fromString("0000111E-0000-1000-8000-00805F9B34FB");//channel 2
    //private static final UUID MY_UUID = UUID.fromString("0000111A-0000-1000-8000-00805F9B34FB");//channel 2
    //private static final String address = "00:18:00:00:01:34";//headband 512
    //private static String address = "00:18:00:00:01:31";//headband 128
    //private static String address = "00:18:00:32:06:ED";//16ch
    private static String address = "00:18:00:32:06:F5";//new 16ch
    //private static String address = "00:15:83:C7:38:20";//BT dongle
    private Buffer buffer;//private byte[] buffer;
    public boolean RUN;
    private Handler mHandler;
    private static final int PRINTMESSAGE = 0;
    private static final int ADDCOUNT =1;
    private Lock mlock;
    private String myName;
    public boolean CONNECTED;
    private byte[] btBuffer,btBuffer_garbage;
    private boolean headerFound;
	public ReceivingThread_test(Handler handler,Lock lock,String name){
        mHandler = handler;
        //mHandler.obtainMessage(PRINTMESSAGE, TAG+": "+"IN THE CREATER").sendToTarget();
        //buffer = new Buffer();//buffer = new byte[2000];
        RUN = false;
        mBluetoothAdapter = BluetoothAdapter.getDefaultAdapter();
        mlock = lock;
        myName = name;
        CONNECTED = false;
        
	}
	public ReceivingThread_test(String name){
        //mHandler.obtainMessage(PRINTMESSAGE, TAG+": "+"IN THE CREATER").sendToTarget();
        //buffer = new Buffer();//buffer = new byte[2000];
		RUN = false;
        mBluetoothAdapter = BluetoothAdapter.getDefaultAdapter();
        myName = name;
        CONNECTED = false;
        btBuffer = new byte[34];
        btBuffer_garbage = new byte[35];
        headerFound = false;
	}
	
	public Boolean getConnection(){
		boolean result = true;
		synchronized(this){
			//mHandler.obtainMessage(PRINTMESSAGE, TAG+": "+"IN THE RUN").sendToTarget();
	        device = mBluetoothAdapter.getRemoteDevice(address); 
			try {
				btSPPSocket = device.createRfcommSocketToServiceRecord(MY_UUID);
				//mHandler.obtainMessage(PRINTMESSAGE, TAG+": Waiting for connection.").sendToTarget();
				btSPPSocket.connect();
				
				//Log.e(TAG, "ON RESUME: BT connection established, data transfer link open.");
				//mHandler.obtainMessage(PRINTMESSAGE, TAG+": BT connection established, data transfer link open.").sendToTarget();
	            //btSocket.close();
			} 
			catch (IOException e) {
				result = false;
	            //closeAllSocket();
	            //mHandler.obtainMessage(PRINTMESSAGE, TAG+": IOException1. "+e.getMessage()).sendToTarget();
			}
			finally{
				//mBluetoothAdapter.cancelDiscovery();
				if(result){
					CONNECTED = true;
					RUN = true;
				}
				Log.e(TAG, "BT connected: "+result, null);
			}
		}
		return result;
	}
	public void getData(){
		int size =0;
		try {
			if(inStream ==null){
				inStream = btSPPSocket.getInputStream();
				Log.e(TAG, "inStream = null");
			}
			else{
				//Log.e(TAG, "1 Stream Size= "+inStream.available());
				while(inStream.available()>0 && RUN){
					if(!headerFound){//header not found yet
						size = inStream.read(btBuffer_garbage);
						searchHeader(btBuffer_garbage);
						Log.e(TAG, "btBuffer_garbage[1]= "+(((int)btBuffer_garbage[1])&0x000000ff)+", btBuffer_garbage[2]= "+(((int)btBuffer_garbage[2])&0x000000ff));
					}
					else{
						size = inStream.read(btBuffer);
						if(size==btBuffer.length){
							buffer.setData(
									((((int)btBuffer[2])&0x000000ff)-64)*64 + ((((int)btBuffer[3])&0x000000ff) -64), 
									((((int)btBuffer[4])&0x000000ff)-64)*64 + ((((int)btBuffer[5])&0x000000ff) -64), 
									((((int)btBuffer[6])&0x000000ff)-64)*64 + ((((int)btBuffer[7])&0x000000ff) -64), 
									((((int)btBuffer[8])&0x000000ff)-64)*64 + ((((int)btBuffer[9])&0x000000ff) -64), 
									((((int)btBuffer[10])&0x000000ff)-64)*64 +((((int)btBuffer[11])&0x000000ff) -64), 
									((((int)btBuffer[12])&0x000000ff)-64)*64 +((((int)btBuffer[13])&0x000000ff) -64), 
									((((int)btBuffer[14])&0x000000ff)-64)*64 +((((int)btBuffer[15])&0x000000ff) -64), 
									((((int)btBuffer[16])&0x000000ff)-64)*64 +((((int)btBuffer[17])&0x000000ff) -64), 
									((((int)btBuffer[18])&0x000000ff)-64)*64 +((((int)btBuffer[19])&0x000000ff) -64), 
									((((int)btBuffer[20])&0x000000ff)-64)*64 +((((int)btBuffer[21])&0x000000ff) -64), 
									((((int)btBuffer[22])&0x000000ff)-64)*64 +((((int)btBuffer[23])&0x000000ff) -64), 
									((((int)btBuffer[24])&0x000000ff)-64)*64 +((((int)btBuffer[25])&0x000000ff) -64), 
									((((int)btBuffer[26])&0x000000ff)-64)*64 +((((int)btBuffer[27])&0x000000ff) -64), 
									((((int)btBuffer[28])&0x000000ff)-64)*64 +((((int)btBuffer[29])&0x000000ff) -64), 
									((((int)btBuffer[30])&0x000000ff)-64)*64 +((((int)btBuffer[31])&0x000000ff) -64), 
									((((int)btBuffer[32])&0x000000ff)-64)*64 +((((int)btBuffer[33])&0x000000ff) -64));
							//Log.e(TAG, "btBuffer[0]= "+(((int)btBuffer[0])&0x000000ff)+", btBuffer[1]= "+(((int)btBuffer[1])&0x000000ff)+", Stream reminded= "+inStream.available());
						
						}
						else{
							Log.e(TAG, "size <34");
						}
					}
					if(inStream.available()<34)
						break;
					//buffer.setData(1, 3, 3, 3, 3, 37678, 9, 7, 87, 9, 23, 987, 797, 987, 87, 987);
					//Log.e(TAG, "Read= "+size+", Stream reminded= "+inStream.available());
				}//end of while(inStream.available()!=0)
			}
		}//end of try 
		catch (IOException e) {
			//mHandler.obtainMessage(PRINTMESSAGE, TAG+": IOException2, "+e.getMessage()).sendToTarget();
			Log.e(TAG,"Excep in getData(), "+e.getMessage());
			closeAllSocket();
		} 
		finally{
				//closeAllSocket();
		}	
	}
	//if found header1&&header2, headerFound=true
	//else herderFound=false(default)
	private void searchHeader(byte[] dataReceived){
		if((((int)dataReceived[1])&0x000000ff)==255 && (((int)dataReceived[2])&0x000000ff)==116)
			this.headerFound = true;
	}
	public void run_ori(){
		mHandler.obtainMessage(PRINTMESSAGE, TAG+": "+"IN THE RUN").sendToTarget();
       
        device = mBluetoothAdapter.getRemoteDevice(address); 
   	 	try {
			btSPPSocket = device.createRfcommSocketToServiceRecord(MY_UUID);
		} catch (IOException e1) {
			mHandler.obtainMessage(PRINTMESSAGE, TAG+":IOException1, " +e1.getMessage()).sendToTarget();
		}
		/*device = mBluetoothAdapter.getRemoteDevice(address); 
   	 	Method m = null;
		try {
			m = device.getClass().getMethod("createRfcommSocket", new Class[]{int.class});
		} catch (SecurityException e1) {
			mHandler.obtainMessage(PRINTMESSAGE, TAG+":SecurityException, " +e1.getMessage()).sendToTarget();//tt.append("SecurityException, " +e1.getMessage());
		} catch (NoSuchMethodException e1) {
			mHandler.obtainMessage(PRINTMESSAGE, TAG+":NoSuchMethodException, " +e1.getMessage()).sendToTarget();
		} 
		try {
			btSPPSocket = (BluetoothSocket)m.invoke(device, Integer.valueOf(1));
		} catch (IllegalArgumentException e) {
			mHandler.obtainMessage(PRINTMESSAGE, TAG+":IllegalArgumentException, " +e.getMessage()).sendToTarget();
		} catch (IllegalAccessException e) {
			mHandler.obtainMessage(PRINTMESSAGE, TAG+":IllegalAccessException, " +e.getMessage()).sendToTarget();
		} catch (InvocationTargetException e) {
			mHandler.obtainMessage(PRINTMESSAGE, TAG+":InvocationTargetException, " +e.getMessage()).sendToTarget();
		} */
  
		try {
			mHandler.obtainMessage(PRINTMESSAGE, TAG+": Waiting for connection.").sendToTarget();
			btSPPSocket.connect();
			//Log.e(TAG, "ON RESUME: BT connection established, data transfer link open.");
			mHandler.obtainMessage(PRINTMESSAGE, TAG+": BT connection established, data transfer link open.").sendToTarget();
            //btSocket.close();
		} catch (IOException e) {
            closeAllSocket();
            mHandler.obtainMessage(PRINTMESSAGE, TAG+": IOException1. "+e.getMessage()).sendToTarget();
		}
	mBluetoothAdapter.cancelDiscovery();

	try {
        inStream = btSPPSocket.getInputStream();
        //inStream = btSPPSocket.getInputStream();
        mHandler.obtainMessage(PRINTMESSAGE, TAG+": INPUTSTREAM OPENED.").sendToTarget();
	} catch (IOException e) {
        //Log.e(TAG, "ON RESUME: Output stream creation failed.", e);
        mHandler.obtainMessage(PRINTMESSAGE, TAG+": getInputStream."+e.getMessage()).sendToTarget();
	}
		int size =0;
		try {
			while(RUN){
				//handler.sendMessage(handler.obtainMessage());
				//mlock.wantToUse();
				//mHandler.obtainMessage(PRINTMESSAGE, TAG+": "+"READING FROM INPUTSTREAM,size= "+Integer.toString(size)).sendToTarget();
				//mHandler.obtainMessage(PRINTMESSAGE, TAG+": "+"SLEEP!"+inStream.available()).sendToTarget();
				//synchronized(this){
				//
				while(inStream.available()==0){
					//mHandler.obtainMessage(PRINTMESSAGE,"Receiving thread sleep.").sendToTarget();
					sleep(900);
				}
				{
					//mHandler.obtainMessage(PRINTMESSAGE,inStream.read(),inStream.read(), myName).sendToTarget();
					if((size = inStream.read())==255){
						if((size = inStream.read())==116){
							buffer.setData(
									(inStream.read()-64)*64 + (inStream.read()-64), 
									(inStream.read()-64)*64 + (inStream.read()-64), 
									(inStream.read()-64)*64 + (inStream.read()-64), 
									(inStream.read()-64)*64 + (inStream.read()-64), 
									(inStream.read()-64)*64 + (inStream.read()-64), 
									(inStream.read()-64)*64 + (inStream.read()-64), 
									(inStream.read()-64)*64 + (inStream.read()-64), 
									(inStream.read()-64)*64 + (inStream.read()-64), 
									(inStream.read()-64)*64 + (inStream.read()-64), 
									(inStream.read()-64)*64 + (inStream.read()-64), 
									(inStream.read()-64)*64 + (inStream.read()-64), 
									(inStream.read()-64)*64 + (inStream.read()-64), 
									(inStream.read()-64)*64 + (inStream.read()-64), 
									(inStream.read()-64)*64 + (inStream.read()-64), 
									(inStream.read()-64)*64 + (inStream.read()-64), 
									(inStream.read()-64)*64 + (inStream.read()-64));
						}
					}
					mHandler.obtainMessage(ADDCOUNT,inStream.available(),buffer.getDataIndex(), myName).sendToTarget();
				}
				//mlock.leave();
				//}
				//mHandler.obtainMessage(PRINTMESSAGE, TAG+": "+"Wake up!"+inStream.available()).sendToTarget();
			}
		} catch (IOException e) {
			mHandler.obtainMessage(PRINTMESSAGE, TAG+": IOException2, "+e.getMessage()).sendToTarget();
		} catch (InterruptedException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		} 
		finally{
			closeAllSocket();
			//mlock.leave();
			mHandler.obtainMessage(PRINTMESSAGE, TAG+" IS DONE!").sendToTarget();
			mHandler.obtainMessage(PRINTMESSAGE, "***************\r\n").sendToTarget();
		}	
		//for(int i=0;i<buffer.length;i++)
		//	mHandler.obtainMessage(PRINTMESSAGE, TAG+": "+"Buffer["+i+"]= "+(int)buffer[i]).sendToTarget();
	}
	public void run1(){
		double data = 0;
		for(int i=0;i<1800;i++){
			for(int j=0;j<128;j++){
				data = 0.9*Math.sin(j * 2 *  Math.PI * 10 / 128)+0.01*Math.sin(j * 2 *  Math.PI * (Math.random()*10) / 128);
				//data = Math.sin(j * 2 *  Math.PI * (10) / 128);
				//data = 0.8*Math.sin(j * 2 *  Math.PI * 10 / 128)+0.1*Math.sin(j * 2 *  Math.PI * (Math.random()*10) / 128)+0.1*Math.sin(j * 2 *  Math.PI * (Math.random()*10) / 128);
				buffer.setData(data, data, data, data, data, data, data, data, data, data, data, data, data, data, data, data);
				//temp[j]	=Math.sin(j * 2 *  Math.PI * (Math.random()*50) / 128);	
				try {
					sleep(1000/128);
				} catch (InterruptedException e) {
					// TODO Auto-generated catch block
					e.printStackTrace();
				}
			}
			
		}
	}
	public void closeAllSocket(){
		//mHandler.obtainMessage(PRINTMESSAGE, TAG+": "+"CLOSE ALL STREAM").sendToTarget();//tt.append("^^^^^^CLOSE ALL STREAM^^^^^^\r\n");
	   	if(inStream != null){
	   		try {
					inStream.close();
				} catch (IOException e) {
					//mHandler.obtainMessage(PRINTMESSAGE, TAG+": "+"IOException in inStream.close()").sendToTarget();
					Log.e(TAG, "Error in closeAllSocket()1, "+e.getMessage());
				}
	    }
        if(btSPPSocket!= null){
			try {
				btSPPSocket.close();
				
			} catch (IOException e) {
				//mHandler.obtainMessage(PRINTMESSAGE, TAG+": "+"IOException in btSPPSocket.close()").sendToTarget();
				Log.e(TAG, "Error in closeAllSocket()2, "+e.getMessage());
			}
        }
        //mHandler.obtainMessage(PRINTMESSAGE, TAG+": "+"ALL STREAM CLOSED").sendToTarget();//tt.append("^^^^^^ALL STREAM CLOSED^^^^^^\r\n");
        Log.e(TAG, "CloseAllSocket() done.");
    }
}
