unit uMonitorSimRes;

{$IFDEF FPC}
  {$MODE Delphi}
{$ENDIF}

interface

uses
  uMonitores, uVarDefs, Classes, uEventosOptSim,
  SysUtils, ufechas, usalasdejuego;

type
  TMonSimRes = class(TMonitores)
  private
    abierto: boolean; //indica si el archivo esta abierto
    defVars: TDAOfVarDef;
    f: TextFile;
    filename: string;
    sala: TSalaDeJuego;

    encabActores, encabUnidades, encabVariables, encabNrosPostes: string;

    procedure armarEncabezados;
  public
    constructor Create(defVars: TList{of TVarDef}; filename: string; sala: TSalaDeJuego);
    function resolverRefProc(refProc: integer): TProcWrapper; override;
    class function darRefProc(nombreProc: string; evento: TEventoOptSim): integer;
      override;

    procedure AbrirArchivo;
    procedure CerrarArchivo;
    procedure EscribirEncabezadoCronica;
    procedure EscribirPaso;

    procedure Free; override;
  end;

implementation

constructor TMonSimRes.Create(defVars: TList{of TVarDef}; filename: string;
  sala: TSalaDeJuego);
var
  i: integer;
begin
  inherited Create;
  abierto := False;
  self.filename := filename;
  self.sala := sala;
  SetLength(Self.defVars, defVars.Count);
  for i := 0 to defVars.Count - 1 do
    self.defVars[i] := defVars[i];
end;

function TMonSimRes.resolverRefProc(refProc: Integer): TProcWrapper;
var
  aux: TProcWrapper;
begin
  case refProc of
    //los procedimientos deben estar en el orden en que se quieren ejecutar
    //abrir archivo debe ser siempre el primero y cerrar el ultimo,
    //se escribe el encabezado de la cronica y luego ultimo el paso
    1: aux := TProcWrapper.Create(self, self.AbrirArchivo);
    2: aux := TProcWrapper.Create(self, self.EscribirEncabezadoCronica);
    3: aux := TProcWrapper.Create(self, self.EscribirPaso);
    4: aux := TProcWrapper.Create(self, self.CerrarArchivo);
    else
      raise Exception.Create('TMonSimRes.resolverRefProc: Metodo no registrado para ' +
        self.ClassName + IntToStr(refProc));
  end;
  Result := aux;
end;

class function TMonSimRes.darRefProc(nombreProc: string;
  evento: TEventoOptSim): integer;
begin
  if nombreProc = 'AbrirArchivo' then
    Result := 1
  else if nombreProc = 'EscribirEncabezadoCronica' then
    Result := 2
  else if nombreProc = 'EscribirPaso' then
    Result := 3
  else if nombreProc = 'CerrarArchivo' then
    Result := 4
  else
    raise Exception.Create('TMonSimRes.darRefProc: Procedimiento no registrado ' +
      nombreProc);
end;

procedure TMonSimRes.AbrirArchivo;
begin
  AssignFile(f, filename);
  {$I-}
  rewrite(f);
  {$I+}
  if ioresult <> 0 then
    raise Exception.Create('Falló en: TMonSimRes.AbrirArchiv: ' +
      filename + #13 + 'Verifique que exista la carpeta destino.');
  abierto := True;
  sala.SimPrint.Inicio;
  armarEncabezados;
end;

procedure TMonSimRes.CerrarArchivo;
begin
  sala.SimPrint.Free;
  abierto := False;
end;

procedure TMonSimRes.EscribirEncabezadoCronica;
begin
  writeln(f);
  Writeln(f, 'CRONICA:', #9, sala.globs.kCronica_, #9, 'SemillaAleatoria:', #9,
    sala.globs.MadresUniformes.get_UltimaSemilla, 'EstadoInicial:', #9, sala.globs.kEstadoInicial_);
  Writeln(f, encabActores);
  Writeln(f, encabUnidades);
  Writeln(f, encabVariables);
  Writeln(f, encabNrosPostes);
end;

procedure TMonSimRes.EscribirPaso;
var
  i: integer;
begin
  Write(f, sala.globs.kPaso_Sim, #9, sala.globs.FechaInicioDelpaso.AsISOStr, #9);
  for i := 0 to high(defVars) - 1 do
    Write(f, defVars[i].asS, uVarDefs.vectorSeparator);
  WriteLn(f, defVars[high(defVars)].asS);
end;

procedure TMonSimRes.Free;
begin
  SetLength(defVars, 0);
  if abierto then
  begin
    closefile(f);
    abierto := False;
  end;
  inherited Free;
end;

procedure TMonSimRes.armarEncabezados;
var
  i: Integer;
  nomActor, unidadesVar, nombreVar, indiceVar: String;
begin
  encabActores := '-'#9'-';
  encabUnidades := '-'#9'-';
  encabVariables := '-'#9'-';
  encabNrosPostes := 'Paso'#9'FechaInicioDelPaso';

  for i := 0 to High(defVars) do
  begin
    defVars[i].getNombreUnidadesNomVarEIndice(nomActor, unidadesVar,
      nombreVar, indiceVar);

    encabActores := encabActores + vectorSeparator + nomActor;
    encabUnidades := encabUnidades + vectorSeparator + unidadesVar;
    encabVariables := encabVariables + vectorSeparator + nombreVar;
    encabNrosPostes := encabNrosPostes + vectorSeparator + indiceVar;
  end;
end;

end.
