//---------------------------------------------------------------------------

#include <vcl.h>
#pragma hdrstop

#include "main.h"
//---------------------------------------------------------------------------
#pragma package(smart_init)
#pragma link "wclBluetooth"
#pragma resource "*.dfm"

TfmMain *fmMain;
//---------------------------------------------------------------------------
__fastcall TfmMain::TfmMain(TComponent* Owner)
        : TForm(Owner)
{
}
//---------------------------------------------------------------------------
void __fastcall TfmMain::FormCreate(TObject *Sender)
{
  // In real application you should always analize the result code.
  // In this demo we assume that all is always OK.
  wclBluetoothManager->Open();

  cbAuthentication->Checked = wclRfCommClient->Authentication;
  cbEncryption->Checked = wclRfCommClient->Encryption;
}
//---------------------------------------------------------------------------
TwclBluetoothRadio* __fastcall TfmMain::GetRadio()
{
  TwclBluetoothRadio* Radio;
  int Res = wclBluetoothManager->GetClassicRadio(Radio);
  if (Res != WCL_E_SUCCESS)
  {
    MessageDlg("Get working radio failed: 0x" + IntToHex(Res, 8), mtError,
      TMsgDlgButtons() << mbOK, 0);
    return NULL;
  }
  return Radio;
}
//---------------------------------------------------------------------------
void __fastcall TfmMain::btDiscoverClick(TObject *Sender)
{
  TwclBluetoothRadio* Radio = GetRadio();
  if (Radio != NULL)
  {
    if (cbEnumPaired->Checked)
    {
      TwclBluetoothAddresses Devices;
      int Res = Radio->EnumPairedDevices(Devices);
      if (Res != WCL_E_SUCCESS)
      {
        MessageDlg("Enum paired devices failed: 0x" + IntToHex(Res, 8),
          mtError, TMsgDlgButtons() << mbOK, 0);
      }
      else
      {
        lvDevices->Items->Clear();
        if (Devices.Length > 0)
        {
          for (int i = 0; i < Devices.Length; i++)
          {
            wclBluetoothManagerDeviceFound(wclBluetoothManager, Radio,
              Devices[i]);
          }
          wclBluetoothManagerDiscoveringCompleted(wclBluetoothManager, Radio,
            WCL_E_SUCCESS);
        }
      }
    }
    else
    {
      int Res = Radio->Discover(10, dkClassic);
      if (Res != WCL_E_SUCCESS)
      {
        MessageDlg("Error starting discovering: 0x" + IntToHex(Res, 8),
          mtError, TMsgDlgButtons() << mbOK, 0);
      }
    }
  }
}
//---------------------------------------------------------------------------
void __fastcall TfmMain::btClearEventsClick(TObject *Sender)
{
  lbEvents->Clear();
}
//---------------------------------------------------------------------------
void __fastcall TfmMain::btConnectClick(TObject *Sender)
{
  if (lvDevices->Selected == NULL)
    MessageDlg("Select device", mtWarning, TMsgDlgButtons() << mbOK, 0);

  else
  {
    TwclBluetoothRadio* Radio = GetRadio();
    if (Radio != NULL)
    {
      wclRfCommClient->Address = StrToInt64("$" + lvDevices->Selected->Caption);
      wclRfCommClient->Authentication = cbAuthentication->Checked;
      wclRfCommClient->Encryption = cbEncryption->Checked;
      wclRfCommClient->Timeout = StrToInt(edTimeout->Text);
      
      wclRfCommClient->Channel = 0;
      wclRfCommClient->Service = SerialPortServiceClass_UUID;

      bool Connect = false;
      if (cbServiceName->Checked)
      {
        TwclBluetoothServices Services;
        TGUID Service = wclRfCommClient->Service;
        int Res = Radio->EnumRemoteServices(wclRfCommClient->Address,
          &Service, // Se are looking for specified services only!
          Services);
        if (Res != WCL_E_SUCCESS)
          MessageDlg("Service enumerating error: 0x" + IntToHex(Res, 8), mtError, TMsgDlgButtons() << mbOK, 0);

        else
        {
          if (Services.Length == 0)
            ShowMessage("Services not found");

          else
          {
            for (int i = 0; i < Services.Length; i++)
            {
              if (Services[i].Name == edServiceName->Text)
              {
                wclRfCommClient->Channel = Services[i].Channel;
                Connect = true;
                break;
              }
            }

            if (!Connect)
              ShowMessage("Service not found");
          }
        }
      }
      else
        Connect = true;

      if (Connect)
      {
        int Res = wclRfCommClient->Connect(Radio);
        if (Res != WCL_E_SUCCESS)
          MessageDlg("Error: 0x" + IntToHex(Res, 8), mtError, TMsgDlgButtons() << mbOK, 0);
      }
    }
  }
}
//---------------------------------------------------------------------------
void __fastcall TfmMain::btDisconnectClick(TObject *Sender)
{
  int Res = wclRfCommClient->Disconnect();
  if (Res != WCL_E_SUCCESS)
  {
    MessageDlg("Error: 0x" + IntToHex(Res, 8), mtError,
      TMsgDlgButtons() << mbOK, 0);
  }
}
//---------------------------------------------------------------------------
void __fastcall TfmMain::btSendClick(TObject *Sender)
{
  AnsiString Ansi = AnsiString(edText->Text);
  unsigned int Sent = 0;
  int Res = wclRfCommClient->Write(Ansi.c_str(), Ansi.Length(), Sent);
  if (Res != WCL_E_SUCCESS)
  {
    MessageDlg("Error: 0x" + IntToHex(Res, 8), mtError,
      TMsgDlgButtons() << mbOK, 0);
  }
  else
  {
    MessageDlg("Sent: " + IntToStr((int)Sent) + " from " + IntToStr(Ansi.Length()),
      mtInformation, TMsgDlgButtons() << mbOK, 0);
  }
}
//---------------------------------------------------------------------------
void __fastcall TfmMain::btSetBuffersClick(TObject *Sender)
{
  // Try to set read buffer size first.
  unsigned int Size = StrToInt(edReadBuffer->Text);
  int Res = wclRfCommClient->SetReadBufferSize(Size);
  if (Res == WCL_E_SUCCESS)
    lbEvents->Items->Add("Read buffer size changed.");
  else
    lbEvents->Items->Add("Set read buffer size error: 0x" + IntToHex(Res, 8));

  // Now write buffer.
  Size = StrToInt(edWriteBuffer->Text);
  Res = wclRfCommClient->SetWriteBufferSize(Size);
  if (Res == WCL_E_SUCCESS)
    lbEvents->Items->Add("Write buffer size changed.");
  else
    lbEvents->Items->Add("Set write buffer size error: 0x" + IntToHex(Res, 8));
}
//---------------------------------------------------------------------------
void __fastcall TfmMain::btGetBuffersClick(TObject *Sender)
{
  GetBuffers();
}
//---------------------------------------------------------------------------
void __fastcall TfmMain::GetBuffers()
{
  // Try to get read and write buffers size.
  unsigned int Size = 0;

  int Res = wclRfCommClient->GetReadBufferSize(Size);
  if (Res != WCL_E_SUCCESS)
    lbEvents->Items->Add("Get read buffer error: 0x" + IntToHex(Res, 8));
  else
    edReadBuffer->Text = IntToStr((int)Size);

  Size = 0;
  Res = wclRfCommClient->GetWriteBufferSize(Size);
  if (Res != WCL_E_SUCCESS)
    lbEvents->Items->Add("Get write buffer error: 0x" + IntToHex(Res, 8));
  else
    edWriteBuffer->Text = IntToStr((int)Size);
}
//---------------------------------------------------------------------------
void __fastcall TfmMain::wclBluetoothManagerNumericComparison(
      TObject *Sender, const TwclBluetoothRadio *Radio,
      const __int64 Address, const DWORD Number, bool& Confirm)
{
  // Accept any pairing.
  Confirm = true;
  lbEvents->Items->Add("Numeric comparison: " + IntToStr((int)Number));
}
//---------------------------------------------------------------------------
void __fastcall TfmMain::wclBluetoothManagerPasskeyNotification(
      TObject *Sender, const TwclBluetoothRadio *Radio,
      const __int64 Address, const DWORD Passkey)
{
  lbEvents->Items->Add("Passkey notification: " + IntToStr((int)Passkey));
}
//---------------------------------------------------------------------------
void __fastcall TfmMain::wclBluetoothManagerPasskeyRequest(TObject *Sender,
      const TwclBluetoothRadio *Radio, const __int64 Address,
      DWORD& Passkey)
{
  // Use 123456 as passkey.
  Passkey = 123456;
  lbEvents->Items->Add("Passkey request: " + IntToStr((int)Passkey));
}
//---------------------------------------------------------------------------
void __fastcall TfmMain::wclBluetoothManagerPinRequest(TObject *Sender,
      const TwclBluetoothRadio *Radio, const __int64 Address,
      String& Pin)
{
  // Use "0000" as PIN.
  Pin = "0000";
  lbEvents->Items->Add("Pin request: " + Pin);
}
//---------------------------------------------------------------------------
void __fastcall TfmMain::wclBluetoothManagerDeviceFound(TObject *Sender,
      const TwclBluetoothRadio *Radio, const __int64 Address)
{
  TwclBluetoothDeviceType DevType = dtMixed;
  int Res = ((TwclBluetoothRadio*)Radio)->GetRemoteDeviceType(Address, DevType);

  TListItem* Item = lvDevices->Items->Add();
  Item->Caption = IntToHex(Address, 12);
  Item->SubItems->Add(""); // We can not read a device"s name here.
  Item->Data = (void*)Radio; // To use it later.
  if (Res != WCL_E_SUCCESS)
    Item->SubItems->Add("Error: 0x" + IntToHex(Res, 8));
  else
  {
    switch (DevType)
    {
      case dtClassic:
        Item->SubItems->Add("Classic");
        break;
      case dtBle:
        Item->SubItems->Add("BLE");
        break;
      case dtMixed:
        Item->SubItems->Add("Mixed");
        break;
      default:
        Item->SubItems->Add("Unknown");
        break;
    }
  }

  lbEvents->Items->Add("Device found: " + IntToHex(Address, 12));
}
//---------------------------------------------------------------------------
void __fastcall TfmMain::wclBluetoothManagerDiscoveringCompleted(
      TObject *Sender, const TwclBluetoothRadio *Radio, const int Error)
{
  if (lvDevices->Items->Count == 0)
    MessageDlg("No devices were found.", mtInformation,
      TMsgDlgButtons() << mbOK, 0);

  else
  {
    // Here we can update found devices names.
    for (int i = 0; i < lvDevices->Items->Count; i++)
    {
      TListItem* Item = lvDevices->Items->Item[i];

      __int64 Address = StrToInt64("$" + Item->Caption);
      String DevName;
      int Res = ((TwclBluetoothRadio*)Radio)->GetRemoteName(Address, DevName);
      if (Res != WCL_E_SUCCESS)
        Item->SubItems->Strings[0] = "Error: 0x" + IntToHex(Res, 8);
      else
        Item->SubItems->Strings[0] = DevName;
    }
  }

  lbEvents->Items->Add("Discovering completed");
}
//---------------------------------------------------------------------------
void __fastcall TfmMain::wclBluetoothManagerDiscoveringStarted(
      TObject *Sender, const TwclBluetoothRadio *Radio)
{
  lvDevices->Items->Clear();
  lbEvents->Items->Add("Discovering started");
}
//---------------------------------------------------------------------------
void __fastcall TfmMain::wclRfCommClientConnect(TObject *Sender,
      const int Error)
{
  if (Error == WCL_E_SUCCESS)
  {
    lbEvents->Items->Add("Connected");

    GetBuffers();

  }
  else
    lbEvents->Items->Add("Connect error: 0x" + IntToHex(Error, 8));
}
//---------------------------------------------------------------------------
void __fastcall TfmMain::wclRfCommClientData(TObject *Sender,
      const Pointer Data, const DWORD Size)
{
  if (Size > 0)
  {
    AnsiString Str = AnsiString((AnsiChar*)Data, Size);

    lbEvents->Items->Add("Received: " + String(Str));
  }
}
//---------------------------------------------------------------------------
void __fastcall TfmMain::wclRfCommClientDisconnect(TObject *Sender,
      const int Reason)
{
  lbEvents->Items->Add("Disconnected: 0x" + IntToHex(Reason, 8));

  edReadBuffer->Text = "0";
  edWriteBuffer->Text = "0";
}
//---------------------------------------------------------------------------
void __fastcall TfmMain::FormDestroy(TObject *Sender)
{
  wclRfCommClient->Disconnect();
  wclBluetoothManager->Close();
}
//---------------------------------------------------------------------------

void __fastcall TfmMain::wclBluetoothManagerAuthenticationCompleted(
      TObject *Sender, const TwclBluetoothRadio *Radio,
      const __int64 Address, const int Error)
{
  lbEvents->Items->Add("Authentication completed: " + IntToHex(Error, 8));        
}
//---------------------------------------------------------------------------

void __fastcall TfmMain::wclBluetoothManagerConfirm(TObject *Sender,
      const TwclBluetoothRadio *Radio, const __int64 Address, bool& Confirm)
{
  Confirm = true;
  lbEvents->Items->Add("Just works pairing");
}
//---------------------------------------------------------------------------

void __fastcall TfmMain::btPairClick(TObject *Sender)
{
  if (lvDevices->Selected == NULL)
    MessageDlg("Select device", mtWarning, TMsgDlgButtons() << mbOK, 0);
  else
  {
    TwclBluetoothRadio* Radio = GetRadio();
    if (Radio != NULL)
    {
      int Res = Radio->RemotePair(StrToInt64("$" + lvDevices->Selected->Caption),
        pmClassic);
      if (Res != WCL_E_SUCCESS)
        ShowMessage("Pair failed: 0x" + IntToHex(Res, 8));
    }
  }
}
//---------------------------------------------------------------------------


void __fastcall TfmMain::btUnpairClick(TObject *Sender)
{
  if (lvDevices->Selected == NULL)
    MessageDlg("Select device", mtWarning, TMsgDlgButtons() << mbOK, 0);
  else
  {
    TwclBluetoothRadio* Radio = GetRadio();
    if (Radio != NULL)
    {
      int Res = Radio->RemoteUnpair(StrToInt64("$" + lvDevices->Selected->Caption),
        pmClassic);
      if (Res != WCL_E_SUCCESS)
        ShowMessage("Unpair failed: 0x" + IntToHex(Res, 8));
    }
  }
}
//---------------------------------------------------------------------------

