#ifndef SPRING1_H
#define SPRING1_H

#include <cassert>
#include <cmath>
using namespace std;

#include <GL/glut.h>

#include <graphmisc.h>
#include <nintegration.h>
#include <spring.h>
#include <typedefs.h>


/*!
\brief One spring, integrates graphics and de solver.
*/
class fspring1
{
public:

  double kval;
  double * x;

  void operator () 
  (
    double &  ddx, 
    doublec & dx, 
    doublec & t 
  ) const
  {
    ddx = -kval*(*x);
  }

};

class fcubicspring1
{
public:

  double kval;
  double * x;

  /** Forcing term parameters. */
  double A;
  double omega;

  fcubicspring1()
    : A(7.5), omega(1.0) {}

  void operator () 
  (
    double &  ddx, 
    doublec & dx, 
    doublec & t 
  ) const
  {
    double xtmp(*x);
    ddx = A*cos(omega*t)-xtmp*xtmp*xtmp-kval*dx;
  }

};




template< typename F >
class spring1
{
public:

  DEsys< double, 2, 1 > de;
  RK< double, F > fi;

  gspring spr;

  bool drawenabled;

  uint sample;

  double lennatural;

  spring1() {}

  void init
  (
    uintc sample_,
    doublec h,
    doublec t0,
    doublec x00,
    doublec x10,
    doublec kval=0.1,
    doublec len=1.0,
    doublec radius=0.2
  );

  void idle();

  void draw();

};



// ------------------------------------------------------------ 
// Implementation


template< typename F >
void spring1<F>::draw()
{
  if (drawenabled)
  {
    glPushMatrix();

    spr.draw();
    
    glPopMatrix();
  }
}

template< typename F >
void spring1<F>::idle()
{
  de();

  static uint counter;

  ++counter;
  if ((counter % sample)==0)
  {
    spr.h.len = lennatural+de.y[0][0];

    glutPostRedisplay();
    counter=0;
  }
}


template< typename F >
void spring1<F>::init
(
  uintc sample_,
  doublec h,
  doublec t0,
  doublec x00,
  doublec x10,
  doublec kval,
  doublec len,
  doublec radius
)
{
  de.h[0]=h;

  de.xval = t0;
  de.yi[0] = x00;
  de.yi[1] = x10;

  fi.Dy.kval = kval;
  fi.Dy.x = & (de.y[0][0]);

  de.fi[0] = & fi;

  lennatural = len;

  spr = gspring
  ( 
    helix(len+x00,10,0.2,200, 0.2,0.8,0.17),
    mysphere
    (
      radius, 
      0.1,0.6,0.77,
      0.0,0.0,0.0
    )
  );

  sample=sample_;

  drawenabled=true;
}



#endif


