// This may look like C code, but it is really -*- C++ -*-
// Standard Image App      R. Ansari  97-98
// LAL (Orsay) / IN2P3-CNRS  DAPNIA/SPP (Saclay) / CEA

#ifndef PISTIMGAPP_H_SEEN
#define PISTIMGAPP_H_SEEN

#include <string.h>
#include <string>
#include <map>
#include <functional>

#include "pisysdep.h"

#include PIAPP_H
#include PIWIN_H 
#include PIMENU_H 
#include PIOPTMENU_H 

#include PISTDWDG_H 

#include PIFILECHO_H 
#include PIPERIODIC_H

#include "picons.h"

#include "piimage.h"
#include "pi3dwdg.h"
#include "nobjmgr.h"
#include "piacmd.h"
#include "pisiadw.h"
#include "pistzwin.h"

#include "pitherm.h"

#include "zthread.h"
#include "resusage.h"


enum DispWinEnum {Disp_Default, Disp_Next, Disp_Win, Disp_Same, Disp_Stack, Disp_Inset};
// Flag de redirection stdout/stderr  
enum RED_OUTERR_FLG { NORED_OE, CONSRED_OE, DOUBLERED_OE };  


typedef map<long, PIWindow*, less<long> > WindMList;
typedef map<long, PIWdg*, less<long> > BWMList;
typedef map<long, PIDrawer*, less<long> > DrwMList;

class PIStdImgApp : public PIApplication  {
public:
     PIStdImgApp(bool fgsmall=false, int narg=0, char* arg[]=NULL);
     ~PIStdImgApp();

     virtual void   Process(PIMessage msg, PIMsgHandler* sender, void* data=NULL);
     virtual void   SetReady();
     virtual void   SetBusy(); 
     virtual void   SetBlocked();

  // <ZThread>  Multithread execution 
  // On redefinit la methode Run pour gestion multithread
     virtual void   Run();
     inline ZMutex &   getMutex() { return thr_glsyn; }
     inline void       LockMutex() { thr_glsyn.lock(); }
     inline void       UnlockMutex(bool fgbr=false) 
        { if (fgbr) thr_glsyn.broadcast(); thr_glsyn.unlock(); }
     inline bool       isGlSyncLocked() { return fg_glsynlock; }
     int               CheckPendingEvents();
     void              CkEvt_LockMutex(); // On fait le lock apres verification de traitement des evenements

  // Methodes d'Affichage generique
     int  DispImage(P2DArrayAdapter* nouv, string const & name, string const & opt, 
		    bool fgimagnav=false, int oid=0, bool fglock=true);
     int  DispScDrawer(PIDrawer* scd, string const & name, string const & opt, 
		       string title="", int oid=0, bool fglock=true);
     int  Disp3DDrawer(PIDrawer3D* scd, string const & name, string const & opt, 
		       string title="", int oid=0, bool fglock=true);

  //  Specification (de l'exterieur) de commande a executer 
     inline void SubmitCommand(string const& cmd) 
            { exc_command = cmd;  fg_exc_cmd = true; }
  //  Execution de commande soumis de l'exterieur
     int  ExecuteExtCommand();
     
  //  Fonction d'ajout de texte (provisoire - Aout 99) 
     void AddText(string const & txt, double xp, double yp, string const& opt, bool fgcn=false);
     void AddCompText(string const & txt, string const & txtup, string const & txtdn, 
		      double xp, double yp, string const& opt, 
		      string const& optss, bool fgcn=false);
  //  Ajout de lignes, rectangles, cercles (provisoires - Aout 2001)
     void AddLine(double xp1, double yp1, double xp2, double yp2, 
		  string const& opt, bool fgarrow=false, bool fgcn=false);
     void AddRectangle(double xp1, double yp1, double xp2, double yp2, string const& opt, 
		       bool fgfill=false, bool fgcn=false);
     void AddCircle(double xc, double yc, double r, string const& opt, 
		    bool fgfill=false, bool fgcn=false);
     void AddOval(double xp, double yp, double dx, double dy, string const& opt, 
		  bool fgfill=false, bool fgcn=false);
     void AddArc(double xc, double yc, double r, double a, double da, 
		 string const& opt, bool fgfill=false, bool fgcn=false);
     void AddArc(double x1, double y1, double x2, double y2,
		 double x3, double y3, string const& opt, bool fgfill=false, bool fgcn=false);
     void AddPoly(vector<double>& x, vector<double>& y, 
		  string const& opt, bool fgfill=false, bool fgcn=false);

  //  Fonction Ajout de titre de trace
     void SetTitle(string const & titleup, string const & titledown, string const& opt);
  //  Fonction d'Ajout label d'axe X,Y 
     void SetAxeLabels(string const & xLabel, string const & yLabel, string const& opt);

  //  Acces au BaseDrawer (PIElDrawer) du PIBaseWdg courant
     PIDrawer* CurrentElDrawer();

     void CreateGraphWin(int nx=1, int ny=1, int sx=0, int sy = 0);
     void CreateStackWin(int sx=0, int sy = 0);
     PIWindow * GetWindow(DispWinEnum typ, int& sx, int& sy, int& px, int& py, int& flag, char * nom);
     void SetZone(int nzx=1, int nzy=1);
     void StackWinNext();

  // Pour specifier le widget pour le trace en superpose, en specifiant un nom de widget
     void SelectLastWidget(string & nom);
  // Pour specifier le widget pour le trace en superpose, en specifiant un nom d'objet
     void SelectLastWidgetByObjName(string & nom);
     
     void DeleteWindow(PIWindow* w);
     void DeleteWidget(PIWdg* w, bool dw=true, bool dwin=true);
     void DelWRsId(int k);
     bool CheckWRsId(int k);
     void CloseAllWindows();

     inline NamedObjMgr* ObjMgr() { return mObjMgr; }
     inline PIACmd* CmdInterpreter() { return mCmd; }
     inline SOpExObj* getSOpExObj() { return mSopex; }

     PIWindow* CurrentWindow() { return (mCurWin); };
     PIBaseWdg* CurrentBaseWdg() { return (mCurWdg); };

     inline PIPixmap* ZoomW() { return zoom; }
     inline PIPixmap* GloVW() { return gimv; }
     inline PICMapView* CMapVW() { return cmapv; }
     inline PIConsole* GetConsole() { return mCons; }

     inline PIMenu* SpecialMenu() { return m[5]; }
     inline PIMenu* ModulesMenu() { return m[6]; }

     inline ObjMgrWind* ObjMgrW() { return mObjmgrw; }
     inline PPInMgrWind* PPInMgrW() { return mPpinmgrw; }

// Gestion (show/hide) de la fenetre Stat/ZoomWindow 
    void   StatZoomWindowSetVisible(bool fg=true);

// Update de l'info de la fenetre stats/ressources
    void   UpdateStatResourceInfo();

// Redirection ou Non de StdOut/StdErr
     void  RedirectStdOutErr(RED_OUTERR_FLG redflg=CONSRED_OE);
     inline RED_OUTERR_FLG HasRedirectedStdOutErr() { return(redirecout); }
// Gestion des signaux
     void  CatchSignals(bool fgfpe=true, bool fgsegv=true);

     void  SetInsetLimits(double xmin=0.4, double xmax=0.6, double ymin=0.4, double ymax=0.6);
     inline void  SetAutoAddTitle(bool aatit=true) { mAddTitle = aatit; }
     void  SetAxesAtt(unsigned int axfl) { mAxesFlags = axfl; }
  //     void  SaveGraphicAtt();
  //     void  RestoreGraphicAtt();
     void  SetDefaultGraphicAttributes(string const & opt);
     void  SetDefaultAxesAttributes(string const & opt);
     DispWinEnum ParseDisplayOption(string const & opt, vector<string>& opts, string& wname);
     inline DispWinEnum ParseDisplayOption(string const & opt, vector<string>& opts)
       {
	 string wname;
	 return ParseDisplayOption(opt, opts, wname);
       }

// Gestion fichiers PS
    int num_eps;
    PSFile *mpsfile;
    string name_ps;

// Gestion OUT-PPF
    POutPersist* mPpfout;
    string name_outppf;    

private:
    void MBProcess1(PIMessage msg, PIMsgHandler* sender, void* data=NULL);
    void MBProcess2(PIMessage msg, PIMsgHandler* sender, void* data=NULL);
    void MBProcess3(PIMessage msg, PIMsgHandler* sender, void* data=NULL);
    void MBProcess4(PIMessage msg, PIMsgHandler* sender, void* data=NULL);
    void MBProcess5(PIMessage msg, PIMsgHandler* sender, void* data=NULL);
    void MBProcess6(PIMessage msg, PIMsgHandler* sender, void* data=NULL);

    

    NamedObjMgr* mObjMgr;
    PIACmd* mCmd;
    SOpExObj* mSopex;

    PIMenu* m[7];
    PIMenu* mc;

    PIContainer* statcont;    // Container pour les widgets zoom, gimv, cmapv ...
    PIPixmap* zoom;
    PIPixmap* gimv;
    PICMapView* cmapv;
  // Pour afficher des stats et etat thread command
    PILabel* lab_mem;
    PIThermometer* therm_mem;
    PILabel* lab_cpu;
    PIThermometer* therm_cpu;
    PILabel* lab_thrcmd;

    PIFileChooser * pfc_fits;   // Pour les fichiers FITS
    PIFileChooser * pfc_ppf;    //  Pour les PPF 
    PIFileChooser * pfc_ascii;  //  Pour les fichiers ASCII 
    PIFileChooser * pfc_ps;     // Pour les PostScript

    PIContainer* consolecont;    // Container pour la PIConsole
    PIConsole* mCons;
    RED_OUTERR_FLG redirecout;    // flag de redirection vers  mCons, ou NORED ou vers mCons+terminal;

    WindMList mWList;
    BWMList mBWList;
    DrwMList mDrwList;

    int mWId,mDId,mBWId;

    PIBaseWdg* mCurWdg;
    PIBaseWdg* mLastWdg;
    PIWindow* mCurWin;
    PIZoneWindow* mGrW;
    PIStackWindow* mStW;
    int mGrIdx;
    int mStIdx;

    ObjMgrWind* mObjmgrw;
    PPInMgrWind* mPpinmgrw;

  // Attributs graphiques, etc ...
    double	 mIXmin, mIXmax, mIYmin, mIYmax;
    bool         mAddTitle;
    unsigned int mAxesFlags;

    vector<string> mDefaultAtt;
    vector<string> mAxesAtt;  

  //  Controles et gestion divers 
    PIMessage mFCMsg;  // Message for processing FileOpen
    int mFgScSz;   // Flag ScreenSize
    bool mFgCWImg; // true -> Current Widget is PIImage

  // Pour comptabiliser l'utilisation des ressources
    ResourceUsage resusg;
    PIPeriodic* resupd_periodic;

  // Commande specifie de l'exterieur a executer 
  // Pris en charge par resupd_periodic
    string exc_command;
    bool fg_exc_cmd;
  // Attributs pour controle de thread
    ZMutex thr_glsyn;
    bool fg_glsynlock;  // true: thr_glsyn locke pour traitement evts
    XtAppContext * _appctx; // Pour CheckPendingEvents()  $CHECK$ A supprimer si possible ...
};

#endif
