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

#include <vcl.h>
#pragma hdrstop

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

#include "wclUUIDs.hpp"
#include "wclCODs.hpp"

TfmMain *fmMain;
//---------------------------------------------------------------------------
__fastcall TfmMain::TfmMain(TComponent* Owner)
        : TForm(Owner)
{
}
//---------------------------------------------------------------------------
void __fastcall TfmMain::FormCreate(TObject *Sender)
{
  wclRfCommServer->Authentication = false;
  wclRfCommServer->Service = OBEXObjectPushServiceClass_UUID;
  wclRfCommServer->ServiceName = "WCL OPP Server";
}
//---------------------------------------------------------------------------
void __fastcall TfmMain::FormDestroy(TObject *Sender)
{
  wclRfCommServer->Close();
  wclBluetoothManager->Close();
}
//---------------------------------------------------------------------------
void __fastcall TfmMain::btClearClick(TObject *Sender)
{
  lbLog->Clear();
}
//---------------------------------------------------------------------------
void __fastcall TfmMain::btListenClick(TObject *Sender)
{
  int Res = wclBluetoothManager->Open();
  if (Res != WCL_E_SUCCESS)
    ShowMessage("Bluetooth manager open failed: 0x" + IntToHex(Res, 8));
  else
  {
    TwclBluetoothRadio* Radio;
    Res = wclBluetoothManager->GetClassicRadio(Radio);
    if (Res != WCL_E_SUCCESS)
    {
      MessageDlg("Get working radio failed: 0x" + IntToHex(Res, 8), mtError,
        TMsgDlgButtons() << mbOK, 0);
    }
    else
    {
      // Switch radio in discoverable and connectable mode.
      // Ignore any errors. In real application you need to check the result.
      Radio->SetDiscoverable(true);
      Radio->SetConnectable(true);

      // As wrote above it is better to start listening in AfterOpen event
      // handler. But again, for demo app its OK to do it here.
      Res = wclRfCommServer->Listen(Radio);
      if (Res != WCL_E_SUCCESS)
        ShowMessage("Failed to start listening: 0x" + IntToHex(Res, 8));
    }

    if (Res != WCL_E_SUCCESS)
      // We must close Bluetooth Manager here!
      wclBluetoothManager->Close();
  }
}
//---------------------------------------------------------------------------
void __fastcall TfmMain::btCloseClick(TObject *Sender)
{
  int Res = wclRfCommServer->Close();
  if (Res != WCL_E_SUCCESS)
    ShowMessage("Close failed; 0x" + IntToHex(Res, 8));
  else
    wclBluetoothManager->Close();
}
//---------------------------------------------------------------------------
void __fastcall TfmMain::wclRfCommServerListen(TObject *Sender)
{
  Trace("Server listening");
}
//---------------------------------------------------------------------------
void __fastcall TfmMain::Trace(String Msg)
{
  lbLog->Items->Add(Msg);
}
//---------------------------------------------------------------------------
void __fastcall TfmMain::wclRfCommServerClosed(TObject *Sender,
      const int Reason)
{
  Trace("Server closed. Reason:: 0x" + IntToHex(Reason, 8));
}
//---------------------------------------------------------------------------
void __fastcall TfmMain::wclRfCommServerDisconnect(TObject *Sender,
      const TwclRfCommServerClientConnection *Client, const int Reason)
{
  Trace("Client " + IntToHex(Client->Address, 12) + " disconnected. Reason: 0x" +
    IntToHex(Reason, 8));
}
//---------------------------------------------------------------------------
void __fastcall TfmMain::wclRfCommServerDestroyProcessor(TObject *Sender,
      const TwclServerClientDataConnection *Connection)
{
  Trace("Data processor for client " +
    IntToHex(((TwclRfCommServerClientConnection*)Connection)->Address, 12) +
    " is destroing");
  Connection->Processor->Free();
}
//---------------------------------------------------------------------------

void __fastcall TfmMain::wclRfCommServerConnect(TObject *Sender,
      const TwclRfCommServerClientConnection *Client, const int Error)
{
  if (Error == WCL_E_SUCCESS)
    Trace("Client " + IntToHex(Client->Address, 12) + " connected");
  else
  {
    Trace("Client " + IntToHex(Client->Address, 12) +
      " connect failed: 0x" + IntToHex(Error, 8));
  }
}
//---------------------------------------------------------------------------

void __fastcall TfmMain::wclRfCommServerCreateProcessor(TObject *Sender,
      const TwclServerClientDataConnection *Connection)
{
  // Here we must create OBEX OPP server data processor.
  #if __BORLANDC__ >= 0x0650
	TwclObexOppServer* Proc = new TwclObexOppServer((TwclServerClientDataConnection*)Connection);
	#if __BORLANDC__ >= 0x0740
	  Proc->OnPutCompleted = OppClientPutCompleted;
	  Proc->OnGetCompleted = OppClientGetCompleted;
	#else
	  Proc->OnPutCompleted = (TwclObexServerClientPutCompletedEvent)&OppClientPutCompleted;
	  Proc->OnGetCompleted = (TwclObexServerClientGetCompletedEvent)&OppClientGetCompleted;
	#endif
  #else
	TwclObexOppServer* Proc = new TwclObexOppServer(Connection);
	Proc->OnPutCompleted = OppClientPutCompleted;
	Proc->OnGetCompleted = OppClientGetCompleted;
  #endif
  Proc->OnConnect = OppClientConnect;
  Proc->OnDisconnected = OppClientDisconnected;
  Proc->OnPutBegin = OppClientPutBegin;
  Proc->OnPutProgress = OppClientPutProgress;
  Proc->OnGetRequest = OppClientGetRequest;
  Proc->OnProgress = OppClientProgress;
}
//---------------------------------------------------------------------------
void __fastcall TfmMain::OppClientConnect(TObject* Sender,
      const String Description)
{
  TwclObexOppServer* Proc = (TwclObexOppServer*)Sender;
  __int64 Address = ((TwclRfCommServerClientConnection*)Proc->Connection)->Address;
  bool Accept = MessageDlg("Client " + IntToHex(Address, 12) +
    " requsts for connection: " + Description + ". Accept?", mtConfirmation,
    TMsgDlgButtons() << mbYes << mbNo, 0) == mrYes;

  int Res;
  if (Accept)
  {
    Res = Proc->Accept("Accepted by user");
    if (Res == WCL_E_SUCCESS)
    {
      TListItem* Item = lvClients->Items->Add();
      Item->Caption = IntToHex(Address, 12);
      Item->Data = Sender;
      Trace("OBEX session opened for client: " + IntToHex(Address, 12));
    }
  }
  else
    Res = Proc->Reject("Rejected by user");

  if (Res != WCL_E_SUCCESS)
  {
    ShowMessage("Operation failed: 0x" + IntToHex(Res, 8));
    // Disconnect client!
    Proc->Connection->Disconnect();
  }
}
//---------------------------------------------------------------------------
void __fastcall TfmMain::OppClientDisconnected(TObject* Sender,
  const int Reason, const String Description)
{
  TwclObexOppServer* Proc = (TwclObexOppServer*)Sender;
  __int64 Address = ((TwclRfCommServerClientConnection*)Proc->Connection)->Address;

  Trace("Client " + IntToHex(Address, 12) +
    " closed OBEX session with reason: 0x" + IntToHex(Reason, 8) +
    ". Description: " + Description);

  for (int i = 0; i < lvClients->Items->Count; i++)
  {
    if (lvClients->Items->Item[i]->Data == Sender)
    {
      lvClients->Items->Delete(i);
      break;
    }
  }
}
//---------------------------------------------------------------------------
//---------------------------------------------------------------------------
void __fastcall TfmMain::btDisconnectClick(TObject *Sender)
{
  if (lvClients->Selected == NULL)
    ShowMessage("Select client");
  else
  {
    TwclObexOppServer* Proc = (TwclObexOppServer*)lvClients->Selected->Data;
    int Res = Proc->Connection->Disconnect();
    if (Res != WCL_E_SUCCESS)
      ShowMessage("Disconnect failed: 0x" + IntToHex(Res, 8));
  }
}
//---------------------------------------------------------------------------

void __fastcall TfmMain::wclRfCommServerGetSdpAttributes(TObject *Sender,
      TwclBluetoothSdpProtocols& Protocols,
      TwclBluetoothSdpProfiles& Profiles, TwclBluetoothSdpFormats& Formats,
      DWORD& Cod)
{
  // We have to provide additional information for SDP record.
  Protocols.set_length(1);
  Protocols[0] = OBEX_PROTOCOL_UUID16;
  Profiles.set_length(1);
  Profiles[0].Uuid = OBEXObjectPushServiceClass_UUID16;
  Profiles[0].Version = 0x0100;
  Formats.set_length(1);
  Formats[0] = 0xFF; // All formats.
  Cod = COD_SERVICE_OBJECT_XFER;
}
//---------------------------------------------------------------------------
void __fastcall TfmMain::OppClientPutBegin(TObject* Sender, const String Name,
  const String Description, const String Mime, const unsigned int Length,
  bool& Accept)
{
  TwclObexOppServer* Proc = (TwclObexOppServer*)Sender;
  __int64 Address = ((TwclRfCommServerClientConnection*)Proc->Connection)->Address;
  String Str = "Client " + IntToHex(Address, 12) + " send file " + Name +
    ". Accept?";
  Accept = MessageDlg(Str, mtConfirmation, TMsgDlgButtons() << mbYes << mbNo, 0) == mrYes;

  if (Accept)
    FFileName = Name;
}
//---------------------------------------------------------------------------
#if __BORLANDC__ >= 0x0740
  void __fastcall TfmMain::OppClientPutCompleted(TObject* Sender,
	const int Error, TStream* const Stream, bool& Accept)
#else
  void __fastcall TfmMain::OppClientPutCompleted(TObject* Sender,
    const int Error, const TStream* Stream, bool& Accept)
#endif
{
  TwclObexOppServer* Proc = (TwclObexOppServer*)Sender;
  __int64 Address = ((TwclRfCommServerClientConnection*)Proc->Connection)->Address;
  if (Error == WCL_E_SUCCESS)
  {
    String Str = "Client " + IntToHex(Address, 12) + " completed sent file. Accept?";
    Accept = MessageDlg(Str, mtConfirmation, TMsgDlgButtons() << mbYes << mbNo, 0) == mrYes;

    if (Accept)
    {
      SaveDialog->FileName = FFileName;
      if (SaveDialog->Execute())
        ((TMemoryStream*)Stream)->SaveToFile(SaveDialog->FileName);
    }
  }
  else
    Trace("Send file error: 0x" + IntToHex(Error, 8));
}
//---------------------------------------------------------------------------
void __fastcall TfmMain::OppClientPutProgress(TObject* Sender,
  const unsigned int Position, const unsigned int Length, bool& Continue)
{
  Trace("Sending file: " + IntToStr((int)Position) + " from " +
    IntToStr((int)Length));
  // Do not foget to set Continue flag!
  Continue = true;
}
//---------------------------------------------------------------------------
void __fastcall TfmMain::OppClientGetRequest(TObject* Sender, String aType,
  TwclObexServerOperationResult& Result, TStream*& Stream)
{
  if (aType == "text/x-vCard" || aType == "x-obex/capability")
  {
    Trace("Requested file type: " + aType);

    if (!OpenDialog->Execute())
    {
      Result = orForbidden;
      Stream = NULL;
    }
    else
    {
      Stream = new TFileStream(OpenDialog->FileName, fmOpenRead);
      Result = orSuccess;
    }
  }
  else
  {
    Result = orUnsupportedMedia;
    Stream = NULL;
  }
}
//---------------------------------------------------------------------------
#if __BORLANDC__ >= 0x0740
  void __fastcall TfmMain::OppClientGetCompleted(TObject* Sender, int Error,
	TStream* const Stream)
#else
  void __fastcall TfmMain::OppClientGetCompleted(TObject* Sender, int Error,
	const TStream* Stream)
#endif
{
  Trace("Get operation completed with result: 0x" + IntToHex(Error, 8));
  if (Stream != NULL)
    ((TStream*)Stream)->Free();
}
//---------------------------------------------------------------------------
void __fastcall TfmMain::OppClientProgress(TObject* Sender,
  const unsigned int Length, const unsigned int Position)
{
  Trace("Sending file: " + IntToStr((int)Position) + " from " +
    IntToStr((int)Length));
}
//---------------------------------------------------------------------------
