/**
   * Create a bluetooth connection with SerialPortServiceClass_UUID
   *
   * @see <a href= "http://lejos.sourceforge.net/forum/viewtopic.php?t=1991&highlight=android" /> On
   *     error the method either sends a message to it's owner or creates an exception in the case
   *     of no message handler.
   */
  public void createNXTconnection() throws IOException {
    try {
      BluetoothSocket nxtBTSocketTemporary;
      BluetoothDevice nxtDevice = null;
      nxtDevice = btAdapter.getRemoteDevice(mMACaddress);
      if (nxtDevice == null) {
        if (uiHandler == null) throw new IOException();
        else {
          sendToast(mResources.getString(R.string.no_paired_nxt));
          sendState(STATE_CONNECTERROR);
          return;
        }
      }
      nxtBTSocketTemporary =
          nxtDevice.createRfcommSocketToServiceRecord(SERIAL_PORT_SERVICE_CLASS_UUID);
      try {
        nxtBTSocketTemporary.connect();
      } catch (IOException e) {
        if (myOwner.isPairing()) {
          if (uiHandler != null) {
            sendToast(mResources.getString(R.string.pairing_message));
            sendState(STATE_CONNECTERROR_PAIRING);
          } else throw e;
          return;
        }

        // try another method for connection, this should work on the HTC desire, credits to Michael
        // Biermann
        try {
          Method mMethod =
              nxtDevice.getClass().getMethod("createRfcommSocket", new Class[] {int.class});
          nxtBTSocketTemporary = (BluetoothSocket) mMethod.invoke(nxtDevice, Integer.valueOf(1));
          nxtBTSocketTemporary.connect();
        } catch (Exception e1) {
          if (uiHandler == null) throw new IOException();
          else sendState(STATE_CONNECTERROR);
          return;
        }
      }
      nxtBTsocket = nxtBTSocketTemporary;
      nxtInputStream = nxtBTsocket.getInputStream();
      nxtOutputStream = nxtBTsocket.getOutputStream();
      connected = true;
    } catch (IOException e) {
      if (uiHandler == null) throw e;
      else {
        if (myOwner.isPairing()) sendToast(mResources.getString(R.string.pairing_message));
        sendState(STATE_CONNECTERROR);
        return;
      }
    }
    // everything was OK
    if (uiHandler != null) sendState(STATE_CONNECTED);
  }
  /**
   * Sends a message on the opened OutputStream. In case of an error the state is sent to the
   * handler.
   *
   * @param message, the message as a byte array
   */
  private void sendMessageAndState(byte[] message) {
    if (nxtOutputStream == null) return;

    try {
      sendMessage(message);
    } catch (IOException e) {
      sendState(STATE_SENDERROR);
    }
  }
  /**
   * Creates the connection, waits for incoming messages and dispatches them. The thread will be
   * terminated on closing of the connection.
   */
  @Override
  public void run() {

    try {
      createNXTconnection();
    } catch (IOException e) {
    }

    while (connected) {
      try {
        returnMessage = receiveMessage();
        if ((returnMessage.length >= 2)
            && ((returnMessage[0] == LCPMessage.REPLY_COMMAND)
                || (returnMessage[0] == LCPMessage.DIRECT_COMMAND_NOREPLY)))
          dispatchMessage(returnMessage);

      } catch (IOException e) {
        // don't inform the user when connection is already closed
        if (connected) sendState(STATE_RECEIVEERROR);
        return;
      }
    }
  }
  private void dispatchMessage(byte[] message) {
    switch (message[1]) {
      case LCPMessage.GET_OUTPUT_STATE:
        if (message.length >= 25) sendState(MOTOR_STATE);

        break;

      case LCPMessage.GET_FIRMWARE_VERSION:
        if (message.length >= 7) sendState(FIRMWARE_VERSION);

        break;

      case LCPMessage.FIND_FIRST:
      case LCPMessage.FIND_NEXT:
        if (message.length >= 28) {
          // Success
          if (message[2] == 0) sendState(FIND_FILES);
        }

        break;

      case LCPMessage.GET_CURRENT_PROGRAM_NAME:
        if (message.length >= 23) {
          sendState(PROGRAM_NAME);
        }

        break;

      case LCPMessage.SAY_TEXT:
        if (message.length == 22) {
          sendState(SAY_TEXT);
        }

      case LCPMessage.VIBRATE_PHONE:
        if (message.length == 3) {
          sendState(VIBRATE_PHONE);
        }
    }
  }