library microMouse_Virtual;

{ Important note about DLL memory management: ShareMem must be the
  first unit in your library's USES clause AND your project's (select
  Project-View Source) USES clause if your DLL exports any procedures or
  functions that pass strings as parameters or function results. This
  applies to all strings passed to and from your DLL--even those that
  are nested in records and classes. ShareMem is the interface unit to
  the BORLNDMM.DLL shared memory manager, which must be deployed along
  with your DLL. To avoid using BORLNDMM.DLL, pass string information
  using PChar or ShortString parameters. }

uses SysUtils, StrUtils,
 //  Classes,      - usetri 40 KB
     Windows,        // Win32 API funkce
     Messages;       // Win32 API zpravy

const mmEndOfMsg = chr(128);

var sDelMsg, sPyMsg, sDelStatus, sPyStatus : THandle;
    mmDel2PyPTR : PChar;                   //pChar je typ stringu ( ekvivalent ASCIIZ )-ukazatel na char (asi)
    mmPy2DelPTR : PChar;
    mmCommandOut: string;
    lMsgID      : LongWord;

{$R *.res}

// export = bude videt z DLL
// cdecl = predavani parametru jako v C, Pascalska konvence je cool, ale ne kazdy jazyk ji dava 
function mmSetDelphiMsg( aText : string ): boolean; cdecl ; export;    // pridani 1 prikazu
begin
  // Provede zapis do souboru sDelMsg
  if sDelMsg <> 0 then
  begin
    inc(lMsgID);       // zvysi msgid o 1

    aText := IntToStr(lMsgID)+';'+aText + mmEndOfMsg;
    mmDel2PyPTR := MapViewOfFile(sDelMsg, FILE_MAP_WRITE,             //klikani na radiobuttony=posilani do buferu, tlacidlo GÓ= pridani konecneho znaku a odeslani
                              0, 0, Length(aText) + 1);
    StrCopy(mmDel2PyPTR, PChar(aText));

    UnmapViewOfFile(mmDel2PyPTR);
    result := True;
  end
  else
    result := False;
end;

function mmSetDelphiReady(): boolean;cdecl ; export;  //nastavi delphi na "pripraveno"
  var lText : PChar;
begin

  // Provede zapis do souboru sDelStatus
  if sDelMsg <> 0 then
  begin
    inc(lMsgID);       // zvysi msgid o 1

    lText := 'READY;' + mmEndOfMsg;
    mmDel2PyPTR := MapViewOfFile(sDelStatus, FILE_MAP_WRITE,             //klikani na radiobuttony=posilani do buferu, tlacidlo GÓ= pridani konecneho znaku a odeslani
                              0, 0, Length(lText) + 1);
    StrCopy(mmDel2PyPTR, PChar(lText));

    UnmapViewOfFile(mmDel2PyPTR);
    result := True;
  end
  else
    result := False;
end;

function mmSetDelphiBusy(): boolean;cdecl ; export;  //nastavi delphi na "pripraveno"
  var lText : PChar;
begin

  // Provede zapis do souboru sDelStatus
  if sDelMsg <> 0 then
  begin
    inc(lMsgID);       // zvysi msgid o 1

    lText := 'BUSY;' + mmEndOfMsg;
    mmDel2PyPTR := MapViewOfFile(sDelStatus, FILE_MAP_WRITE,             //klikani na radiobuttony=posilani do buferu, tlacidlo GÓ= pridani konecneho znaku a odeslani
                              0, 0, Length(lText) + 1);
    StrCopy(mmDel2PyPTR, PChar(lText));

    UnmapViewOfFile(mmDel2PyPTR);
    result := True;
  end
  else
    result := False;
end;

function mmOpenCommunication(): boolean;cdecl ; export;
begin

  try
    sDelMsg     := CreateFileMapping($FFFFFFFF, nil, PAGE_READWRITE, 0, 1024, 'mmFiDel2PyMsg'); //namapovani
    sPyMsg      := CreateFileMapping($FFFFFFFF, nil, PAGE_READWRITE, 0, 1024, 'mmFiPy2DelMsg');
    sDelStatus  := CreateFileMapping($FFFFFFFF, nil, PAGE_READWRITE, 0, 1024, 'mmFiDel2PyFlg');
    sPyStatus   := CreateFileMapping($FFFFFFFF, nil, PAGE_READWRITE, 0, 1024, 'mmFiPy2DelFlg');
    lMsgID      := 0;
    mmSetDelphiReady();
    mmSetDelphiMsg('JustRelaxing();');
    result := True;
  except
    result := False;
  end;

end;

function mmIsPythonReady(): boolean;cdecl ; export;  //kontroluje, jestli je python pripraven poslouchat
begin

  if sPyMsg <> 0 then begin                         //kdyz byla zahajena komunikace
    mmPy2DelPTR := MapViewOfFile(sPyStatus, FILE_MAP_READ, 0, 0, 0);        // tak se k nemu pristoupi

    if (mmPy2DelPTR= 'READY;') then                    //zjistzime co tam je , vratime podle toho hodnotu a uklidime po sobe
      result := True
    else
      begin
        result := False;
      end;

    UnmapViewOfFile(mmPy2DelPTR);
    end
  else
    result := False;

end;


function mmGetPythonMsg(): PChar;cdecl ; export;  //co rika Python
  var tmpstr : PChar;
begin

  if sPyMsg <> 0 then begin                         //kdyz byla zahajena komunikace
      mmPy2DelPTR := MapViewOfFile(sPyMsg, FILE_MAP_READ, 0, 0, 0);        // tak se k nemu pristoupi
      tmpstr := mmPy2DelPTR;
      result := PChar(tmpstr+'');       // Manualne pridame null character nakonec
      UnmapViewOfFile(mmPy2DelPTR);
    end
  else
    result := 'ERROR';

end;

function mmAddCommand( aText : string ): boolean; cdecl;cdecl ; export;    // pridani prikazu
begin
  // Nebudeme pouzivat
  result := False;
  exit;
  // Provede zapis do souboru sDelMsg
  if sDelMsg <> 0 then
  begin
                                          //docasny buffer do ktereho si pridavame a pak se jako balik odeslou  (python poslocha, ale nekona, dokud se neprida konecny znak)
    mmCommandOut := mmCommandOut + aText;
    mmDel2PyPTR := MapViewOfFile(sDelMsg, FILE_MAP_WRITE,             //klikani na radiobuttony=posilani do buferu, tlacidlo GÓ= pridani konecneho znaku a odeslani
                              0, 0, Length(mmCommandOut) + 1);        // fix, byla tu spatna delka
    StrCopy(mmDel2PyPTR, PChar(mmCommandOut));

    UnmapViewOfFile(mmDel2PyPTR);
    result := True;
  end
  else
    result := False;
end;


function mmCloseCommunication(): boolean;cdecl ; export;      //pridani konecneho znaku a uzavre komunikaci
begin
  mmSetDelphiMsg('END();');
  try
    CloseHandle(sPyStatus);
    CloseHandle(sDelStatus);
    CloseHandle(sPyMsg);
    CloseHandle(sDelMsg);
    mmSetDelphiBusy();       // tak busy az sme skoncili :)
    result := True;
  except
    result := False;
  end;
end;

function mmSetMsgEnd(): boolean;cdecl ; export;          //poslani konecneho znaku (samotneho)
begin
  result := False;    // Nebudeme pouzivat
  exit;
  result := mmAddCommand('');
  mmCommandOut := '';
end;

function mmSetSteps( aSteps : LongWord ): boolean;cdecl ; export;
begin
  result := mmSetDelphiMsg('SETSTEP(' + IntToStr(aSteps) + ');' );
end;

function mmMoveForward( aCount : LongWord ): boolean;cdecl ; export;
begin
  result := mmSetDelphiMsg('MOVFWD(' + IntToStr(aCount) + ');')
end;

function mmMoveBackward( aCount : LongWord ): boolean;cdecl ; export;
begin
  result := mmSetDelphiMsg('MOVBKW(' + IntToStr(aCount) + ');')
end;

function mmTurnLeft( aCount : LongWord ): boolean;cdecl ; export;
begin
  result := mmSetDelphiMsg('TRNLFT(' + IntToStr(aCount) + ');')
end;

function mmTurnRight( aCount : LongWord ): boolean;cdecl ; export;
begin
  result := mmSetDelphiMsg('TRNRGT(' + IntToStr(aCount) + ');')
end;

exports mmOpenCommunication, mmCloseCommunication,mmAddCommand, mmSetMsgEnd,
        mmSetSteps, mmMoveForward, mmMoveBackward, mmTurnLeft, mmTurnRight,
        mmIsPythonReady, mmGetPythonMsg, mmSetDelphiMsg, mmSetDelphiReady, mmSetDelphiBusy;

begin
end.

