#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <math.h>

#include <iostream>

#include "sopnamsp.h"
#include "pisysdep.h"

#include PIAPP_H
#include PIMENU_H 
#include PISTDWDG_H 
#include PIWIN_H
#include PIPERIODIC_H

#include "pidrawwin.h"
#include "piscdrawwdg.h"
#include "piyfxdrw.h"
#include "piimage.h"
#include "parradapter.h"

#include "psfile.h"

#include "piimgtools.h"
#include "pidrwtools.h"
#include "piaxestools.h"

#include "pisurfdr.h"
#include "pi3dwdg.h"


//  ---------- classe PITApp -----------------------
class PITApp : public PIApplication {
public:
     PITApp(int narg=0, char* arg[]=NULL);
     ~PITApp();
     virtual void   Process(PIMessage msg, PIMsgHandler* sender, void* data=NULL);

  PIMenu* m[3];
  PIText* txt;
  PIPixmap* zoom;  
  PICMapView* cmapv;
  PIWindow *mCurW;
};


/* --Methode-- */
PITApp::PITApp(int narg, char* arg[])
: PIApplication(360, 130, narg, arg) 
{

m[0] = new PIMenu(Menubar(),"Fichier");
m[0]->AppendItem("Info", 10101);
m[0]->AppendItem("Close", 10110);
m[0]->AppendItem("Exit", 10150);
// On accroche le menu au Menubar
AppendMenu(m[0]);

// 2eme Menu

m[1] = new PIMenu(Menubar(),"Graphics");
m[1]->AppendItem("Sin(x)/x", 10201);
m[1]->AppendItem("YfXDrawer", 10202);
m[1]->AppendItem("2-Drawers", 10203);
m[1]->AppendItem("Surf-3D", 10204);
m[1]->AppendItem("Surf-3D-Color", 10205);
m[1]->AppendItem("Image", 10206);

AppendMenu(m[1]);


m[2] = new PIMenu(Menubar(),"Tools");
m[2]->AppendItem("ShowImageTools", 10301);
m[2]->AppendItem("ShowDrawerTools", 10302);
m[2]->AppendItem("ShowAxesTools", 10303);
m[2]->AppendItem("PostScript (EPS)", 10305);
AppendMenu(m[2]);

MainWin()->SetSize(360,130);
zoom = new PIPixmap(MainWin(), "Zoom", 90, 90, 5, 5);
// zoom->SetBinding(PIBK_elastic,PIBK_elastic,PIBK_elastic,PIBK_elastic);
// zoom->SetBinding(PIBK_fixed,PIBK_fixed,PIBK_elastic,PIBK_fixed);
cmapv = new PICMapView(MainWin(), "CMapView", 350, 25, 5, 100);
// cmapv->SetBinding(PIBK_elastic,PIBK_elastic,PIBK_elastic,PIBK_elastic);
cmapv->SetBinding(PIBK_fixed,PIBK_free,PIBK_fixed,PIBK_free);
// Creation d' zone texte multiligne
txt = new PIText(MainWin(), "mltext", 250, 90, 105, 5);
// txt->SetBinding(PIBK_elastic,PIBK_elastic,PIBK_elastic,PIBK_elastic);
txt->SetBinding(PIBK_fixed,PIBK_fixed,PIBK_fixed,PIBK_free);
txt->SetMutiLineMode(true);
txt->SetTextEditable(false);
txt->SetText("");

SetReady();
}

/* --Methode-- */
PITApp::~PITApp()
{
for(int i=0; i<3; i++)  delete m[i]; 
delete txt;
delete cmapv;
delete zoom;
}  


static int nbwin = 0;
static int numpsf = 0;
static int fgswcol = 0;

static double fsinc(double x) {if ( (x>-1.e-8) && (x<1.e-8) ) return(0.); else return (sin(x)/x);}

/* --Methode-- */
void PITApp::Process(PIMessage msg, PIMsgHandler* sender, void* data)
{
char strg[64];
int i,j;

 printf("DBG-PITApp::Process() Msg= %d (%d - %d) Sender=%lx (This=%lx) \n", 
	(int)msg, (int)UserMsg(msg),(int)ModMsg(msg), (long)sender, (long)this);

if ( ( ModMsg(msg) == PIMsg_Active) || (ModMsg(msg) == PIMsg_Close) ) {
  PIWdg *sndw;
  sndw = (PIWdg *)sender;      
  if (sndw->kind() ==  PIWindow::ClassId)  {
    if (ModMsg(msg) == PIMsg_Close)  { 
      printf("PITApp::Process()/Debug : Closing Window %lx \n", (long)sender);
      delete (PIWindow *)sender;  
      mCurW = NULL; }
    else  mCurW = (PIWindow *)sender;
  }
  else if (sender == this) {
    printf(" PIMsg_Close from Application !!! \n");
    return;
  }
}
else
  {
  switch(UserMsg(msg))
    {

// --------- 1er menu ----------
    case 10101:     
      txt->SetText("pitgr: PI Graphics Tests \n * 2-D graphics \n * 3-D Graphics \n Image display ");
      break;

    case 10110 :
      if (mCurW)  { mCurW->Hide();  delete mCurW;}
      mCurW = NULL;
      break;

    case 10150:          // Sortie d'application
      Stop();
      break;


// ----------  3eme menu --------
    case 10301 :
      PIImgTools::ShowPIImgTools();
      break;
    case 10302 :
      PIDrwTools::ShowPIDrwTools();
      break;
    case 10303 :
      PIAxesTools::ShowPIAxesTools();
      break;
    case 10305 :
      if(mCurW) {
        char buff[64];
        sprintf(buff, "pigr_%d.eps", numpsf);        numpsf++;
        printf("Creating EPS File %s (Encapsulated PostScript) \n", buff);
        PSFile *mps;
	mps = new PSFile(buff);
	mCurW->PSPrint(mps,0,0);
	delete mps;
        }
      break;

// ----------  2eme menu --------

    case 10201 :        //  Trace de la fonction sin(x)/x
      {
      SetBusy();    // souris -> montre 
      txt->SetText("PIScDrawWdg Creation\n Sin(x)/x \n Button 1 -> Coord \n  Button 2 Zoom \n <Alt>O <Alt>V \n Try DrawerTools");

      PIFuncDrawer* mfd = new PIFuncDrawer(fsinc);
      mfd->GetGraphicAtt().SetColAtt(PI_Gold);
      mfd->GetGraphicAtt().SetLineAtt(PI_NormalLine);
      nbwin++; sprintf(strg,"2D Graphics (PI W %d)", nbwin);
      PIWindow* wp = new PIWindow(this, strg, PIWK_normal,  300, 300, 150, 150);
      wp->SetAutoDelChilds(true);
      PIScDrawWdg* scd = new PIScDrawWdg(wp, "scwdg-sinc", 300, 300, 0, 0);
      scd->SetBinding(PIBK_fixed,PIBK_fixed,PIBK_fixed, PIBK_fixed);
      scd->SetLimits(0.1, 30., -1., 1.);
      scd->AddScDrawer(mfd,true);
      PIGraphicAtt gatt;
      gatt.SetColAtt(PI_Red);
      scd->BaseDrawer()->ElDrwMgr().ElAddText(2., 0.8, "Y = Sin(x)/x", gatt, 0);
      scd->SetTitles(" --- PIFuncDrawer (Sin(x)/x) --- ", "");
      wp->Show();    // On affiche  la fenetre 
      SetReady();    //  souris->pointeur , on n'est plus occupe
      }
      break;


    case 10202 :    // Trace Test de PIYfXDrawer
      {
      SetBusy();    // souris -> montre 
      txt->SetText("PIScDrawWdg Creation\n PIYfXDrawer \n Button 1 -> Coord \n  Button 2 Zoom \n <Alt>O <Alt>V \n Try DrawerTools");

      float* vpx = new float[30]; 
      float* vpy = new float[30]; 
      int i;   double x;
      for(i=0; i<30; i++) { x = 8.*i/30;  vpx[i] = x;  vpy[i] = 3*cos(x)+2*sin(x); }
      PIYfXDrawer* mxyd = new   PIYfXDrawer( new P1DAdapter<float>(vpx, 30, true), 
                                            new P1DAdapter<float>(vpy, 30, true), true); 
      mxyd->GetGraphicAtt().SetColAtt(PI_Red);
      mxyd->GetGraphicAtt().SetMarkerAtt(7, PI_FTriangleMarker);

      nbwin++; sprintf(strg,"2D Graphics (PI W %d)", nbwin);
      PIWindow* awp = new PIWindow(this, strg, PIWK_normal, 300, 300, 300, 300);
      PIScDrawWdg* scd = new PIScDrawWdg(awp, "scwdg-YfX", 300, 300, 0, 0);
      scd->SetBinding(PIBK_fixed,PIBK_fixed,PIBK_fixed, PIBK_fixed);
      scd->AddScDrawer(mxyd,true);
      scd->SetTitles(" --- PIYfXDrawer (3*cons(x)+2*sin(x)) --- ", "");
      awp->SetAutoDelChilds(true);
      awp->Show();
      SetReady();
      }
      break;

    case 10203 :    // FunDrawer + PIYfXDrawer
      {
      SetBusy();    // souris -> montre 
      txt->SetText("PIScDrawWdg Creation\n PIYfXDrawer + FuncDrawer(Sin(x)/x) \n Button 1 -> Coord \n  Button 2 Zoom \n <Alt>O <Alt>V \n Try DrawerTools");

      float* vpx = new float[30]; 
      float* vpy = new float[30]; 
      int i;   double x;
      for(i=0; i<30; i++) { x = 8.*i/30;  vpx[i] = x;  vpy[i] = 3*cos(x)+2*sin(x); }
      PIYfXDrawer* mxyd = new   PIYfXDrawer( new P1DAdapter<float>(vpx, 30, true), 
                                             new P1DAdapter<float>(vpy, 30, true), true); 

      mxyd->GetGraphicAtt().SetColAtt(PI_Magenta);
      mxyd->GetGraphicAtt().SetMarkerAtt(7, PI_FBoxMarker);

      PIFuncDrawer* mfd = new PIFuncDrawer(fsinc);
      mfd->GetGraphicAtt().SetColAtt(PI_Blue);
      mfd->GetGraphicAtt().SetLineAtt(PI_NormalLine);

      nbwin++; sprintf(strg,"2D Graphics (PI W %d)", nbwin);
      PIWindow* awp = new PIWindow(this, strg, PIWK_normal, 400, 400, 300, 300);
      PIScDrawWdg* scd = new PIScDrawWdg(awp, "scwdg-YfX", 400, 400, 0, 0);
      scd->SetBinding(PIBK_fixed,PIBK_fixed,PIBK_fixed, PIBK_fixed);
      scd->AddScDrawer(mxyd,true);
      scd->AddScDrawer(mfd,true);
      scd->SetTitles(" --- PIYfXDrawer + PIFuncDrawer --- ", "");
      awp->SetAutoDelChilds(true);
      awp->Show();

      SetReady();
      }
      break;

    case 10206 :
      {
      SetBusy();    // souris -> montre 
      txt->SetText("PIImage Creation\n Image Display \n Button 1 -> Coord/value \n  Button 2 Select Rectangle \n Butt on 3 Move \n <Alt>O <Alt>V <Alt>C \n Try ImageTools");
 
      int sx, sy;
      sx = 400; 
      sy = 600;
      printf(" Creating Image (%dx%d) ... ", sx, sy);
      float* img = new float[sx*sy];
      int i, j, k, kk, i0, j0;
      double lamp, amp,x,y;
      for(k=0; k<sx*sy; k++)   img[k] = 1000.+(random()%200-100);
//   On genere 500 etoiles
      for(k=0; k<500; k++) {
        i0 = 20+random()%(sx-20);
        j0 = 20+random()%(sy-20);
        lamp = 2.0+0.012*(random()%100);
        amp = pow(10., lamp);
//        if (k%5 == 0)  printf(" DBG %d %d - %g \n", i0, j0, flux);
        for(i=i0-15; i<i0+15; i++) {
          if(i<0 || i>=sx) continue;
          for(j=j0-15; j<j0+15; j++) {
            if(j<0 || j>=sy) continue;
            x = i-i0;  y = j-j0;
            kk = j*sx+i;
            img[kk] += amp*exp(-(x*x)/7.-(y*y)/8.);
            }
	}
      }
      printf("  >> OK \n");
     
      nbwin++; sprintf(strg,"Image (PI W %d)", nbwin);
      PIWindow* awp = new PIWindow(this, strg, PIWK_normal, sx, sy, 300, 300);
      PIImage * pii = new PIImage(awp, "fitsimage", sx, sy, 0, 0);
      pii->SetBinding(PIBK_fixed, PIBK_fixed, PIBK_fixed, PIBK_fixed);
      pii->SetZoomWin(zoom, false);
      pii->SetCMapWin(cmapv, false);
      pii->ShowCursor(true);
      awp->SetAutoDelChilds(true);
      awp->Show();
      pii->SetImage(new P2DAdapter<float>(img, sx, sy, true), true);
      SetReady();
      }
      break;


//    Dessins 3D  
    case 10204:         
      {
      SetBusy();    // souris -> montre 
      txt->SetText("PIDraw3DWdg Creation\n 3-D Surf Display \n Button 1 \n (Shift) Button 2 Rotate \n Button Zoom \n <Alt>O <Alt>V \n Try DrawerTools");

      printf(" Creating Matrix 80x60  ... ");
      float* tf = new float[60*80];
      int i,j,k;
      double xp,yp,rp;
      for(i=0; i<80; i++)
        for(j=0; j<60; j++) { 
           xp = i-30;   yp = j-20;
           rp = (xp*xp)/16.+(yp*yp)/9.;
           tf[j*80+i] = 10.*exp(-rp);
           xp = i-50;   yp = j-28;
           rp = (xp*xp)/9.+(yp*yp)/9.;
           tf[j*80+i] += 4.*exp(-rp);
        }
      printf("  >> OK \n");

      nbwin++; sprintf(strg,"3D Surf (PI W %d)", nbwin);
      PIWindow* awp = new PIWindow(this, strg, PIWK_normal, 500, 500, 200, 200);
      PISurfaceDrawer* sd = new PISurfaceDrawer(new P2DAdapter<float>(tf, 80, 60, true), true, true, true);
      PIDraw3DWdg* drw3 = new PIDraw3DWdg(awp, "ex3ddrw", 500, 500, 0, 0);
      drw3->SetBinding(PIBK_fixed , PIBK_fixed , PIBK_fixed, PIBK_fixed);
      drw3->AddDrawer3D(sd, false);
      drw3->SetTitles(" --- PISurfaceDrawer (80x60) --- ", "");
      awp->SetAutoDelChilds(true);
      awp->Show();
      SetReady();
      }
      break;

    case 10205:         
      {
      SetBusy();    // souris -> montre 
      txt->SetText("PIDraw3DWdg Creation\n 3-D Surf Display \n Button 1 \n (Shift) Button 2 Rotate \n Button Zoom \n <Alt>O <Alt>V \n Try DrawerTools");

      printf(" Creating Matrix 50x50  ... ");
      float * tf = new float[2500];
      int i,j;
      double xp,yp,rp;
      for(i=0; i<50; i++)
        for(j=0; j<50; j++) { 
           xp = i-15;   yp = j-25;
           rp = (xp*xp)/16.+(yp*yp)/16.;
           tf[j*50+i] = 11.*exp(-rp);
           xp = i-35;   yp = j-15;
           rp = (xp*xp)/9.+(yp*yp)/9.;
           tf[j*50+i] += 3.*exp(-rp);
           xp = i-45;   yp = j-40;
           rp = (xp*xp)/10.+(yp*yp)/20.;
           tf[j*50+i] += 6.*exp(-rp);
        }
      printf("  >> OK \n");

      nbwin++; sprintf(strg,"PI W# %d 3D Surf", nbwin);
      PIWindow* awp = new PIWindow(this, strg, PIWK_normal, 500, 500, 200, 200);
      PISurfaceDrawer* sd = new PISurfaceDrawer(new P2DAdapter<float>(tf, 50, 50, true), true, true, true);
      if (fgswcol%3 == 0) sd->GetGraphicAtt().SetColMapId(CMAP_COLRJ32);
      else if (fgswcol%3 == 1) sd->GetGraphicAtt().SetColMapId(CMAP_COLBR32);
      else sd->GetGraphicAtt().SetColMapId(CMAP_COLRV32);
      fgswcol++;
      PIDraw3DWdg* drw3 = new PIDraw3DWdg(awp, "ex3ddrw", 600, 600, 0, 0);
      drw3->SetBinding(PIBK_fixed , PIBK_fixed , PIBK_fixed, PIBK_fixed);
      drw3->AddDrawer3D(sd, false);
      drw3->SetTitles(" --- PISurfaceDrawer (50x50) --- ", "");
      awp->SetAutoDelChilds(true);
      awp->Show();
      SetReady();
      }
      break;

    default :
      printf("PITApp::Process() Msg= %d (%d - %d)??? \n", 
            (int)msg, (int)UserMsg(msg),(int)ModMsg(msg));
     break;
    }
  }
return;
}


// ................................................................
//                   programme principal 
// ................................................................

int main(int narg, char *arg[])
{

if ( (narg > 1) && (strcmp(arg[1],"-h") == 0) ) {
  printf("pitgr : PI 2D Graphics/ 3D Surface plot/ Image Display Tests  \n");
  printf("  Usage : pitgr [Xt options] \n");
  }


PITApp* app = new PITApp(narg, arg);
int sx,sy,sxmm,symm,resx,resy;
PIApplicationPrefCompSize(sx, sy);
printf("##### pit-main() PrefCompSize= %d %d ##### \n", sx, sy);
PIApplicationScreenSize(sx, sy);
printf("##### pit-main() ScreenSize (pixels) = %d %d ##### \n", sx, sy);
PIApplicationScreenSizeMM(sxmm, symm);
printf("##### pit-main() ScreenSize (mm) = %d %d ##### \n", sxmm, symm);
PIApplicationScreenResolution(resx, resy);
printf("##### pit-main() ScreenResolution (pixel/cm) = %d %d ##### \n", resx, resy);
PIColorMap* cmap = new PIColorMap(CMAP_GREY32);
printf("##### pit-main() NbTotColors=%d Already Allocated= %d ##### \n", 
       cmap->TotNbColors(), cmap->NbAllocColors());
app->Run();

 printf("Apres app->Run(); \n");
delete cmap;
delete app;
exit(0);
}


