//---------------------------------------------------------------------------
#include <vcl.h>
#pragma hdrstop

#include "EXEForm.h"
#include "DLLMain.h"
//---------------------------------------------------------------------------

static const char *DLLName = "DLLProject.dll";
static HINSTANCE DLLInst = NULL;
static bool FormIsVisible;

// Exported functions from the DLL
typedef void __stdcall (*CREATEFN) (void *);
typedef void __stdcall (*SHOWFN) (int);
typedef void __stdcall (*RETRIEVEFN) (void *);

// These will be set when the DLL is loaded from disk.
CREATEFN DLL_CreateForm;
SHOWFN DLL_ShowForm;
RETRIEVEFN DLL_GetData;

//---------------------------------------------------------------------------
#pragma package(smart_init)
#pragma resource "*.dfm"
TfrmEXE *frmEXE;

// The DLL will call this function to communicate changes with the EXE
void Callback(FormData *data)
{
    // Make a copy of the data. No guarantee that the pointer will be
    // valid after returning (back to the DLL) from this function.
  frmEXE->UpdateUI(data);
}

//---------------------------------------------------------------------------
__fastcall TfrmEXE::TfrmEXE(TComponent* Owner) : TForm(Owner)
{
}
//---------------------------------------------------------------------------

// Load the DLL and get the exported functions.
void __fastcall TfrmEXE::btnLoadDLLClick(TObject *Sender)
{
  DLLInst = LoadLibrary(DLLName);
  if (!DLLInst)
    barStatus->SimpleText = "Could not load DLL: " + String(DLLName);
  else
  {
    DLL_CreateForm = (CREATEFN) GetProcAddress(DLLInst, "CreateForm");
    if (!DLL_CreateForm)
      ShowMessage("Can't find function: CreateForm");

    DLL_ShowForm = (SHOWFN) GetProcAddress(DLLInst, "ShowForm");
    if (!DLL_ShowForm)
      ShowMessage("Can't find function: ShowForm");

    DLL_GetData = (RETRIEVEFN) GetProcAddress(DLLInst, "GetData");
    if (!DLL_GetData)
      ShowMessage("Can't find function: GetData");

    btnCreateForm->Enabled = DLL_CreateForm ? true : false;
  }
}
//---------------------------------------------------------------------------

void __fastcall TfrmEXE::btnCreateFormClick(TObject *Sender)
{
    // Send the function pointer that the DLL will callback
  DLL_CreateForm(Callback);

  btnShowForm->Enabled = true;
  btnGetData->Enabled = true;
}
//---------------------------------------------------------------------------

// Toggle visibility of the DLL form
void __fastcall TfrmEXE::btnShowFormClick(TObject *Sender)
{
  if (FormIsVisible)
  {
    DLL_ShowForm(0);
    btnShowForm->Caption = "Show form";
    FormIsVisible = false;
  }
  else
  {
    DLL_ShowForm(1);
    btnShowForm->Caption = "Hide form";
    FormIsVisible = true;
  }
}
//---------------------------------------------------------------------------

// Get the values from the DLL form
void __fastcall TfrmEXE::btnGetDataClick(TObject *Sender)
{
  FormData data;
  DLL_GetData(&data);
  UpdateUI(&data);
}
//---------------------------------------------------------------------------

// Helper function to copy the values from data to the UI components
void TfrmEXE::UpdateUI(const FormData *data)
{
  rgrpMap->ItemIndex          = data->map;
  chkSpectre->Checked         = data->spectre;
  chkArachnotron->Checked     = data->arachnotron;
  chkMancubus->Checked        = data->mancubus;
  spnNumSpectre->Position     = (short) data->spectre_count;
  spnNumArachnotron->Position = (short) data->arachnotron_count;
  spnNumMancubus->Position    = (short) data->mancubus_count;
  edtTitle->Text              = data->title;
  edtDescription->Text        = data->description;
}