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

#include <GL/gl.h>
#include <GL/glu.h>
#include <GL/glut.h>

#include "Controle.h"
#include "PotentiometreVertical.h"
#include "Couleur.h"
#include "ModuleFont.h"

#define UNREFERENCED_PARAMETER(P) (P)

PotentiometreVertical::PotentiometreVertical(void):Controle() {
  coulTexte = new Couleur();
  coulBouton = new Couleur();
  coulTexteBouton = new Couleur();
  taille = 0;
  min = 0.0F;
  max = 0.0F;
  v = NULL;
  d = NULL;
  type = 0;
  strcpy(titre,"");
  delta = -1.0F;
  aff = 0;
}

PotentiometreVertical::PotentiometreVertical(int px,int py,int taille,Couleur *coul,float min,float max,Couleur *coulB,const char *titre,Couleur *coulT,Couleur *coulTB,float *v):Controle(px,py,coul) {
  this->coulTexte = new Couleur(coulT);
  this->coulBouton = new Couleur(coulB);
  this->coulTexteBouton = new Couleur(coulTB);
  this->taille = taille;
  this->min = min;
  this->max = max;
  this->type = 1;
  this->v = v;
  this->d = NULL;
  strcpy(this->titre,titre);
  this->delta = -1.0F;
}

PotentiometreVertical::PotentiometreVertical(int px,int py,int taille,Couleur *coul,float min,float max,Couleur *coulB,const char *titre,Couleur *coulT,Couleur *coulTB,int *d):Controle(px,py,coul) {
  this->coulTexte = new Couleur(coulT);
  this->coulBouton = new Couleur(coulB);
  this->coulTexteBouton = new Couleur(coulTB);
  this->taille = taille;
  this->min = min;
  this->max = max;
  this->type = 2;
  this->v = NULL;
  this->d = d;
  strcpy(this->titre,titre);
  this->delta = -1.0F;
}

PotentiometreVertical::PotentiometreVertical(int px,int py,int taille,Couleur *coul,float min,float max,Couleur *coulB,const char *titre,Couleur *coulT,Couleur *coulTB,float *v,float delta):Controle(px,py,coul) {
  this->coulTexte = new Couleur(coulT);
  this->coulBouton = new Couleur(coulB);
  this->coulTexteBouton = new Couleur(coulTB);
  this->taille = taille;
  this->min = min;
  this->max = max;
  this->type = 1;
  this->v = v;
  this->d = NULL;
  strcpy(this->titre,titre);
  this->delta = delta;
}

PotentiometreVertical::PotentiometreVertical(int px,int py,int taille,Couleur *coul,float min,float max,Couleur *coulB,const char *titre,Couleur *coulT,Couleur *coulTB,int *d,int delta):Controle(px,py,coul) {
  this->coulTexte = new Couleur(coulT);
  this->coulBouton = new Couleur(coulB);
  this->coulTexteBouton = new Couleur(coulTB);
  this->taille = taille;
  this->min = min;
  this->max = max;
  this->type = 2;
  this->v = NULL;
  this->d = d;
  strcpy(this->titre,titre);
  this->delta = delta;
}

PotentiometreVertical::PotentiometreVertical(int px,int py,int taille,Couleur *coul,float min,float max,Couleur *coulB,const char *titre,Couleur *coulT,Couleur *coulTB,int aff,float *v):Controle(px,py,coul) {
  this->coulTexte = new Couleur(coulT);
  this->coulBouton = new Couleur(coulB);
  this->coulTexteBouton = new Couleur(coulTB);
  this->taille = taille;
  this->min = min;
  this->max = max;
  this->type = 1;
  this->v = v;
  this->d = NULL;
  strcpy(this->titre,titre);
  this->delta = -1.0F;
  this->aff = aff;
}

PotentiometreVertical::PotentiometreVertical(int px,int py,int taille,Couleur *coul,float min,float max,Couleur *coulB,const char *titre,Couleur *coulT,Couleur *coulTB,int aff,int *d):Controle(px,py,coul) {
  this->coulTexte = new Couleur(coulT);
  this->coulBouton = new Couleur(coulB);
  this->coulTexteBouton = new Couleur(coulTB);
  this->taille = taille;
  this->min = min;
  this->max = max;
  this->type = 2;
  this->v = NULL;
  this->d = d;
  strcpy(this->titre,titre);
  this->delta = -1.0F;
  this->aff = aff;
}

PotentiometreVertical::PotentiometreVertical(int px,int py,int taille,Couleur *coul,float min,float max,Couleur *coulB,const char *titre,Couleur *coulT,Couleur *coulTB,int aff,float *v,float delta):Controle(px,py,coul) {
  this->coulTexte = new Couleur(coulT);
  this->coulBouton = new Couleur(coulB);
  this->coulTexteBouton = new Couleur(coulTB);
  this->taille = taille;
  this->min = min;
  this->max = max;
  this->type = 1;
  this->v = v;
  this->d = NULL;
  strcpy(this->titre,titre);
  this->delta = delta;
  this->aff = aff;
}

PotentiometreVertical::PotentiometreVertical(int px,int py,int taille,Couleur *coul,float min,float max,Couleur *coulB,const char *titre,Couleur *coulT,Couleur *coulTB,int aff,int *d,int delta):Controle(px,py,coul) {
  this->coulTexte = new Couleur(coulT);
  this->coulBouton = new Couleur(coulB);
  this->coulTexteBouton = new Couleur(coulTB);
  this->taille = taille;
  this->min = min;
  this->max = max;
  this->type = 2;
  this->v = NULL;
  this->d = d;
  strcpy(this->titre,titre);
  this->delta = delta;
  this->aff = aff;
}

PotentiometreVertical::~PotentiometreVertical(void) {
  delete(this->coulTexte);
  delete(this->coulBouton);
  delete(this->coulTexteBouton);
}

void PotentiometreVertical::setValue(int val) {
  if ( v )
    *v = val;
  if ( d )
    *d = val;
  dessiner();
}

void PotentiometreVertical::setValue(float val) {
  if ( v )
    *v = val;
  if ( d )
    *d =(int) val;
  dessiner();
}

int PotentiometreVertical::getPositionAscenceur(void) {
  float pos = 0.0F;
  if ( type == 1 )
    pos = taille*(*v-max)/(min-max);
  if ( type == 2 )
    pos = taille*(*d-max)/(min-max);
  return((int) pos);
}

void PotentiometreVertical::setAdresseVariable(float *addr) {
  if ( v )
    v = addr;
  dessiner();
}

void PotentiometreVertical::setAdresseVariable(int *addr) {
  if ( d )
    d = addr;
  dessiner();
}
    
static void cylindre(float r,float h,int np1,int np2) {
  glPushMatrix();
  glRotatef(90.0F,0.0F,1.0F,0.0F);
  GLUquadricObj *qobj = gluNewQuadric();
  gluQuadricDrawStyle(qobj,GLU_FILL);
  gluCylinder(qobj,r,r,h,np1,np2);
  gluDeleteQuadric(qobj);  
  glPopMatrix();
}

void affichage(int type,float f,int i,float x,float y,float z) {
  if ( type == 1 )
    bitmapStringOutput(x,y,z,"%5.2f",f);
  if ( type == 2 )
	  bitmapStringOutput(x,y,z,"%d",i); 
}

void PotentiometreVertical::dessiner(void) {
  if ( !enabled )
    actif = 0;
  glEnable(GL_LIGHTING);
  glPushMatrix();
  glTranslatef(px,py,0.0F);
  setGLMaterial(GL_FRONT,GL_DIFFUSE,(float *) coul);
  { glPushMatrix();
    glScalef(1.7F,1.0F,1.0F);
    glutSolidSphere(6.0F,18,18);
    glPopMatrix(); }
  { glPushMatrix();
    glTranslatef(0.0F,taille,0.0F);
    glScalef(1.7F,1.0F,1.0F);
    glutSolidSphere(6.0F,18,18);
    glPopMatrix(); }
  { glPushMatrix();
    glRotatef(90.0F,0.0F,0.0F,1.0F);
    cylindre(3.0F,taille,18,18);
    glPopMatrix(); }
  if ( delta > 0.0F ) {
    { glPushMatrix();
      glTranslatef(0.0F,-15.0F,0.0F);
      glScalef(1.7F,1.0F,1.0F);
      glutSolidSphere(6.0F,18,18);
      glPopMatrix(); }
    { glPushMatrix();
      glTranslatef(0.0F,taille+15.0F,0.0F);
      glScalef(1.7F,1.0F,1.0F);
      glutSolidSphere(6.0F,18,18);
      glPopMatrix(); } }
  float pos = 0;
  { setGLMaterial(GL_FRONT,GL_DIFFUSE,(float *) coulBouton);
    if ( type == 1 )
      pos = taille*(*v-max)/(min-max);
    if ( type == 2 )
      pos = taille*(*d-max)/(min-max);
    glPushMatrix();
    glTranslatef(0.0F,pos,10.0F);
    glScalef(1.7F,1.0F,1.0F);
    glutSolidSphere(6.0F,18,18);
    glPopMatrix(); }
  glDisable(GL_LIGHTING);
  setGLColor((float *) coulTexte);
  { setFont(GLUT_BITMAP_8_BY_13,CENTER);
    bitmapStringOutput(0.0,-20.0F+((delta > 0.0) ? -10.0F:0.0F),0.0F,titre); }
  if ( ( aff == 1 ) || ( aff == 0 ) ) { 
    setFont(GLUT_BITMAP_8_BY_13,LEFT);
    affichage(type,max,(int) max,10.0F,4.0F,0.0F); }
    else { 
    setFont(GLUT_BITMAP_8_BY_13,RIGHT);
    affichage(type,max,(int) max,-10.0F,4.0F,0.0F); }
  if ( ( aff == 1 ) || ( aff == 0 ) ) { 
    setFont(GLUT_BITMAP_8_BY_13,LEFT);
    affichage(type,min,(int) min,10.0F,4.0F+taille,0.0F); }
    else { 
    setFont(GLUT_BITMAP_8_BY_13,RIGHT);
    affichage(type,min,(int) min,-10.0F,4.0F+taille,0.0F); }
  if ( delta > 0.0F ) {
    Couleur *c = new Couleur();
    setGLColor((float *) Couleur::jaune);
    setFont(GLUT_BITMAP_8_BY_13,CENTER);
    bitmapStringOutput(1.0F,-11.0F,0.0F,"+");
    bitmapStringOutput(0.0F,taille+19.0F,0.0F,"-");
    delete(c); }
  setGLColor((float *) coulTexteBouton);
  if ( ( aff == 2 ) || ( aff == 0 ) ) { 
    setFont(GLUT_BITMAP_8_BY_13,RIGHT);
    affichage(type,(v) ? *v : 0.0F,(d) ? *d : 0,-10.0F,4.0F+pos,0.0F); }
    else {
    setFont(GLUT_BITMAP_8_BY_13,LEFT);
    affichage(type,(v) ? *v : 0.0F,(d) ? *d : 0,10.0F,4.0F+pos,0.0F); }
  glPopMatrix();
}

void PotentiometreVertical::sauve(void) {
  if ( d )
    saved = *d;
  if ( v )
    savev = *v;
}

void PotentiometreVertical::annule(void) {
  if ( v )
    *v = savev;
  if ( d )
    *d = saved;
}

static float carreDistance(float x,float y,float xx,float yy) {
  float dx = (x - xx);
  float dy = (y - yy)*1.7F;
  return(dx*dx+dy*dy);
}

int PotentiometreVertical::selection(int x,int y) {
  if ( enabled ) {
    float pos = 0.0F;
    if ( type == 1 )
      pos = py+(taille*(*v-max))/(min-max);
    if ( type == 2 )
      pos = py+((float) taille*(*d-max))/(min-max);
    if ( carreDistance(x,y,px,pos) < 100 )
      return(1);
    if ( carreDistance(x,y,px,py+taille+15.0F) < 100 ) {
      if ( type == 1 ) {
        *v -= delta;
        if ( *v < min )
          *v = min; }
      if ( type == 2 ) {
        *d -=(int) delta;
        if ( *d < min )
          *d =(int) min; }
      return(2); }
    if ( carreDistance(x,y,px,py-15.0F) < 100 ) {
      if ( type == 1 ) {
        *v += delta;
        if ( *v > max )
          *v = max; }
      if ( type == 2 ) {
        *d +=(int) delta;
        if ( *d > max )
          *d =(int) max; }
      return(2); } }
  return(-1);
}

int PotentiometreVertical::gereModification(int x,int y,int dx,int dy) {
  UNREFERENCED_PARAMETER(x);
  UNREFERENCED_PARAMETER(y);
  UNREFERENCED_PARAMETER(dx);
  if ( type == 1 ) {
    *v += (dy*(min-max)/taille);
    if ( *v < min )
      *v = min;
    if ( *v > max )
      *v = max; }
  if ( type == 2 ) {
    *d += ((int) ((dy*(min-max))/taille));
    if ( *d < min )
      *d =(int) min;
    if ( *d > max )
      *d =(int) max; }
  return(1);
}

void PotentiometreVertical::sauve(FILE *f) {
  if ( strcmp(name,"") ) {
    if ( v )
      fprintf(f,"  <%s valeur=\"%f\"></%s>\n",name,*v,name);
      else
      fprintf(f,"  <%s valeur=\"%d\"></%s>\n",name,*d,name); }
}
