unit ueditorsalacmd;

{$mode delphi}

interface

uses
  Classes, SysUtils, syncobjs,
  uConstantesSimSEE,
  usalasdejuego, ucosa,
  usalasdejuegoParaEditor,
  uInicioYFinal;

type
  { TRbtEditorSala_cmd }
  TRbtEditorSala_cmd = class(TRbtEditorSala)
    nid: integer;
    flg_modificada: boolean;

    // lista de ayuda para la exploración por comando ls, cd
    LasCosas: TList;

    aRecLnk: TCosa_RecLnk;
    LaCosa: TCosa;

    constructor Create(nid: integer);

    // Busca el ejecutor asociado a la orden y le pasa los parametros
    // si no encuentra el ejecutor, retonra en la primera linea "error: comando desconocido".
    // si lo encuentra retorna lo que retorne el ejecutor.
    // El comando desconocido puede ser porque el nombre de la orden sea desconocido
    // o porque la cantidad de parámetros no es correcta.
    function ejecutar( orden: string; paramlst: TStrings): TStrings;
  end;


  { TRobotsEditoresLst }

  TRobotsEditoresLst = class(TList)
    cs: TCriticalSection;

    constructor Create;
    destructor Destroy; override;

    // Si no existe retorna nil
    function LocateRobotEditor(nid: integer): TRbtEditorSala_cmd;
    function CreateRobotEditor: TRbtEditorSala_cmd;

    // da el siguiente nid e incrementa el contador en forma segura
    function nextnid: integer;
  private
    cnt_nextnid: integer;
  end;


procedure wrln(r: TStrings; s: string); overload;
procedure wrln( r: TStrings; ls: TStrings); overload;
procedure werror(r: TStrings; s: string);

implementation
uses
  uejecutor;


procedure wrln(r: TStrings; s: string);
begin
  r.Add(s);
end;

procedure wrln(r: TStrings; ls: TStrings);
begin
  r.AddStrings( ls );
end;

procedure werror(r: TStrings; s: string);
begin
  r.add('ERROR: ' + s);
end;


{ TRobotsEditoresLst }

constructor TRobotsEditoresLst.Create;
begin
  inherited Create;
  cs := TCriticalSection.Create;
  cnt_nextnid := 1;
end;

destructor TRobotsEditoresLst.Destroy;
var
  k: integer;
  aRbt: TRbtEditorSala_cmd;
begin
  cs.Enter;
  for k := 0 to Count - 1 do
  begin
    aRbt := items[k];
    aRbt.Free;
  end;
  cs.Free;
  inherited Destroy;
end;

function TRobotsEditoresLst.LocateRobotEditor(nid: integer): TRbtEditorSala_cmd;
var
  buscando: boolean;
  k: integer;
  aRbt: TRbtEditorSala_cmd;
begin
  buscando := True;
  k := 0;
  while buscando and (k < Count) do
  begin
    aRbt := items[k];
    if aRbt.nid = nid then
      buscando := False
    else
      Inc(k);
  end;
  if not buscando then
    Result := aRbt
  else
    Result := nil;
end;

function TRobotsEditoresLst.CreateRobotEditor: TRbtEditorSala_cmd;
var
  aRbt: TRbtEditorSala_cmd;
  anid: integer;
begin
  anid := nextnid;
  aRbt := TRbtEditorSala_cmd.Create(anid);
  cs.Acquire;
  try
    add(aRbt);
  finally
    cs.Release;
  end;
  Result := aRbt;
end;

function TRobotsEditoresLst.nextnid: integer;
begin
  cs.Enter;
  try
    Result := cnt_nextnid;
    Inc(cnt_nextnid);
  finally
    cs.Leave;
  end;
end;


{ TRbtEditorSala }

constructor TRbtEditorSala_cmd.Create(nid: integer);
begin
  inherited Create(nil);
  self.nid := nid;
  flg_modificada:= false;

  // auxiliares
  LasCosas:= nil;
  aRecLnk:=nil;
  LaCosa:= nil;
end;

function TRbtEditorSala_cmd.ejecutar(orden: string; paramlst: TStrings
  ): TStrings;
var
  buscando: boolean;
  k: integer;
  aEjecutor: TEjecutorDeOrden;
  res: TStringList;

begin
  // buscamos el ejecutor
  buscando:= true;
  aEjecutor:= EjecutoresDeOrdenes.findFirmaOk( orden, paramLst );
  if aEjecutor = nil then
  begin
    res:= TStringList.Create;
    aEjecutor:= EjecutoresDeOrdenes.find( orden );
    if aEjecutor = nil then
    begin
      res.add( 'Comando desconocido: '+ orden );
      res.add( '<br>Para obtener un listado de comandos ejecute: "ayuda"' );
    end
    else
    begin
      res.add( 'Error, la sintaxis esperada es: ' );
      res.AddStrings( aEjecutor.ayuda );
    end;
    result:= res;
  end
  else
  begin
    result:= aEjecutor.ejecutar( self, paramLst );
  end;
end;

end.


procedure TFSimSEEEdit.mConsolaKeyPress(Sender: TObject; var Key: char);
var
  aCampoLnk: TCosa_CampoLnk;
  campo, orden, s: string;
  aCosaH: TCosa;
  k, rescod: integer;
begin
  if key = #13 then
  begin
    s := trim(mComandos.Lines[mComandos.Lines.Count - 1]);

    if LasCosas.Count = 0 then
      LasCosas.add(sala);
    LaCosa := LasCosas[LasCosas.Count - 1];

    aRecLnk := LaCosa.rec_lnk;
    if aRecLnk = nil then
    begin
      wrln('LaCosa.rec_lnk = NIL !!!!! PROBLEMA');
    end;

    orden := NextPal(s);

    else if (orden = 'cd') and (s <> '') then
    begin
      if s = '..' then
      begin
        // Subir al Padre
        if LasCosas.Count = 1 then
          wrln('Ya está en la raíz')
        else
        begin
          LasCosas.Delete(LasCosas.Count - 1);
          LaCosa := LasCosas[LasCosas.Count - 1];
          wrln('La Cosa: ' + LaCosa.InfoAd_20);
        end;
      end
      else if length(s) > 0 then
      begin
        val(s, k, rescod);
        if LaCosa is TListaDeCosas then
        begin
          if rescod = 0 then
            if (0 <= k) and (k < TListaDeCosas(LaCosa).Count) then
              aCosaH := TListaDeCosas(LaCosa)[k]
            else
              aCosaH := nil
          else
          if LaCosa is TListaDeCosasConNombre then
            aCosaH := TListaDeCosasConNombre(LaCosa).find(s)
          else
            wrln('no puede buscar por nombre en una lista de cosas sin nombre');

          if aCosaH <> nil then
          begin
            LasCosas.add(TCosa(aCosaH));
          end
          else
            wrln('No fue posible ubicar la Cosa: ' + s);
        end
        else
        begin
          if rescod = 0 then
          begin
            if (0 <= k) and (k < aRecLnk.Count) then
              aCampoLnk := aRecLnk[k]
            else
              aCampoLnk := nil;
          end
          else
            aCampoLnk := LaCosa.GetFieldByName(s);
          if (aCampoLnk <> nil) then
            if (aCampoLnk.CampoDef.ClassName = 'TCosa_CampoDef_Cosa') then
              if aCampoLnk.pval <> nil then
              begin
                LasCosas.add(TCosa(aCampoLnk.pval^));
                LaCosa := LasCosas[LasCosas.Count - 1];
                wrln('La Cosa: ' + LaCosa.InfoAd_20);
              end
              else
                wrln('COSA = NIL no es posible seleccionarla.')
            else
              wrln('El campo: ' + s + ' no es una Cosa')
          else
            wrln('No logré identificar el campo: ' + s);

        end;
      end;
    end
    else if (orden = 'set') then
    begin
      campo := nextpal(s);
      LaCosa.SetValStr(campo, s, self.sala.evaluador);
    end;
  end;
end;
