package info.guardianproject.gilga.service;

import info.guardianproject.gilga.GilgaApp;
import info.guardianproject.gilga.GilgaMeshActivity;
import info.guardianproject.gilga.R;
import info.guardianproject.gilga.model.Device;
import info.guardianproject.gilga.model.DirectMessage;
import info.guardianproject.gilga.model.Status;
import info.guardianproject.gilga.radio.WifiController;
import info.guardianproject.gilga.uplink.IRCUplink;

import java.io.IOException;
import java.util.ArrayList;
import java.util.Hashtable;
import java.util.Iterator;
import java.util.StringTokenizer;

import android.app.Notification;
import android.app.NotificationManager;
import android.app.PendingIntent;
import android.app.Service;
import android.bluetooth.BluetoothAdapter;
import android.bluetooth.BluetoothDevice;
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import android.content.IntentFilter;
import android.graphics.Color;
import android.net.wifi.p2p.WifiP2pDevice;
import android.net.wifi.p2p.WifiP2pManager;
import android.os.Handler;
import android.os.IBinder;
import android.os.Message;
import android.util.Log;
import android.widget.Toast;

public class GilgaService extends Service {

	public final static String TAG = "GilgaService";

	public final static String ACTION_NEW_MESSAGE = "action_new_message";
    public final static String MATCH_DIRECT_MESSAGE = "(?i)^(d |dm |pm ).*$";
    
 // Local Bluetooth adapter
    private BluetoothAdapter mBluetoothAdapter = null;
    private final static int BLUETOOTH_DISCOVERY_RETRY_TIMEOUT = 12000;
    
   //Local Device Address
   private String mLocalShortBluetoothAddress = "";
   private String mLocalAddressHeader = "";
   
   private WifiController mWifiController;
   public static Hashtable<String,Device> mDeviceMap = new Hashtable<String,Device>();
   
    boolean mRepeaterMode = false; //by default RT trusted messages
    boolean mRepeatToIRC = false; //need to add more options here    
    private IRCUplink mIRCRepeater = null;
    private final static String DEFAULT_IRC_CHANNEL = "#gilgamesh";
    
    
    private Status mLastStatus = null;
    // String buffer for outgoing messages
    private StringBuffer mOutStringBuffer;
    
    private static Hashtable<String,Status> mMessageLog = null; //uses hash to ensure we don't display dup messages
    
    private ArrayList<DirectMessage> mQueuedDirectMessage = new ArrayList<DirectMessage>();
    private DirectMessageSession mDirectChatSession;
    
    
	@Override
	public IBinder onBind(Intent arg0) {
		// TODO Auto-generated method stub
		return null;
	}
	
	@Override
	public void onCreate() {
		super.onCreate();
		
		init();
	}

	@Override
	public int onStartCommand(Intent intent, int flags, int startId) {
	
		if (intent != null)
		{
			if (intent.hasExtra("status"))
			{
				String status = intent.getStringExtra("status");
				
				if (status.matches(MATCH_DIRECT_MESSAGE))
				{
					sendDirectMessage (status);
				}
				else
				{
					if (mLastStatus != null)
						mLastStatus.active = false;
					
		        	mLastStatus = new Status();
		        	mLastStatus.from = getString(R.string.me_);
		        	mLastStatus.ts = new java.util.Date().getTime();
		        	mLastStatus.trusted = false;
		        	mLastStatus.body = status;
		        	mLastStatus.reach = mDeviceMap.size();
		            mLastStatus.active = true;
		            
		            if (intent.hasExtra("type"))
		            	mLastStatus.type = intent.getIntExtra("type", Status.TYPE_GENERAL);
		            	
			        GilgaApp.mStatusAdapter.add(mLastStatus);
			        
					updateStatus (status);
				}
				
			}
			
			if (intent.hasExtra("repeat"))
			{
				mRepeaterMode = intent.getBooleanExtra("repeat", false);
				
				if (mRepeatToIRC)
				{
					if (mRepeaterMode)
						mIRCRepeater = new IRCUplink(mLocalShortBluetoothAddress,DEFAULT_IRC_CHANNEL);
					else if (mIRCRepeater != null)
						mIRCRepeater.shutdown();
				}
			}
		}
		
		startListening();
		
		startForegroundNotify();
		
	    return (START_STICKY);
	}


	@Override
    public void onDestroy() {
        super.onDestroy();
        
        stopForeground(true);
        // Stop the Bluetooth chat services
        if (mDirectChatSession != null) mDirectChatSession.stop();
        
        // Make sure we're not doing discovery anymore
        if (mBluetoothAdapter != null && mBluetoothAdapter.isDiscovering())
        {
        	mBluetoothAdapter.cancelDiscovery();      
        	mBluetoothAdapter = null;
        }
        
        mWifiController.stopWifi();
        
        this.unregisterReceiver(mReceiver);

    }

	private void startForegroundNotify ()
	{
		
		String message = getString(R.string.app_name) + getString(R.string._is_running);
		
		if (mRepeaterMode)
			message += " | " + getString(R.string.repeater_enabled);
			
		Notification.Builder builder =
    		    new Notification.Builder(this)
    		    .setSmallIcon(R.drawable.ic_notify)
    		    .setContentTitle(getString(R.string.app_name))
    		    .setContentText(message);
    	
		if (mRepeaterMode)
			builder.setTicker(getString(R.string.repeater_enabled));		
    	        
    	Intent resultIntent = new Intent(this, GilgaMeshActivity.class);
    	
    	// Because clicking the notification opens a new ("special") activity, there's
    	// no need to create an artificial back stack.
    	PendingIntent resultPendingIntent =
    	    PendingIntent.getActivity(
    	    this,
    	    0,
    	    resultIntent,
    	    PendingIntent.FLAG_UPDATE_CURRENT
    	);
    	
    	builder.setContentIntent(resultPendingIntent);

    	// Sets an ID for the notification
    	int mNotificationId = 002;
    	
    	startForeground(mNotificationId,builder.getNotification());
	}

	public static Hashtable<String,Status> getMessageLog ()
	{
		return mMessageLog;
	}

	private void init ()
	{
		
		
		mMessageLog = new Hashtable<String,Status>();
		
        // Get local Bluetooth adapter
        mBluetoothAdapter = BluetoothAdapter.getDefaultAdapter();

        mLocalShortBluetoothAddress = mapToNickname(mBluetoothAdapter.getAddress());
        mLocalAddressHeader = mLocalShortBluetoothAddress.substring(0,5);
       // mChatService = new BluetoothChatService(this, mHandler);

        mWifiController = new WifiController();
        mWifiController.init(this);
        
        IntentFilter filter = new IntentFilter();
        // Register for broadcasts when a device is discovered
        filter.addAction(BluetoothDevice.ACTION_FOUND);
        // Register for broadcasts when discovery has finished
        filter.addAction(BluetoothAdapter.ACTION_DISCOVERY_FINISHED);

        //  Indicates a change in the Wi-Fi P2P status.
        filter.addAction(WifiP2pManager.WIFI_P2P_STATE_CHANGED_ACTION);

        // Indicates a change in the list of available peers.
        filter.addAction(WifiP2pManager.WIFI_P2P_PEERS_CHANGED_ACTION);

        // Indicates the state of Wi-Fi P2P connectivity has changed.
        filter.addAction(WifiP2pManager.WIFI_P2P_CONNECTION_CHANGED_ACTION);

        // Indicates this device's details have changed.
        filter.addAction(WifiP2pManager.WIFI_P2P_THIS_DEVICE_CHANGED_ACTION);
        
        registerReceiver(mReceiver, filter);
        
        // Initialize the buffer for outgoing messages
        mOutStringBuffer = new StringBuffer("");

        mHandler.postDelayed(mBluetoothChecker, BLUETOOTH_DISCOVERY_RETRY_TIMEOUT);
	}

	private Runnable mBluetoothChecker = new Runnable ()
	{
		public void run ()
    	{
    		if (mBluetoothAdapter != null && mBluetoothAdapter.isEnabled())
    		{     
    			try
    			{
	            	if (!mBluetoothAdapter.isDiscovering())
	            		mBluetoothAdapter.startDiscovery();
            		          
	            }
            	catch (Exception e){}
    		}
    		
    		mHandler.postDelayed(mBluetoothChecker, BLUETOOTH_DISCOVERY_RETRY_TIMEOUT);
    	}
	};
    
    public boolean processInboundMessage (String name, String address, boolean trusted)
    {
    	String messageBuffer = name;
    	
    	StringTokenizer st = new StringTokenizer(messageBuffer,"\n");
    	
    	boolean isNewDevice = false;
    	
    	while (st.hasMoreTokens())
    	{
    	
    		String message = st.nextToken();
    		
        	if (message.startsWith("#")||
        			message.startsWith("!")||
        			message.startsWith("@")||
        			message.startsWith(".")||
        			message.startsWith(" "))
        	{
        		
        		message = message.trim();
        		
        		Status status = new Status();
        		status.from = address;
        		status.body = message;
        		status.trusted = trusted;
        		status.ts = new java.util.Date().getTime();
        		
            	if (isNewMessage(status)) //have we seen this message before
            	{
            		isNewDevice = true;
            		
            		if (message.startsWith("!"))
            		{
            			status.type = Status.TYPE_ALERT;
            			String alertMsg = '@' + mapToNickname(status.from) + ": " + status.body;
    	                sendNotitication(getString(R.string.alert),alertMsg);
            		}
            		
            		GilgaApp.mStatusAdapter.add(status);
            		
            		if (mRepeaterMode             				
            						&& (!message.contains('@' + mLocalAddressHeader))
            				) //don't RT my own tweet
            		{
            			String rtMessage = "RPT @" + mapToNickname(status.from) + ": " + status.body;
            			updateStatus(rtMessage); //retweet!

            			try
            			{
            				mIRCRepeater.sendMessage(rtMessage);
            			}
            			catch (IOException e)
            			{
            				Log.e(TAG,"error repeating to IRC",e);
            			}
            			
            			Status statusMe = new Status();
                        statusMe.from = getString(R.string.me_);
                        statusMe.ts = status.ts;
                        statusMe.trusted = trusted;
                        statusMe.body = rtMessage;
                        statusMe.type = Status.TYPE_REPEAT;
                        
                		GilgaApp.mStatusAdapter.add(statusMe);

            		}
            		
            	}
            
        	}
    	}
    	
    	return isNewDevice;
    }
    
    
    
    private boolean isNewMessage (Status msg)
    {
    	
    	if (msg.body.indexOf(':')!=-1)
    	{
    	    
    		String messageBody = msg.body.substring(msg.body.lastIndexOf(':')+1).trim();
    		String hash = MD5(messageBody);
    		
    		if (mMessageLog.containsKey(hash))
    			return false;
    		else
    		{
    			mMessageLog.put(hash, msg);
    			return true;
    		}
    	}
    	else
    	{
    		String hash = MD5(msg.body);
    		if (mMessageLog.containsKey(hash))
    			return false;
    		else
    		{
    			mMessageLog.put(hash, msg);
    			return true;
    		}
    	}
    	
    	
    }
    
   
    
    private void startBroadcasting() {
      //  if(D) Log.d(TAG, "ensure discoverable");
       if (mBluetoothAdapter.getScanMode() !=
          BluetoothAdapter.SCAN_MODE_CONNECTABLE_DISCOVERABLE) {
        	
            Intent discoverableIntent = new Intent(BluetoothAdapter.ACTION_REQUEST_DISCOVERABLE);
            discoverableIntent.putExtra(BluetoothAdapter.EXTRA_DISCOVERABLE_DURATION, 3600);
            discoverableIntent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
            startActivity(discoverableIntent);
            
        }
       
       if (!mBluetoothAdapter.isDiscovering())
    	   mBluetoothAdapter.startDiscovery();

       if (mDirectChatSession == null)
       {
    	   mDirectChatSession = new DirectMessageSession(this, mHandler);
    	   mDirectChatSession.start();
       }
       else {
           // Only if the state is STATE_NONE, do we know that we haven't started already
           if (mDirectChatSession.getState() == DirectMessageSession.STATE_NONE) {
             // Start the Bluetooth chat services
        	   mDirectChatSession.start();
           }
           
       }
        
    }
    
    private void startListening ()
    {
        
    	if (!mBluetoothAdapter.isDiscovering())
    		mBluetoothAdapter.startDiscovery();
        
    	mWifiController.startWifiDiscovery ();
       
    }
    
    private void sendDirectMessage (String message)
    {
    	
    	StringTokenizer st = new StringTokenizer(message," ");
    	String cmd = st.nextToken();
    	String address = st.nextToken();
    	
    	if (address.equals(mLocalShortBluetoothAddress)
    			|| address.equals(mBluetoothAdapter.getAddress()))
    			{
    		//can't send DM's to yourself
    		Toast.makeText(this, R.string.you_can_t_send_private_messages_to_yourself, Toast.LENGTH_SHORT).show();
    		return;
    			}
    	
    	try
    	{
	    	final BluetoothDevice device = mBluetoothAdapter.getRemoteDevice(address);
	    	final boolean isSecure = device.getBondState()==BluetoothDevice.BOND_BONDED;
	    	
	    	StringBuffer dMessage = new StringBuffer();
	    	
	    	while (st.hasMoreTokens())
	    		dMessage.append(st.nextToken()).append(" ");
	    	
	    	DirectMessage dm = new DirectMessage();
	    	dm.to = address;
	    	dm.body = dMessage.toString().trim();
	    	dm.ts = new java.util.Date().getTime();
	    	dm.delivered = false;
	
	    	mQueuedDirectMessage.add(dm);
	    	
	    	dm.trusted = isSecure;
	    	GilgaApp.mStatusAdapter.add(dm);
	    	
	    	if (mDirectChatSession == null)
	    	{
	    	 mDirectChatSession = new DirectMessageSession(this, mHandler);
	  	   	 mDirectChatSession.start();
	    	}
	    	else
	    	{
	    		mDirectChatSession.disconnect();
	    	}
	    	
	    	mHandler.postAtTime(new Runnable ()
	    	{
	    		public void run ()
	    		{
	    	    	mDirectChatSession.connect(device, isSecure);
	    		}
	    	}, 2000);
    	}
    	catch (IllegalArgumentException iae)
    	{
    		Toast.makeText(this, getString(R.string.error_sending_message_) + iae.getLocalizedMessage(), Toast.LENGTH_LONG).show();
    	}
    	
    }
    
    
    /**
     * Sends a message.
     * @param message  A string of text to send.
     */
    private void updateStatus(String message) {

        // Check that there's actually something to send
        if (message.length() > 0) {
           
        	mOutStringBuffer.append(' ' + message + '\n');

        	if (mOutStringBuffer.toString().getBytes().length > 248)
        	{
        		  mOutStringBuffer.setLength(0);
        		  mOutStringBuffer.append(' ' + message + '\n');
        	}
        	
        	mBluetoothAdapter.setName(mOutStringBuffer.toString());
        	
        	mWifiController.updateWifiStatus(message);
    		startBroadcasting() ;
            
            
        }
    }
    
    public static String mapToNickname (String hexAddressIn)
    {
    	String shortAddress = new String(hexAddressIn);
    	if (shortAddress.length() > 6)
    	{
	    	//remove : and get last 6 characters
    		shortAddress = shortAddress.replace(":", "");
    		shortAddress = shortAddress.substring(shortAddress.length()-6,shortAddress.length());	   
    	}
    	
    	return shortAddress.toUpperCase();
    }
    
    public String MD5(String md5) {
    	   try {
    	        java.security.MessageDigest md = java.security.MessageDigest.getInstance("MD5");
    	        byte[] array = md.digest(md5.getBytes());
    	        StringBuffer sb = new StringBuffer();
    	        for (int i = 0; i < array.length; ++i) {
    	          sb.append(Integer.toHexString((array[i] & 0xFF) | 0x100).substring(1,3));
    	       }
    	        return sb.toString();
    	    } catch (java.security.NoSuchAlgorithmException e) {
    	    }
    	    return null;
    	}
    
 // The Handler that gets information back from the BluetoothChatService
    private final Handler mHandler = new Handler() {
        @Override
        public void handleMessage(Message msg) {
            switch (msg.what) {
            case MESSAGE_STATE_CHANGE:
                //if(D) Log.i(TAG, "MESSAGE_STATE_CHANGE: " + msg.arg1);
                switch (msg.arg1) {
                case DirectMessageSession.STATE_CONNECTED:
                   
                	//once connected, send message, then wait for response
                	String address = msg.getData().getString("address");
                	ArrayList<DirectMessage> listSent = new ArrayList<DirectMessage>();
                	
                	if (address != null)
                	{
                		synchronized (mQueuedDirectMessage)
                		{
	                		Iterator<DirectMessage> itDm = mQueuedDirectMessage.iterator();
	                		while (itDm.hasNext())
	                		{
	                			DirectMessage dm = itDm.next();
	                			
	                			if (dm.to.equals(address))
	                			{
	                				String dmText = dm.body + '\n';
	                				mDirectChatSession.write(dmText.getBytes());
	                				dm.delivered = true;
	                				GilgaApp.mStatusAdapter.notifyDataSetChanged();
	                				listSent.add(dm);
	                			}
	                		}
                		}
                		
                		
                	}
                	
                	mQueuedDirectMessage.removeAll(listSent);
                	
                    break;
                case DirectMessageSession.STATE_CONNECTING:
                  //  setStatus(R.string.title_connecting);
                    break;
                case DirectMessageSession.STATE_LISTEN:
                case DirectMessageSession.STATE_NONE:
                //    setStatus(getString(R.string.broadcast_mode_public_) + " | " + getString(R.string.you_are_) + mLocalAddress);
                    break;
                }
                break;
            case MESSAGE_WRITE:
            	
            	//we just add it directly, but we should mark as delivered here
            	/**
                byte[] writeBuf = (byte[]) msg.obj;
                // construct a string from the buffer
                String writeMessage = new String(writeBuf);
                
                Status status = new Status();
                status.from = getString(R.string.me_);
                status.body = writeMessage;
                status.trusted = true;
                status.type = Status.TYPE_DIRECT;
                status.ts = new java.util.Date().getTime();
                **/
            //    GilgaApp.mStatusAdapter.add(status);
                break;
            case MESSAGE_READ:
                byte[] readBuf = (byte[]) msg.obj;
                // construct a string from the valid bytes in the buffer
                String readMessage = new String(readBuf, 0, msg.arg1);
                String addr = msg.getData().getString("address");
                
                StringTokenizer st = new StringTokenizer (readMessage,"\n");
                
                while (st.hasMoreTokens())
                {
	                DirectMessage dm = new DirectMessage();
	                dm.from = addr;
	                dm.body = st.nextToken();
	                dm.trusted = true;
	                dm.ts = new java.util.Date().getTime();
	                
	                sendNotitication(getString(R.string._pm_from_) + addr, dm.body);
	                
	                GilgaApp.mStatusAdapter.add(dm);
                }
                
                break;
            case MESSAGE_DEVICE_NAME:
                // save the connected device's name
         //       mConnectedDeviceName = mapToNickname(msg.getData().getString(DEVICE_NAME));
               // Toast.makeText(getApplicationContext(), R.string.connected_to_
                 //              + mConnectedDeviceName, Toast.LENGTH_SHORT).show();
                break;
            case MESSAGE_TOAST:
               // Toast.makeText(getApplicationContext(), msg.getData().getString(TOAST),
                 //              Toast.LENGTH_SHORT).show();
                break;
            }
        }
    };
    
    public void sendNotitication (String title, String message)
    {
    	Notification.Builder builder =
    		    new Notification.Builder(this)
    		    .setSmallIcon(R.drawable.ic_notify)
    		    .setContentTitle(title)
    		    .setContentText(message);
    	
    	  //Vibration
        builder.setVibrate(new long[] { 500, 1000, 500 });
        builder.setAutoCancel(true);

     //LED
        builder.setLights(Color.BLUE, 3000, 3000);
        
    	Intent resultIntent = new Intent(this, GilgaMeshActivity.class);
    	
    	// Because clicking the notification opens a new ("special") activity, there's
    	// no need to create an artificial back stack.
    	PendingIntent resultPendingIntent =
    	    PendingIntent.getActivity(
    	    this,
    	    0,
    	    resultIntent,
    	    PendingIntent.FLAG_UPDATE_CURRENT
    	);
    	
    	builder.setContentIntent(resultPendingIntent);

    	// Sets an ID for the notification
    	int mNotificationId = 001;
    	// Gets an instance of the NotificationManager service
    	NotificationManager mNotifyMgr = 
    	        (NotificationManager) getSystemService(NOTIFICATION_SERVICE);
    	// Builds the notification and issues it.
    	mNotifyMgr.notify(mNotificationId, builder.getNotification());
    }
    
    // The BroadcastReceiver that listens for discovered devices and
    // changes the title when discovery is finished
    private final BroadcastReceiver mReceiver = new BroadcastReceiver() {
    	
        @Override
        public void onReceive(Context context, Intent intent) {
            String action = intent.getAction();

            // When discovery finds a device
            if (BluetoothDevice.ACTION_FOUND.equals(action)) {
                // Get the BluetoothDevice object from the Intent
                BluetoothDevice device = intent.getParcelableExtra(BluetoothDevice.EXTRA_DEVICE);
                
                if (device.getName() != null)
                {
                	String address = device.getAddress();
                	
                	boolean isNewStatusOrDevice = processInboundMessage(device.getName(),address,device.getBondState() == BluetoothDevice.BOND_BONDED);
                	
                	if (isNewStatusOrDevice) //this is a gilgamesh device
                	{
                		Device d = new Device(device);
                		mDeviceMap.put(device.getAddress(), d);
                		
                        int  rssi = intent.getShortExtra(BluetoothDevice.EXTRA_RSSI,Short.MIN_VALUE);
                        d.mSignalInfo = rssi + context.getString(R.string.dbm);
                		
                		//if we have a last status, increase the number of devices reached
                		if (mLastStatus != null)
                			mLastStatus.reach = mDeviceMap.size(); //set to current size
                        
                	}
                	else
                	{
                		Device d = mDeviceMap.get(device.getAddress());
                		if (d != null)
                		{
                            int  rssi = intent.getShortExtra(BluetoothDevice.EXTRA_RSSI,Short.MIN_VALUE);
                            d.mSignalInfo = rssi + context.getString(R.string.dbm);
                		}
                	}
                	
                	if (mQueuedDirectMessage.size() > 0 && mDirectChatSession != null
                			&& (mDirectChatSession.getState() != DirectMessageSession.STATE_CONNECTED 
                			|| mDirectChatSession.getState() != DirectMessageSession.STATE_CONNECTING))
                	{
                		//try to do resend now if address matches
                		
                		if (address != null)
                    	{
                			synchronized (mQueuedDirectMessage)
                			{
	                    		Iterator<DirectMessage> itDm = mQueuedDirectMessage.iterator();
	                    		while (itDm.hasNext())
	                    		{
	                    			DirectMessage dm = itDm.next();
	                    			
	                    			if (dm.to.equals(address))
	                    			{
	                    		    	boolean isSecure = device.getBondState()==BluetoothDevice.BOND_BONDED;
	                    		    	mDirectChatSession.connect(device, isSecure);
	                    		    	break;
	                    			}
	                    		}
                			}
                    	}
                	}
                	
                }
                
            // When discovery is finished, change the Activity title
            } else if (BluetoothAdapter.ACTION_DISCOVERY_FINISHED.equals(action)) {
                
            	mHandler.postDelayed(new Runnable ()
            	{
            		public void run ()
            		{
            			if (mBluetoothAdapter != null)
            				mBluetoothAdapter.startDiscovery();
            		}
            	}, BLUETOOTH_DISCOVERY_RETRY_TIMEOUT);
            }
            else if (WifiP2pManager.WIFI_P2P_STATE_CHANGED_ACTION.equals(action)) {
                // Determine if Wifi P2P mode is enabled or not, alert
                // the Activity.
                int state = intent.getIntExtra(WifiP2pManager.EXTRA_WIFI_STATE, -1);
                if (state == WifiP2pManager.WIFI_P2P_STATE_ENABLED) {
                
                	mWifiController.setEnabled(true);
                } 
                
            } else if (WifiP2pManager.WIFI_P2P_PEERS_CHANGED_ACTION.equals(action)) {

            	mWifiController.requestPeers();
            	
                

            } else if (WifiP2pManager.WIFI_P2P_CONNECTION_CHANGED_ACTION.equals(action)) {

            	mWifiController.getNetworkInfo ();
            	
            } else if (WifiP2pManager.WIFI_P2P_THIS_DEVICE_CHANGED_ACTION.equals(action)) {
                
            	WifiP2pDevice device = (WifiP2pDevice) intent.getParcelableExtra(
                        WifiP2pManager.EXTRA_WIFI_P2P_DEVICE);
            	
            	mDeviceMap.put(device.deviceAddress, new Device(device));
        		
        		//if we have a last status, increase the number of devices reached
        		if (mLastStatus != null)
        			mLastStatus.reach = mDeviceMap.size(); //set to current size

            	 boolean trusted = false; //not sure how to do this with wifi
            	 
            	 if (!mapToNickname(device.deviceAddress).startsWith(mLocalAddressHeader)) //not me
           	  		processInboundMessage(device.deviceName,device.deviceAddress,trusted);
            }
        }
    };

    // Message types sent from the BluetoothChatService Handler
    public static final int MESSAGE_STATE_CHANGE = 1;
    public static final int MESSAGE_READ = 2;
    public static final int MESSAGE_WRITE = 3;
    public static final int MESSAGE_DEVICE_NAME = 4;
    public static final int MESSAGE_TOAST = 5;
  
}