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

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

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

#define UNREFERENCED_PARAMETER(P) (P)

PotentiometreHorizontalLogarithmique::PotentiometreHorizontalLogarithmique(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;
  setNombreDigits(2);
}

PotentiometreHorizontalLogarithmique::PotentiometreHorizontalLogarithmique(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->v = v;
  this->d = NULL;
  this->type = 1;
  strcpy(this->titre,titre);
  this->delta = -1.0F;
  setNombreDigits(2);
}

PotentiometreHorizontalLogarithmique::PotentiometreHorizontalLogarithmique(int px,int py,int taille,Couleur *coul,float min,float max,Couleur *coulB,const char *titre,Couleur *coulT,Couleur *coulTB,int *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->v = NULL;
  this->d = v;
  this->type = 2;
  strcpy(this->titre,titre);
  this->delta = -1.0F;
  setNombreDigits(2);
}

PotentiometreHorizontalLogarithmique::PotentiometreHorizontalLogarithmique(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->v = v;
  this->d = NULL;
  this->type = 1;
  strcpy(this->titre,titre);
  this->delta = delta;
  setNombreDigits(2);
}

PotentiometreHorizontalLogarithmique::PotentiometreHorizontalLogarithmique(int px,int py,int taille,Couleur *coul,float min,float max,Couleur *coulB,const char *titre,Couleur *coulT,Couleur *coulTB,int *v,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->v = NULL;
  this->d = v;
  this->type = 2;
  strcpy(this->titre,titre);
  this->delta = delta;
  setNombreDigits(2);
}

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

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

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

void PotentiometreHorizontalLogarithmique::setAdresseVariable(int *val) {
  if ( d )
    d = val;
  dessiner();
}

void PotentiometreHorizontalLogarithmique::setAdresseVariable(float *val) {
  if ( v )
    v = val;
  dessiner();
}

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

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 PotentiometreHorizontalLogarithmique::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.0F,1.7F,1.0F);
    glutSolidSphere(6.0F,18,18);
    glPopMatrix(); }
  { glPushMatrix();
    glTranslatef(taille,0.0F,0.0F);
    glScalef(1.0F,1.7F,1.0F);
    glutSolidSphere(6.0F,18,18);
    glPopMatrix(); }
  { glPushMatrix();
    cylindre(3.0F,taille,18,18);
    glPopMatrix(); }
  if ( delta > 0.0F ) {
    { glPushMatrix();
      glTranslatef(-15.0F,0.0F,0.0F);
      glScalef(1.0F,1.7F,1.0F);
      glutSolidSphere(6.0F,18,18);
      glPopMatrix(); }
    { glPushMatrix();
      glTranslatef(taille+15.0F,0.0F,0.0F);
      glScalef(1.0F,1.7F,1.0F);
      glutSolidSphere(6.0F,18,18);
      glPopMatrix(); } }
  float pos = 0.0F;
  { setGLMaterial(GL_FRONT,GL_DIFFUSE,(float *) coulBouton);
    if ( type == 1 )
      pos = taille*(log((double) *v)-log((double) min))/(log((double) max)-log((double) min));
    if ( type == 2 )
      pos = taille*(log((double) *d)-log((double) min))/(log((double) max)-log((double) min));
    glPushMatrix();
    glTranslatef(pos,0.0F,10.0F);
    glScalef(1.0F,1.7F,1.0F);
    glutSolidSphere(6.0F,18,18);
    glPopMatrix(); }
  glDisable(GL_LIGHTING);
  setGLColor((float *) coulTexte);
  { setFont(GLUT_BITMAP_8_BY_13,CENTER);
    bitmapStringOutput(taille/2,-15.0F,0.0F,titre); }
  { setFont(GLUT_BITMAP_8_BY_13,LEFT);
    if ( type == 1 )
      bitmapStringOutput(taille+14.0F+((delta > 0.0) ? 15.0F:0.0F),3.0F,0.0F,format,max);
    if ( type == 2 )
      bitmapStringOutput(taille+14.0F+((delta > 0.0) ? 15.0F:0.0F),3.0F,0.0F,"%d",(int) max); }
  { setFont(GLUT_BITMAP_8_BY_13,RIGHT);
    if ( type == 1 )
      bitmapStringOutput(-14.0F-((delta > 0.0) ? 15.0F:0.0F),3.0F,0.0F,format,min);
    if ( type == 2 )
      bitmapStringOutput(-14.0F-((delta > 0.0) ? 15.0F:0.0F),3.0F,0.0F,"%d",(int) min); }
  if ( delta > 0.0F ) {
    Couleur *c = new Couleur();
    setGLColor(Couleur::jaune->r,Couleur::jaune->v,Couleur::jaune->b,Couleur::jaune->a);
    setFont(GLUT_BITMAP_8_BY_13,CENTER);
    bitmapStringOutput(-15.0F,4.0F,0.0F,"-");
    bitmapStringOutput(taille+16.0F,4.0F,0.0F,"+");
    delete(c); }
  setGLColor((float *) coulTexteBouton);
  { setFont(GLUT_BITMAP_8_BY_13,CENTER);
    if ( type == 1 )
      bitmapStringOutput(pos,24.0F,0.0F,format,*v);
    if ( type == 2 )
      bitmapStringOutput(pos,24.0F,0.0F,"%d",*d); }
  glPopMatrix();
}

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

void PotentiometreHorizontalLogarithmique::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)*1.7F;
  float dy = (y - yy);
  return(dx*dx+dy*dy);
}

int PotentiometreHorizontalLogarithmique::selection(int x,int y) {
  if ( enabled ) {
    float pos = 0.0F;
    if ( type == 1 )
      pos = px+taille*(log((double) *v)-log((double) min))/(log((double) max)-log((double) min));
    if ( type == 2 )
      pos = px+taille*(log((double) *d)-log((double) min))/(log((double) max)-log((double) min));
    if ( carreDistance(x,y,pos,py) < 100 )
      return(1);
    if ( carreDistance(x,y,px-15.0F,py) < 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+taille+15.0F,py) < 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 PotentiometreHorizontalLogarithmique::gereModification(int x,int y,int dx,int dy) {
  UNREFERENCED_PARAMETER(y);
  UNREFERENCED_PARAMETER(dx);
  UNREFERENCED_PARAMETER(dy);
  float r =(float) (x-px)/taille;
  if ( r < 0.0F )
    r = 0.0F;
  if ( r > 1.0F )
    r = 1.0F;
  r *= (log(max)-log(min));
  r += log(min);
  r = exp(r);
  if ( type == 1 ) {
    *v = r; }
  if ( type == 2 ) {
    *d =(int) r; }
  return(1);
}

void PotentiometreHorizontalLogarithmique::setNombreDigits(int n) {
  digits = n;
  sprintf(format,"%c%d.%df",'%',digits+3,digits);
}

void PotentiometreHorizontalLogarithmique::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); }
}
