// This may look like C code, but it is really -*- C++ -*-
// Classe interpreteur de commande pour piapp 
// Reza      Aout 97 , Juillet,Aout 98
// LAL-IN2P3/CNRS

#ifndef PIACMD_H_SEEN
#define PIACMD_H_SEEN

#include "machdefs.h"
#include <iostream>
#include <fstream>
#include <string>
#include <vector>
#include <list>
#include <stack>
#include <map>
#include <functional>

#include "dlftypes.h"
#include "pdlmgr.h"
#include "ctimer.h"

// Classe definissant l'interface pour un executeur de commande
class CmdExecutor {
public:
  virtual	~CmdExecutor() {} ;
  // keyw : Le mot cle associe , args: Arguments de la commande
  virtual int	Execute(string& keyw, vector<string>& args, string& toks)=0;
};

// Classe definissant l'interface pour un interpreteur de commande
class CmdInterpreter {
public:
  virtual		~CmdInterpreter() {} ;
  virtual string	Name()=0;
  virtual int		Interpret(string& line)=0;
};



// Forward declaration of some classes ...
class NamedObjMgr;
class PIStdImgApp;
#ifdef SANS_EVOLPLANCK
class Timer;
#else
namespace SOPHYA { 
class Timer;
}
#endif

class PIAHelpWind;   // Fenetre d'aide en ligne 
class CxxExecWind;   // Fenetre pour CxxExecutor
class CxxOptionWind; // Option de CxxExecutor

class PIACmdBloc;    // Bloc de type foreach / for de l'interpreteur PIACmd
class PIACmdScript;  // Script de commandes defini ds l'interpreteur PIACmd

// ---------------------------------------------------------------------
// Classe Interpreteur de commande, gestionnaire de module chargeable,
// et de fonctions dynamiquement linke pour PIStdImgApp
// Permet de gerer plusieurs Interpreter differents 
// ---------------------------------------------------------------------


class PIACmd : public CmdInterpreter  {
public:
  static PIACmd*	GetInterpreter();

			PIACmd(NamedObjMgr* omg, PIStdImgApp* app);
  virtual		~PIACmd();
  virtual string	Name();

  virtual void		RegisterCommand(string& keyw, string& usage, CmdExecutor * ce, 
                                        string grp="Commands");
  virtual void		RegisterHelp(string& keyw, string& usage, string& grp);
  virtual void		LoadModule(string& fnameso, string& name);

  virtual void		AddInterpreter(CmdInterpreter * cl);
  virtual void		SelInterpreter(string& name);

  virtual int		Interpret(string& line);
  virtual int		ParseLineExecute(string& line, bool qw=true);
  virtual int		ExecuteCommand(string& keyw, vector<string>& args, string& toks);
  virtual int		ExecFile(string& file, vector<string>& args);
  virtual int		CShellExecute(string cmd);
  virtual string&	GetUsage(const string& kw);

          void		ShowHelpWindow();
          void          ShowCxxOptionWindow();
          void          ShowCxxExecWindow();

  virtual void 		HelptoLaTeX(string const & flnm);

  inline  CmdInterpreter* CurrentInterpreter() { return(curcmdi); }
  inline  CmdExecutor*    BaseExecutor()  { return(basexec); }
  inline  CmdExecutor*    ContExecutor()  { return(cntexec); } //_OP_
  inline  PIStdImgApp*    GetImgApp() { return(mImgApp); }

//   Pour utilisation par PIAHelpWind uniquement 
  virtual void		UpdateHelpList(PIAHelpWind* hw, int gid);

//   Utilitaire pour decoupage en mot
  static  int   LineToWords(string& line, string& kw, vector<string>& tokens,
			    string& toks, bool uq=true);
protected:
  virtual int	CheckHelpGrp(string& grp);
  int           ExecuteCommandLine(string & keyw, vector<string> & args,
				   string & toks);

  int           SubstituteVars(string & s, string & s2);  
  int	        EvaluateTest(vector<string> & args, 
			     string & line, bool & res);
  int	        EvalRPNExpr(vector<string> & args, string & line);

  bool          GetVar(string & vn, string & vv);
  void          PushStack(vector<string> & args);
  void          PopStack(bool psta=true);

  NamedObjMgr* mObjMgr;
  PIStdImgApp* mImgApp;

  CmdInterpreter* curcmdi;
  CmdExecutor* basexec;  // basic command executor
  CmdExecutor* fitexec;  // Fit command executor
  CmdExecutor* pawexec;  // paw-like command executor
  CmdExecutor* cxxexec;  // on-line c++ compile/execution command executor

  CmdExecutor *cntexec; // contour executor _OP_
  CmdExecutor *flwexec; // flow chart executor _OP_
 
// Pour enregistrer la liste de commandes et leurs executeurs et le help
  struct cmdex {int group; string us; CmdExecutor * cex; } ;
  typedef map<string, int, less<string> > CmdHGroup;   // Liste des groupes de commandes
  CmdHGroup cmdhgrp;
  int cmdgrpid;                                     // Numero de groupe courant
  typedef map<string, cmdex, less<string> > CmdExmap;
  CmdExmap cmdexmap;
  CmdExmap helpexmap;                               // Pour les helps sans commande

// Pour garder la liste des modules 
  typedef map<string, PDynLinkMgr* , less<string> > Modmap;
  Modmap modmap;

// Pour garder la liste des interpreteur
  typedef map<string, CmdInterpreter*, less<string> > InterpMap;
  InterpMap interpmap;
 
//  Pour stocker les scripts definis ds l'interpreteur
  typedef map<string, PIACmdScript*, less<string> > ScriptList;
  ScriptList mScripts;  // Liste des scripts
  PIACmdScript* curscript; // Script en cours de definition

//  Pour stocker les alias definies par l'interpreteur
  typedef map<string, string, less<string> > CmdStrList;
  CmdStrList mAliases;  // Liste des alias 

// Le stack pour les arguments des .pic et des scripts
  stack< vector<string> > ArgsStack;

  stack< PIACmdBloc * > CmdBlks;  // Bloc de commande courant (foreach, ...)
  int felevel;                    // foreach-for level 
  stack< list<char> > TestsStack; // Stack des resultats de test
  list<char>::iterator tresit;       // Test courant
  bool curtestresult;             // Resultat courant des tests 

  bool mulinefg;            // Bloc multi-lignes (ligne suite)
  string mulinecmd;         // Commande multi-lignes
  string spromptmul;        // Prompt console avant multi-ligne

  ofstream hist;       //  History file 
  bool histon;        //  True ->  history file
  bool trace;          // Trace flag
  bool timing;         // Display CPU Time
  Timer* gltimer;      // pour Display CPU Time

// Fenetre d'aide interactive 
  PIAHelpWind* helpwin;
  CxxExecWind* cxxexwin;
  CxxOptionWind* cxxoptwin;
};



#endif
