unit Aurelius.Plugin.Import;

interface

uses
  SysUtils,

  Aurelius.Plugin.Types,
  Aurelius.Plugin.Options,
  Aurelius.Plugin.Database;

const
  DLLName = 'AureliusPluginLibrary.dll';

type
  HDICTIONARY = Pointer;
  TProgressProc = procedure(Percentage: double);

  TCreateDictionary = function(SQLDialect: WideString; out Dictionary: HDICTIONARY): HRESULT; stdcall;
  TFreeDictionary = procedure(Dictionary: HDICTIONARY); stdcall;
  TRetrieveDictionary = function(Connection: IASPluginConnection; Dictionary: HDICTIONARY;
    ProgressProc: TProgressProc; ProgressData: Pointer): HRESULT; stdcall;
  TRetrieveDatabase = function(Dictionary: HDICTIONARY; out Database: IPluginDatabase): HRESULT; stdcall;
  TGenerateSourceCode = function(Dictionary: HDICTIONARY; PluginOptions: IASPluginOptions;
    out SourceCode: WideString): HRESULT; stdcall;
  TGetLastPluginError = function: WideString; stdcall;

var
  CreateDictionary: TCreateDictionary;
  FreeDictionary: TFreeDictionary;
  RetrieveDictionary: TRetrieveDictionary;
  GenerateSourceCode: TGenerateSourceCode;
  RetrieveDatabase: TRetrieveDatabase;
  GetLastPluginError: TGetLastPluginError;

function LoadAureliusPluginLibrary(LocalDLLName: string = ''): boolean;
procedure UnloadAureliusPluginLibrary;
procedure PluginCheck(Value: HRESULT);

implementation

uses
  WinApi.Windows;

var
  LibraryHandle: THandle;

procedure PluginCheck(Value: HRESULT);
begin
  if Value <> 0 then
  begin
    if Value = 2 then
      raise EAureliusPluginException.Create(GetLastPluginError)
    else
      raise EAureliusPluginUnexpectedException.Create(GetLastPluginError);
  end;
end;

procedure InitAureliusPluginLibrary;
begin
  LibraryHandle := 0;
end;

procedure UnloadAureliusPluginLibrary;
begin
  if LibraryHandle <> 0 then
  begin
    FreeLibrary(LibraryHandle);
    LibraryHandle := 0;
  end;
end;

function LoadAureliusPluginLibrary(LocalDLLName: string = ''): boolean;

  function LoadProc(ProcName: string): Pointer;
  begin
    Result := GetProcAddress(LibraryHandle, PChar(ProcName));
    Assert(Assigned(Result), LocalDLLName + ' - Could not find method: ' + ProcName);
  end;

begin
  if LibraryHandle <> 0 then
    Exit(True);

  Result := False;

  if LocalDLLName = '' then
    LocalDLLName := DLLName;
  LibraryHandle := SafeLoadLibrary(PChar(LocalDLLName));
  if (LibraryHandle <> 0) then
  begin
    Result := True;

    CreateDictionary := LoadProc('CreateDictionary');
    RetrieveDictionary := LoadProc('RetrieveDictionary');
    FreeDictionary := LoadProc('FreeDictionary');
    GenerateSourceCode := LoadProc('GenerateSourceCode');
    GetLastPluginError := LoadProc('GetLastPluginError');
    RetrieveDatabase := LoadProc('RetrieveDatabase');
  end;
end;


Initialization
  InitAureliusPluginLibrary;

finalization
  UnloadAureliusPluginLibrary;

end.
