unit uFuncionesAuxiliares;

{$mode delphi}

interface

uses
  Classes, uconstantes_nettopos, uheapmanager, ubuffrw, uConstantesSimSEE,
  SysUtils, zipper, xMatDefs, unettopostypes, unettopos, uNodosDeCalculo,
  uglobsharedmem,

  {$IFDEF LINUX}
   uEmuladorWinIPC, ukeydir
  {$ELSE}
  FileUtil, windows, ipcthrd
  {$ENDIF}
  ;

type

    TDArrOfBytes = array of byte;

//funcion para bajar disco un buffer de archivo
procedure bajarArchivos (destino: string; archi: TBuffReader);

function get_FileLst (patron, dir: string):TStringList;
function vaciarDir (dir: string): boolean;

//funciones para zippeo/unzippeo de archivos
function zippearArchvios (zipName: String;lstArchivos: TStringList; destino:String): boolean;
function unZippearArchivos (dirSalida, zipFile: string): boolean;

//Retorna la lista de archivos que tienen que estar disponibles para la
//ejecución de la sala. Crea un archivo de sala modificado con los paths
//de los archivos modificados para que arranquen de dirbase
//El archivo de sala modificado se agrega a la lista resultado en el primer
//lugar
function procesarPaths(archiSala: string): TStringList;
//Es el path que tendran los archivos en los nodos cliente
procedure toNetoposPath(var path: String);

//crea un array de largo XdivY y cada casilla le asigna ese valor, despues
//si hay resto (XmodY) suma 1 a las primeras XmodY.
//Se usara para repartir las tareas de forma estatica (tareas sobre nodos)
function XdivYrepartirResto(x: integer; y:integer):TDAofNInt;


function getOLanzarTopoLocal(var idTopo:Cardinal):Boolean;

{$IFDEF LINUX}
 function ExtractFileNameOnly(str: string):string;
{$ENDIF}

implementation


procedure bajarArchivos(destino: string; archi: TBuffReader);
var
  nombre:string;
  nBytesArchivo: TDArrOfBytes;
  fileModoOLD: Byte;
  f: TypedFile;

begin

 SetLength(nBytesArchivo, archi.tamBuff);
 archi.xBytes(nBytesArchivo[0], archi.tamBuff);

 fileModoOLD := filemode;
 filemode:= 2;

 AssignFile(f, destino+'archivoTMP.zip');
 writeln(destino+'archivoTMP.zip '+IntToStr(archi.tamBuff));
 system.rewrite(f,1);


 BlockWrite(f, nBytesArchivo[0], archi.tamBuff);

 CloseFile(f);
 Filemode := fileModoOLD;

 writeln(unZippearArchivos(destino, 'archivoTMP.zip'));

 DeleteFile(pchar(destino+'archivoTMP.zip'));

end;

function get_FileLst(patron, dir: string): TStringList;

var
  Rslt: TSearchRec;
  Lst: TStringList;
  i: Integer;

begin
     Lst := TStringList.Create;
     if FindFirst(dir+patron, faArchive, Rslt) = 0 then
     begin
          repeat
                Lst.Add(dir+Rslt.Name);
          until FindNext(Rslt)<>0;
     //FindClose(Rslt);
     end;
     result := Lst;
end;

function vaciarDir(dir: string): boolean;
var
 fileLst: TStringList;
 i: Integer;
begin
 fileLst := get_FileLst('*.*', dir+DirectorySeparator);
 for i:=0 to fileLst.Count-1 do
  DeleteFile(pchar(dir+DirectorySeparator+fileLst[i]));
end;

function unZippearArchivos(dirSalida, zipFile: string): boolean;
var
  UnZipper: TUnZipper;
begin
 try
  UnZipper := TUnZipper.Create;
  UnZipper.FileName := dirSalida+zipFile;
  UnZipper.OutputPath := dirSalida;
  UnZipper.Examine;
  UnZipper.UnZipAllFiles;
  UnZipper.Free;
  result:=true;
 except
  result:=false;
 end;
end;

function procesarPaths(archiSala: string): TStringList;
var
  f, fMod: TextFile;
  res: TStringList;
  posIgual, posPuntoYComa, posPunto: Integer;
  linea, pathPosible: String;
  fileName: String;
begin
  res := TStringList.Create;
  fileName := ExtractFileName(archiSala);
  res.Add(getDir_Tmp+fileName);
  AssignFile(f, archiSala);
  AssignFile(fMod, getDir_Tmp+fileName);
  try
    Reset(f);
    Rewrite(fMod);
    while not Eof(f) do
    begin
      Readln(f, linea);
      posIgual:= pos('= ', linea);
      if posIgual <> 0 then
      begin
        posPuntoYComa:= Pos(';', linea);
        pathPosible:= quitarRaiz_(copy(linea, posIgual + 2, posPuntoYComa - 2 - posIgual));
        if FileExists(pathPosible) then
        begin
          writeln(pathPosible);
          if res.IndexOf(pathPosible) = -1 then
            res.Add(pathPosible);
          toNetoposPath(pathPosible);
          Writeln(fMod, copy(linea, 1, posIgual + 1) + pathPosible + ';');
        end
        else
          writeln(fMod, linea);
      end
      else
        Writeln(fMod, linea);
    end;
  finally
    CloseFile(f);
    CloseFile(fMod);
  end;
  result:= res;
end;

procedure toNetoposPath(var path: String);
begin
 path := getDir_DatosComunes+ExtractFileName(path);
end;

function XdivYrepartirResto(x: integer; y: integer): TDAofNInt;
var
 arr: TDAofNInt;
 cociente, resto: Integer;
 i: Integer;
begin
 cociente:= x div y;
 resto := x mod y;
 SetLength(arr, y);
 for i:= 0 to y-1 do
  if i < resto then
   arr[i]:=cociente+1
  else
   arr[i]:=cociente;

 result:= arr;
end;

function getOLanzarTopoLocal(var idTopo: Cardinal): Boolean;
var
   id: Cardinal;
   smf: Tmutex;
begin

   {$IFDEF LINUX}
     smf := TMutex.Create(keySmfGetOLanzarTopo , 1);
   {$ELSE}
     smf := TMutex.Create(nom_smf_get_lanzar_topo);
   {$ENDIF}


   if not smf.get(2000) then
   begin
     writeln('no consegui smf_get_lanzar_topo');
     idTopo := 0;
     smf.Free;
     exit;
   end;

   Result:= False;
   idTopo:= getIdAplicacion(0, uconstantes_nettopos.AppName_Topo);
   if idTopo = 0 then  //Si no encontre un topo corriendo ejecuto uno
   begin
 {$IFDEF WINDOWS}
     //TODO
     //ver si se puede sacar el 0
     id := ShellExecuteA(0, nil, uconstantes_nettopos.AppName_Topo, nil, nil, SW_SHOWMINIMIZED );
     if id > 32 then
 {$ELSE}
     if LanzarApl(uconstantes_nettopos.BinName, []) then
 {$ENDIF}
     begin
       sleep(500); //Doy tiempo al topo de registrarse
       idTopo:= pm^.idTopoLocal;
     end;
     result:= True;

   end;

   smf.Release;
   smf.Free;

end;


{$IFDEF LINUX}
function ExtractFileNameOnly(str: string):string;
var
   fileName_: string;
begin
 fileName_:= ExtractFileName(str);
 SetLength(fileName_, Length(fileName_)-4);

 result:= fileName_;;

end;
{$ENDIF}

//zippea los archivos y los pone en la carpeta temporal, la idea es borrarlo luego de enviado
function zippearArchvios (zipName: String;lstArchivos: TStringList; destino:string): boolean;
var

 zipiador: TZipper;
 i: Integer;
 nombreArchivo: string;
 ultimaBarraPos: integer;
 oldDir: String;


begin
 try
  oldDir:= GetCurrentDir;
  ChDir(destino);

  zipiador := TZipper.Create;
  zipiador.FileName:= zipName;
  for i := 0 to lstArchivos.Count-1 do
   begin
    //nombreArchivo:=lstArchivos[i];
    //ultimaBarraPos:=LastDelimiter(DirectorySeparator,nombreArchivo);
    //delete( nombreArchivo, 1, ultimaBarraPos);
    zipiador.Entries.AddFileEntry(lstArchivos[i], ExtractFileName(lstArchivos[i]));
   end;
  zipiador.ZipAllFiles;
  zipiador.Free;
  result := true;

  ChDir(oldDir);
 except
  result := false;
 end;
end;


end.

