#include "sopnamsp.h"
#include "machdefs.h"
#include <stdio.h>
#include <stdlib.h>
#include <iostream>
#include <math.h>

#include <typeinfo>

#include <vector>
#include <string>

#include "piacmd.h"
#include "nobjmgr.h"
#include "pistdimgapp.h"


//  Module chargeable ds piapp - Commande de gestion de sortie PS

//  Declaration de la fonction d'activation et de desactivation du module
extern "C" {
void W2PSModule_init();
void W2PSModule_end();
}


//  Une classe commande-executor, permettant d'enregistrer de 
//  nouvelles commandes a piapp
class W2PSModuleExecutor : public CmdExecutor {
public:
                W2PSModuleExecutor();
  virtual       ~W2PSModuleExecutor();
  // Execute s'occupe de l'execution effective des commandes
  virtual int   Execute(string& keyw, vector<string>& args, string& toks);
protected:
  string psfilename;
  PSFile * mpsfile;
};

/* --Methode-- */
W2PSModuleExecutor::W2PSModuleExecutor()
{

psfilename = "w2ps.ps";
mpsfile = NULL;

PIACmd * mpiac;
NamedObjMgr omg;
mpiac = omg.GetImgApp()->CmdInterpreter();

// On enregistre deux nouvelles commandes 
string hgrp = "GraphicExport";
// commande w2pssetfilename
string kw = "pssetfilename";
string usage = "pssetfilename: Sets current PostScript file name\n" ;
usage += "Usage: pssetfilename FileName ";
mpiac->RegisterCommand(kw, usage, this, hgrp);
// commande w2psgetfilename
kw = "psgetfilename";
usage = "psgetfilename: Prints current PostScript file name \n" ;
usage += "Usage: psgetfilename ";
mpiac->RegisterCommand(kw, usage, this, hgrp);
// commande w2psclosefile
kw = "psclosefile";
usage = "psclosefile: close current postscript file \n" ;
usage += "Usage: w2psclosefile ";
mpiac->RegisterCommand(kw, usage, this, hgrp);
// commande w2ps
kw = "w2ps";
usage = "w2ps: Current Window To PostScript \n" ;
usage += "Usage: w2ps ";
mpiac->RegisterCommand(kw, usage, this, hgrp);
// commande w2eps
kw = "w2eps";
usage = "w2eps: Current Window To EncapsulatedPostScript \n" ;
usage += "Usage: w2eps EPSFileName";
mpiac->RegisterCommand(kw, usage, this, hgrp);
// commande imagcmap2eps
kw = "imagcmap2ps";
usage = "w2ps: Current Image+ColorMap To PostScript \n" ;
usage += "Usage: imagcmap2ps ";
mpiac->RegisterCommand(kw, usage, this, hgrp);
// commande imagcmap2eps
kw = "imagcmap2eps";
usage = "imagcmap2eps: Current Image+ColorMap To EncapsulatedPostScript \n" ;
usage += "Usage: imagcmap2eps EPSFileName";
mpiac->RegisterCommand(kw, usage, this, hgrp);
}

/* --Methode-- */
W2PSModuleExecutor::~W2PSModuleExecutor()
{
  if(mpsfile) delete mpsfile;
}

/* --Methode-- */
int W2PSModuleExecutor::Execute(string& kw, vector<string>& tokens, string&)
{

NamedObjMgr omg;
if (kw == "pssetfilename") {
  if (tokens.size() < 1) {
    cout << "Usage: pssetfilename PSFileName" << endl;
    return(0);
    }
  if (mpsfile) delete mpsfile;
  mpsfile = NULL;
  psfilename = tokens[0];
}
else if (kw == "psgetfilename") {
  cout << " W2PS: PSFileName= " << psfilename << endl;
}
else if (kw == "psclosefile") {
  if (mpsfile) { 
    cout << "psclosefile: Closing file " << psfilename << endl; 
    delete mpsfile;
    mpsfile = NULL;
    psfilename = "w2ps.ps";
  }
}
else if ( (kw == "w2ps") || (kw == "w2eps") ) {
  PIStdImgApp*  sapp = omg.GetImgApp();
  if (sapp == NULL) {
    cout << " W2PSModuleExecutor::Execute() No PIStdImgApp !" << endl;
    return(0);
  }
  sapp->CkEvt_LockMutex();
  if (sapp->CurrentWindow() == NULL) {
    sapp->UnlockMutex(); 
    cout << " W2PSModuleExecutor::Execute() No current window !" << endl;
    return(0);
  }
  if (kw == "w2ps") {
    if (mpsfile == NULL) 
      mpsfile = new PSFile(psfilename.c_str(), PI_Portrait, PI_A4, 2., 2.);
    sapp->CurrentWindow()->PSPrint(mpsfile,0,0);
    cout << " w2ps: Current window to PS file " << psfilename << endl;
  }
  else if (kw == "w2eps") {
    if (tokens.size() < 1) {
      sapp->UnlockMutex();
      cout << "Usage: w2eps EPSFileName" << endl;
      return(0);
    }
    PSFile epsfile(tokens[0].c_str());
    sapp->CurrentWindow()->PSPrint(&epsfile,0,0);
    cout << " w2eps: Current window to EPS file " << tokens[0] << endl;
  }
  sapp->UnlockMutex();
}
else if ( (kw == "imagcmap2ps") || (kw == "imagcmap2eps") ) {
  PIStdImgApp*  sapp = omg.GetImgApp();
  if (sapp == NULL) {
    cout << " W2PSModuleExecutor::Execute() No PIStdImgApp !" << endl;
    return(0);
  }
  PIImage* curpimg = NULL;
  sapp->CkEvt_LockMutex();
  if (sapp->CurrentBaseWdg()) 
    curpimg = dynamic_cast<PIImage *>(sapp->CurrentBaseWdg());
  if (curpimg == NULL) {
    sapp->UnlockMutex();
    cout << " W2PSModuleExecutor::Execute() No current PIImage !" << endl;
    return(0);
  }
  PSFile * cpsf = NULL;
  PSFile * cepsf = NULL;
  if (kw == "imagcmap2ps") {
    if (mpsfile == NULL) 
      mpsfile = new PSFile(psfilename.c_str(), PI_Portrait, PI_A4, 2., 2.);
    cpsf = mpsfile;
    cout << " imagcmap2ps: Current image+colormap to PS file " << psfilename << endl;
  }
  else if (kw == "imagcmap2eps") {
    if (tokens.size() < 1) {
      sapp->UnlockMutex();
      cout << "Usage: imagcmap2eps EPSFileName" << endl;
      return(0);
    }
    cepsf = new PSFile(tokens[0].c_str());
    cpsf = cepsf;
    cout << " imagcmap2eps: Current image+colormap to EPS file " << tokens[0] << endl;
  }
  double sx, sy;
  sx = curpimg->XSize();
  sy = curpimg->YSize() + sapp->CMapVW()->YSize() + 10;
  cpsf->NewPage(sx, sy, PI_Auto);
  curpimg->PSPrint(cpsf, -curpimg->XPos(), -curpimg->YPos());
  sapp->CMapVW()->PSPrint(cpsf, -(sapp->CMapVW()->XPos()), 			
			  -(sapp->CMapVW()->YPos())+curpimg->YSize()+10,
			  sx/(double)sapp->CMapVW()->XSize(), 1.);

  sapp->UnlockMutex();
  if (cepsf) delete cepsf;
}

return(0);

}

static W2PSModuleExecutor * piaw2psex = NULL;
/* Nouvelle-Fonction */
void W2PSModule_init()
{
// Fonction d'initialisation du module
// Appele par le gestionnaire de modules de piapp (PIACmd::LoadModule())
if (piaw2psex) delete piaw2psex;
piaw2psex = new W2PSModuleExecutor;
}

/* Nouvelle-Fonction */
void W2PSModule_end()
{
// Desactivation du module
if (piaw2psex) delete piaw2psex;
piaw2psex = NULL;
}

