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


#include <vector>
#include <string>

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


//  Exemple de module chargeable ds piapp 

// Classe Drawer de Test 
class TstSpeedDrw : public PIDrawer {
public:
                     TstSpeedDrw(int npt, int nblk);
  virtual           ~TstSpeedDrw();
  
  virtual void       Draw(PIGraphicUC* g, double xmin, double ymin, double xmax, double ymax);
  virtual void       UpdateLimits();
  
       
protected:
  int _npt, _nblk;
  double * _mesx;
  double * _mesy;
};

/* --Methode-- */
TstSpeedDrw::TstSpeedDrw(int npt, int nblk)
    : PIDrawer()
{
  if (nblk > 1) {
    int q = npt / nblk;  npt = q*nblk; 
  }
  _npt = npt; _nblk = nblk;
  _mesx = new double[npt];
  _mesy = new double[npt];
  double dx = 3./npt;
  for(int i=0; i<npt; i++) {
    double x =  i*dx;
    _mesx[i] = x;
    _mesy[i] = x*x + 3*drandpm1();
  }
  mName = "TstSpeedDrw";
  cout << " TstSpeedDrw::TstSpeedDrw(" << npt << "," << nblk << ")" << endl;
} 

/* --Methode-- */
TstSpeedDrw::~TstSpeedDrw()
{
  delete[] _mesx;
  delete[] _mesy;
}

/* --Methode-- */
void TstSpeedDrw::UpdateLimits()
{
  double xmin = -0.1 ; 
  double xmax = 3.1;
  double ymin = -2.;
  double ymax = 11.;
  PIAxes::ReSizeMinMax(isLogScaleX(),xmin,xmax);
  PIAxes::ReSizeMinMax(isLogScaleY(),ymin,ymax);
  SetLimits(xmin,xmax,ymin,ymax);
  SetAxesFlags(kBoxAxes | kExtTicks | kLabels);
}


/* --Methode-- */
void TstSpeedDrw::Draw(PIGraphicUC* g, double xmin, double ymin, double xmax, double ymax)
{
  /*
  PIMarker mrk = GetGraphicAtt().GetMarker();
  mrk = (mrk != PI_NotDefMarker) ? mrk : PI_DotMarker;
  int msz = GetGraphicAtt().GetMarkerSz(); 
  if (msz < 1) msz = 1;
  g->SelMarker(msz, mrk);
  */
   PrtTim("TstSpeedDrw::Draw() START");
  if (_nblk < 2) {
    for(int i=0; i<_npt; i++) 
      g->DrawMarker(_mesx[i], _mesy[i]);      
    PrtTim("TstSpeedDrw::Draw() Blk=1 done");
  }
  else {
    int q = _npt/_nblk;
    PIGrCoord* grx = new PIGrCoord[_nblk];
    PIGrCoord* gry = new PIGrCoord[_nblk];
    for(int k=0; k<q; k++) {
      int off = k*_nblk;
      for(int j=0; j<_nblk; j++) {
	grx[j] = _mesx[off+j];
 	gry[j] = _mesy[off+j];
      }
      g->DrawMarkers(grx, gry, _nblk);
    }
    PrtTim("TstSpeedDrw::Draw() Blk>1 done");    
  }
}


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


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

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

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

// On enregistre deux nouvelles commandes 
string hgrp = "ExModDrw";
// commande excmd1
string kw = "tspeeddrw";
string usage = "tspeeddrw npt nblk gr_opt \n" ;
mpiac->RegisterCommand(kw, usage, this, hgrp);
}

/* --Methode-- */
exmoddrwExecutor::~exmoddrwExecutor()
{
}

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

NamedObjMgr omg;
if (kw == "tspeeddrw") {
  if (tokens.size() < 2) {
    cout << "Usage: tspeeddrw npt nblk gr_opt" << endl;
    return(0);
    }
  int npt = atoi(tokens[0].c_str());
  int nblk = atoi(tokens[1].c_str());
  string opt = "";
  if (tokens.size() > 2) opt = tokens[2];
  TstSpeedDrw* drw = new TstSpeedDrw(npt, nblk);
  string name = "TstSpeedDrw";
  omg.GetImgApp()->DispScDrawer(drw, name, opt); 
  }

return(0);

}

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

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

