#include <stdlib.h>
#include <stdio.h>
#include <unistd.h>
#include <iostream>

#include "sopnamsp.h"
#include "pistdimgapp.h"
#include "piacmd.h"
#include "piacmdrdr.h"
#include "piversion.h"
#include "piaversion.h"

#include "timing.h"
#include "skyinit.h"


// ---- Pour charger automatiquement le module sopiamodule 
extern "C" {
void sopiamodule_init();
void sopiamodule_end();
void skymapmodule_init();
void skymapmodule_end();
void fitsbtadapter_init();
void fitsbtadapter_end();
void W2PSModule_init();
void W2PSModule_end();
}

/*!
  \defgroup ProgPI ProgPI module
  This module contains programs for interactive data analysis and
  visualisation, based on SOPHYA class libray and PI (GUI framework)
  and PIext (Interactive data analysis framework).
*/

/*!
  \ingroup ProgPI
  \file piapp.cc
  \brief \b spiapp: Starts the piapp interactive data analysis program.

  This interactive data analysis program uses the SOPHYA libray, 
  the PI GUI library. It has multiple execution threads and a 
  c-shell inspired command execution interpreter. 
  See the piapp user manual for more information.
  The SOPHYA piapp executable is called \b spiapp.

  \verbatim
  csh> spiapp -h
 PIOPersist::Initialize() Starting Sophya Persistence management service 
SOPHYA Version 2.1 Revision 0 (V_Nov2007) -- Nov 24 2007 13:08:58 cxx 

 piapp: Interactive data analysis and visualisation program 
 Usage: piapp [-nored] [-doublered] [-termread] [-term] 
              [-hidezswin] [-small] [-nosig] [-nosigfpe] [-nosigsegv] 
              [-tmpdir TmpDirectory] [-help2tex] [-exec file [args]] 
  -nored : Don't redirect stdout/stderr to piapp console
  -doublered : Redirect stdout/stderr to piapp console AND the terminal
  -termread : Read commands on terminal (stdin)
  -term : equivalent to -nored -termread -small 
  -hidezswin : Hide Zoom/Stat/ColMap window 
  -small : Create small size main piapp window 
  -nosig : Don't catch SigFPE, SigSEGV 
  -nosigfpe -nosigsegv: Don t catch SigFPE / SigSEGV 
  -tmpdir TmpDirectory: defines TMDIR for temporary files 
  -help2tex: Create a LaTeX help file (piahelp.tex)
  -exec file [args] : Execute command file (last option)

  \endverbatim
 
*/

int Usage(bool fgerr)
{
  if (fgerr) { 
    cout << " piapp : Argument Error ! piapp -h for Usage" << endl; 
    return 1;
  }
  else {
    cout << "\n piapp: Interactive data analysis and visualisation program \n"
	 << " Usage: piapp [-nored] [-doublered] [-termread] [-term] \n"
	 << "              [-hidezswin] [-small] [-nosig] [-nosigfpe] [-nosigsegv] \n"
	 << "              [-tmpdir TmpDirectory] [-help2tex] [-exec file [args]] \n"
	 << "  -nored : Don't redirect stdout/stderr to piapp console\n"
         << "  -doublered : Redirect stdout/stderr to piapp console AND the terminal \n"
	 << "  -termread : Read commands on terminal (stdin)\n"
	 << "  -term : equivalent to -nored -termread -small \n"
	 << "  -hidezswin : Hide Zoom/Stat/ColMap window \n"
	 << "  -small : Create small size main piapp window \n"
	 << "  -nosig : Don't catch SigFPE, SigSEGV \n"
         << "  -nosigfpe -nosigsegv: Don t catch SigFPE / SigSEGV \n"
	 << "  -tmpdir TmpDirectory: defines TMDIR for temporary files \n"
	 << "  -help2tex: Create a LaTeX help file (piahelp.tex)\n"
	 << "  -exec file [args] : Execute command file (last option)\n"
	 << endl;
    return 0;
  }
}

/*  ================================ MAIN() =================================  */

int main(int narg, char *arg[])
{
int ofa;
bool fgfpe, fgsegv, fghidezsw, fgexec, fgsmall, fgtermrd;
RED_OUTERR_FLG fgred = CONSRED_OE;

SkyTInitiator skyinit;
   
InitTim();

if(narg>1) 
  for(int jh=1;jh<narg;jh++) if(strcmp(arg[jh],"-h") == 0) return Usage(false);

ofa = 1;
fgred = CONSRED_OE;
fgfpe = fgsegv = true;
fghidezsw = false;
fgexec = false;
bool fgtmp = false;
fgsmall = false;
 fgtermrd = false;
string tmpdir;
string exfc;
// Pour fabriquer le help
bool fgtexh = false;
int ka;
for(ka=1; ka<narg; ka++) {
  if (strcmp(arg[ka],"-nored") == 0)   fgred=NORED_OE; 
  else if (strcmp(arg[ka],"-doublered") == 0)   fgred=DOUBLERED_OE; 
  else if (strcmp(arg[ka],"-nosig") == 0)   fgfpe=fgsegv=false; 
  else if (strcmp(arg[ka],"-termread") == 0)   fgtermrd=true; 
  else if (strcmp(arg[ka],"-term") == 0)  
    { fgred=NORED_OE;  fgtermrd=true; fgsmall=true; }
  else if (strcmp(arg[ka],"-nosigfpe") == 0)   fgfpe=false; 
  else if (strcmp(arg[ka],"-nosigsegv") == 0)   fgsegv=false; 
  else if (strcmp(arg[ka],"-small") == 0)     fgsmall=true; 
  else if (strcmp(arg[ka],"-hidezswin") == 0)   fghidezsw=true; 
  else if (strcmp(arg[ka],"-help2tex") == 0) { fgtexh=true; fgred=NORED_OE; }
  else if (strcmp(arg[ka],"-tmpdir") == 0) {
    if (ka == narg-1) return Usage(true);
    fgtmp = true;  ka++;
    tmpdir = arg[ka];    
  }
  else if (strcmp(arg[ka],"-exec") == 0) {
    if (ka < narg-1) {
      fgexec = true;
      exfc = "exec";
      for(int kaa=ka+1; kaa<narg; kaa++)  { exfc += ' ';  exfc +=  arg[kaa]; }
      }
    break;
    }
  }

 
if (fgexec) printf(">>>>> Starting piapp , Executing %s \n", exfc.c_str()); 
else printf(">>>>> Starting piapp <<<<< \n");

SophyaInitiator::PrintVersion(true);  // SOPHYA version and module list 

// Reza , Jan07
// On cree l'objet PIApplication avant de faire mkdir TmpDir
// En cas de pb X11 , il n'y a pas de repertoire PIATmpxxx qui traine apres

PIStdImgApp * app = new PIStdImgApp(fgsmall, narg, arg);
// cout << " DBG-2 " <<  app->ObjMgr()->GetTmpDir() << endl;

char* vcmds=NULL;
string vcmd;
if (fgtmp) {
  if (tmpdir[tmpdir.length()-1] != '/') tmpdir += '/';  // Necessaire pour SetSwapPath
  vcmd = "TMPDIR=" + tmpdir;
  vcmds = new char[vcmd.length()+1];
  strcpy(vcmds, vcmd.c_str());
  putenv(vcmds);
}

const char* tmpde = getenv("TMPDIR");
char  tmpdname[32];
if (tmpde == NULL) tmpde = "./";
if (tmpde[strlen(tmpde)-1] != '/')
  strcpy(tmpdname, "/PIATmp_XXXXXX"); 
else 
  strcpy(tmpdname, "PIATmp_XXXXXX"); 
mktemp(tmpdname);
tmpdir = tmpde;
tmpdir += tmpdname;
tmpdir += '/';
vcmd = "mkdir ";
vcmd += tmpde;
vcmd += tmpdname;
cout << " --piapp: Creating Tmp Directory: " << tmpdir << endl;
int rcc = system(vcmd.c_str());
if (rcc != 0) {
  cout << " --piapp: Error creating TmpDir " << vcmd << " ---> exit !" << endl;
  return(9);
}

cout << "  NamedObjMgr::SetTmpDir() " << tmpdir << endl;
app->ObjMgr()->SetTmpDir(tmpdir);

// Gestion de redirection stdout/err et Signaux
app->RedirectStdOutErr(fgred);
app->CatchSignals(fgfpe, fgsegv);

// if Hide Zoom/Stat Win
if (fghidezsw)  app->StatZoomWindowSetVisible(false);

// S'il y a un fichier de commande a executer
// if (fgexec) app->CmdInterpreter()->Interpret(exfc);
if (fgexec) app->SubmitCommand(exfc);

// On charge le module sopiamodule
sopiamodule_init();
// On charge le module skymapmodule
skymapmodule_init();
// On charge le module de lecture ligne a ligne des Fits BINARY/ASCII tables
fitsbtadapter_init();
// On charge le module des commandes de creation de fichier postscript
W2PSModule_init();

// S'il y a besoin de faire le fichier Help
if (fgtexh) { 
  string thf = "piahelp.tex";
  app->CmdInterpreter()->HelptoLaTeX(thf);
  printf("piapp : Help file piahelp.tex created --> exit(0) \n"); 
  delete app;
  exit(0);
}

// Creation du lecteur de commande sur terminal (avec GNU readline)
PIACmdReader cmdrdr(app);
if (fgtermrd) cmdrdr.start();

int rc = 0;
bool cont = true;
char rep; // ans[32]
int excnt = 0;
while(cont) {
  rc = 0;   cont = false;
  app->SetReady();
  app->RedirectStdOutErr(fgred);
  try {
    app->Run();
  }
  catch(PThrowable exc) {  // Catching SOPHYA exceptions 
    app->Stop();
    app->RedirectStdOutErr(NORED_OE);  
    //BUG ? fait planter OSF-cxx     fflush(stdout); 
    cout << endl;      cerr << endl;
    cout << "\n piapp/main() PThrowable catched ! " << exc.Msg() << endl;
    cout << ++excnt << "- continue <CR>, Close Windows, "
         << " continue C<CR> Stop program S<CR> ? " << endl; 
    rep = getchar();  // was: gets(ans);
    rep = toupper(rep);  
    if (rep == 'S')  { 
      cout << " !!!! Stopping piapp !!!! " << endl;
      rc = 78;
      cont = false;
    }
    else { 
      if (rep == 'C') {
	cout << "piapp/main() Closing all windows ... " << endl;
	app->CloseAllWindows();
      }
      cout << " *** piapp - Continuing event loop *** " << endl;
      cont = true;
    }
  }
  catch(...) { // Catching all other exceptions 
    app->Stop();
    app->RedirectStdOutErr(NORED_OE);  
    cout << endl;      cerr << endl;
    cout << "\n piapp/main() exception catched ! " << endl;
    cout << ++excnt << "- continue <CR>, Close Windows, "
         << " continue C<CR> Stop program S<CR> ? " << endl; 
    rep = getchar(); // gets(ans);
    rep = toupper(rep);  
    if (rep == 'S')  { 
      cout << " !!!! Stopping piapp !!!! " << endl;
      rc = 78;
      cont = false;
    }
    else { 
      if (rep == 'C') {
	cout << "piapp/main() Closing all windows ... " << endl;
	app->CloseAllWindows();
      }
      cout << " *** piapp - Continuing event loop *** " << endl;
      cont = true;
    }
  }
}
cout << "\n ------------------------------------------------ \n"
     << " piapp: Cleaning up ... " << endl;
app->RedirectStdOutErr(NORED_OE);  
cout << "\n ------------------------------------------------ \n"
     << " piapp: Exiting - Cleaning up ... " << endl;

// -- ca fait planter sur linux -- Reza 04/2006 if (fgtermrd) cmdrdr.cancel();

// On de-charge le module sopiamodule et fitsbtadapter
sopiamodule_end();
skymapmodule_end();
fitsbtadapter_end();
W2PSModule_end();

delete app;
if (fgtmp) delete[] vcmds;

vcmd = "rm -rf ";
vcmd += tmpdir;
cout << " --piapp: Removing Tmp Directory: " << tmpdir << endl;
rcc = system(vcmd.c_str());
if (rcc != 0) {
  cout << " --piapp: Error deleting TmpDir " << vcmd << endl;
  return(9);
}

cout << "------------------------------------------------ \n"
     << "-------- piapp : Exiting .... Rc= " << rc << " -----------\n"
     << "------------------------------------------------ " << endl; 
return(rc);
}

