unit uServiciosTopo;

interface

uses
  uconstantes_nettopos, xMatDefs, SysUtils, ubuffrw,
  uAuxiliares,
{$IFDEF WINDOWS}
  ShellApi, Windows, 
{$ELSE}
  uEmuladorWinIPC, uWinMsgs,
{$ENDIF}  
{$IFDEF NETTOPOS_DLL}
  uimportnettopos,
{$ELSE}
  unettopos,
  unettopostypes,
  uglobsharedmem
{$ENDIF}; 

type
  TServiciosTopo = class
    private
      function getOLanzarTopoLocal: Cardinal;
    public
      idTopoLocal: Cardinal;
      idNodoLocal: Cardinal;

      Constructor Create;

      function pedirGet_NodosSincrono(excluirNodoLocal: boolean): TDAofNCardinal;
{      procedure pedirGet_NodosAsincrono;
      function recibirGet_NodosAsincrono(var msg: TMessage): TDAofNCardinal;}
      function pedir_RunCmd_Sincrono(idNodo: Cardinal; nomAplicacion: String): Cardinal;

      function lanzarAppSiNoExiste(idNodo: Cardinal; nomAplicacion: String): Cardinal;
  end;

implementation

Constructor TServiciosTopo.Create;
begin
  inherited Create;
  idNodoLocal:= getIdNodoLocal;
  idTopoLocal:= getOLanzarTopoLocal;
end;

function TServiciosTopo.pedirGet_NodosSincrono(excluirNodoLocal: boolean): TDAofNCardinal;
var
  comunicadoAEnviar, comunicadoRecibido: TFichaComunicado;
  idPeticion: Cardinal;
  buffReader: TBuffReader;
  res: TDAofNCardinal;
begin
  with comunicadoAEnviar do
  begin
    idNodoOrigen:= idNodoLocal;
    idOrigen:= idAplicYo;
    idNodoDestino:= idNodoLocal;
    idDestino:= idTopoLocal;
    codigoMsg:= uconstantes_nettopos.MSGP_GETNODOS;
    nBytesDatos:= 0;
    pdatos:= NIL;
    lParam:= 0;
    idTarea:= 0;
  end;

  idPeticion:= comunicarTS(@comunicadoAEnviar, NIL, 5000);
  if idPeticion = 0 then
    raise Exception.Create('TServiciosTopo.pedirGet_NodosSincrono: el topo no me respondió los ids de los nodos');

  if leerFichaComunicado(idPeticion, @comunicadoRecibido) = 0 then
    raise Exception.Create('TServiciosTopo.pedirGet_NodosSincrono: no pude leer la ficha del comunicado de respuesta');

  buffReader:= TBuffReader.Create(comunicadoRecibido.pdatos, comunicadoRecibido.nBytesDatos);
  buffReader.xTDAOfCardinal(res);
  buffReader.Free;

  if levantarDatosComunicado(idPeticion, NIL, 0) = 0 then
    raise Exception.Create('TServiciosTopo.pedirGet_NodosSincrono: no pude leevantar los datos de la respuesta');

  if excluirNodoLocal then
    res:= quitarElementoTDAOfNCardinal(res, idNodoLocal);

  result:= res;
end;

function TServiciosTopo.pedir_RunCmd_Sincrono(idNodo: Cardinal; nomAplicacion: String): Cardinal;
var
  res: Cardinal;
  msjError: String;
  comunicadoAEnviar, comunicadoRecibido: TFichaComunicado;
  idPeticion: Cardinal;
  buffWriter: TBuffWriter;
  buffReader: TBuffReader;
begin
  with comunicadoAEnviar do
  begin
    idNodoOrigen:= idNodoLocal;
    idOrigen:= idAplicYo;
    idNodoDestino:= idNodo;
    idDestino:= getIdAplicacion(idNodo, uconstantes_nettopos.AppName_Topo);
    codigoMsg:= uconstantes_nettopos.MSGP_RUNCMD;
    lParam:= 0;
    idTarea:= 0;
  end;

  comunicadoAEnviar.nBytesDatos:= xSizeOf(nomAplicacion);

  buffWriter:= TBuffWriter.Create(comunicadoAEnviar.nBytesDatos);
  buffWriter.xString(nomAplicacion);

  idPeticion:= comunicarTS(@comunicadoAEnviar, buffWriter.pBuff, 5000);
  buffWriter.Free;
  if idPeticion = 0 then
    raise Exception.Create('TServiciosTopo.pedir_RunCmd_Sincrono: el topo no me respondió el resultado de run cmd');

  if leerFichaComunicado(idPeticion, @comunicadoRecibido) = 0 then
    raise Exception.Create('TServiciosTopo.pedir_RunCmd_Sincrono: no pude leer la ficha del comunicado de respuesta');

  buffReader:= TBuffReader.Create(comunicadoRecibido.pdatos, comunicadoRecibido.nBytesDatos);
  buffReader.xCardinal(res);
  if res <= 0 then
    buffReader.xString(msjError);
  buffReader.Free;

  if levantarDatosComunicado(idPeticion, NIL, 0) = 0 then
    raise Exception.Create('TServiciosTopo.pedir_RunCmd_Sincrono: no pude leevantar los datos de la respuesta');

  result:= res;
end;

function TServiciosTopo.lanzarAppSiNoExiste(idNodo: Cardinal; nomAplicacion: String): Cardinal;
var
  nomAplicacionPChar: String;
  res: Cardinal;
begin
  nomAplicacionPChar:= nomAplicacion + #0;
  res:= getIdAplicacion(idNodo, @nomAplicacionPChar[1]);
  if res = 0 then
  begin
    if pedir_RunCmd_Sincrono(idNodo, nomAplicacion) = 0 then
      raise Exception.Create('TServiciosTopo.lanzarAppSiNoExiste: error no obtuve el identificador de la aplicacion ' + nomAplicacion + ' en el nodo ' + IntToStr(idNodo))
    else
    begin
      sleep(500);
      res:= getIdAplicacion(idNodo, @nomAplicacionPChar[1]);
    end;
  end;
  result:= res;
end;

function TServiciosTopo.getOLanzarTopoLocal: Cardinal;
var
  idTopo: Cardinal;
  dir : pchar;
  dirAsString: String;
begin
  idTopo:= getIdAplicacion(0, uconstantes_nettopos.AppName_Topo);
  if idTopo = 0 then  //Si no encontre un topo corriendo ejecuto uno
  begin
    dirAsString:= GetCurrentDir;
    GetMem(dir, length(dirAsString) + 1);
    StrPCopy(dir, dirAsString);
{$IFDEF WINDOWS}
    //TODO
    //ver si se puede sacar el 0
    if Shellexecute(0, 'open', uconstantes_nettopos.BinName, nil, dir, SW_SHOW ) <> 0 then
{$ELSE}
    if LanzarApl(uconstantes_nettopos.BinName, []) then
{$ENDIF}
    begin
      sleep(500); //Doy tiempo al topo de registrarse
      idTopo:= getIdAplicacion(0, uconstantes_nettopos.AppName_Topo);
    end;
    FreeMem(dir, length(dirAsString) + 1);
  end;
  result:= idTopo;
end;

end.
