import ddf.minim.*;
class MainMenuState extends State
{
  //Minim minim;
  //AudioInput in;
  boolean createdWave = false;
  int currentGestureID;
  int nGestures = 1;
  Gesture[] gestureArray;
  PShader nebula;

  PImage bg_img;
  PFont font;
  int direction = 0;
  float posY;
  void setup()
  {
    b.setVisible(true);
    //----------------------------------Microphone------------------
    //minim = new Minim(this);
    //in = minim.getLineIn();
    //--------------------------------Shader------------------------------
    currentGestureID = -1;
    bg_img = loadImage("hubble.jpg");
    bg_img.resize(width, height);
    nebula = loadShader("nebula.glsl");
    nebula.set("resolution", float(width), float(height));
    font = loadFont("SpaceFrigate-48.vlw");
    //---------------------------------------WaveVars------------------------------
    direction = 0;
    createdWave = false;
    posY = height*1/4+ 10 + 15.0f*((float)(nGestures)/10);
    currentGestureID = -1;
    gestureArray = new Gesture[nGestures];
    for (int i = 0; i < nGestures; i++) {
      gestureArray[i] = new Gesture(width, height);
    }
    clearGestures();
  }
  void draw()
  {

    background(0);
    nebula.set("time", millis() / 500.0);  
    shader(nebula); 
    rect(0, 0, width, height);
    
    resetShader();
    
    for (int i = 0; i < in.bufferSize()*3/4 - 1; i++)
    {
      if ((in.left.get(i)*50 >1.2 || in.left.get(i)*50 < -1.2))
      {
        createdWave = true;      
        currentGestureID = (currentGestureID+1) % nGestures;
        createGeometry();
      }
      if (createdWave)
      {
        break;
      }
    }
    
    updateGeometry();
    fill(255, 255, 245);
    for (int i = 0; i < nGestures; i++) 
    {
      renderGesture(gestureArray[i], width, height);
    }
    //------------------------------------------------------Text and GUI------------------------------------------
    textFont(font, 90);
    fill(255);
    textAlign(CENTER);
    text("PRANAWAVE", width/2, height*1/4);
  }
  //-------------------------------------------------WAVES--------------------------------------------
  void createGeometry()
  {
    Gesture G = new Gesture(width, height);
    G.clear();
    G.clearPolys();
    G.jumpInScreen = posY*currentGestureID;
    direction = 1 - direction;

    G.waveDirection = direction;
    println(direction);
    for (int i = 0; i < in.bufferSize() - 1; i++)
    {
      //G.addPoint(i + (width*2/8) * 250, G.jumpInScreen + in.left.get(i)*450);
      G.addPoint(i +width/2 * 350, height/2 + in.left.get(i)*650);
    }
    if (!existsAlready(G))
    {
      gestureArray[currentGestureID] = G;
    }
  }

  boolean existsAlready(Gesture newElement )
  {

    for (int i = 0; i < gestureArray.length-1; i++)
    {
      for (int j = 0; j < gestureArray[i].path.length -1; j++)
      {

        if (newElement.path[j].y - newElement.jumpInScreen == gestureArray[i].path[j].y - gestureArray[i].jumpInScreen)
        {
          return true;
        }
      }
    }
    return false;
  }

  void renderGesture(Gesture gesture, int w, int h) {
    if (gesture.exists) {
      if (gesture.nPolys > 0) {
        Polygon polygons[] = gesture.polygons;
        int crosses[] = gesture.crosses;

        int xpts[];
        int ypts[];
        Polygon p;
        int cr;

        beginShape(QUADS);
        int gnp = gesture.nPolys;
        for (int i=0; i<gnp; i++) {

          p = polygons[i];
          xpts = p.xpoints;
          ypts = p.ypoints;

          vertex(xpts[0], ypts[0]);
          vertex(xpts[1], ypts[1]);
          vertex(xpts[2], ypts[2]);
          vertex(xpts[3], ypts[3]);

          if ((cr = crosses[i]) > 0) {
            if ((cr & 3)>0) {
              vertex(xpts[0]+w, ypts[0]);
              vertex(xpts[1]+w, ypts[1]);
              vertex(xpts[2]+w, ypts[2]);
              vertex(xpts[3]+w, ypts[3]);

              vertex(xpts[0]-w, ypts[0]);
              vertex(xpts[1]-w, ypts[1]);
              vertex(xpts[2]-w, ypts[2]);
              vertex(xpts[3]-w, ypts[3]);
            }
            if ((cr & 12)>0) {
              vertex(xpts[0], ypts[0]+h);
              vertex(xpts[1], ypts[1]+h);
              vertex(xpts[2], ypts[2]+h);
              vertex(xpts[3], ypts[3]+h);

              vertex(xpts[0], ypts[0]-h);
              vertex(xpts[1], ypts[1]-h);
              vertex(xpts[2], ypts[2]-h);
              vertex(xpts[3], ypts[3]-h);
            }

            // I have knowingly retained the small flaw of not
            // completely dealing with the corner conditions
            // (the case in which both of the above are true).
          }
        }
        endShape();
      }
    }
  }

  void updateGeometry() {
    Gesture J;
    for (int g=0; g<nGestures; g++) {
      if ((J=gestureArray[g]).exists) {
        advanceGesture(J);
      }
    }
  }

  void advanceGesture(Gesture gesture) 
  {
    // Move a Gesture one step
    if (gesture.exists) 
    { // check
      int nPts = gesture.nPoints;
      int nPts1 = nPts-1;
      Vec3f path[];
      float jx = gesture.jumpDx;
      float jy = gesture.jumpDy;
      if (gesture.waveDirection == 0)
      {
        if (nPts > 0) 
        {
          path = gesture.path;
          for (int i = nPts1; i > 0; i--) 
          {
            path[i].x = path[i-1].x;
            path[i].y = path[i-1].y;
          }
          path[0].x = path[nPts1].x - jx;
          path[0].y = path[nPts1].y - jy;
        }
      } else
      {
        if (nPts > 0 ) {
          path = gesture.path;
          for (int i = 0; i < nPts1; i++) {
            path[i].x = path[i+1].x;
            path[i].y = path[i+1].y;
          }
          path[nPts1].x = path[0].x + jx;
          path[nPts1].y = path[0].y + jy;
        }
      }
      gesture.compile();
    }
  }
  void clearGestures()
  {
    for (int i = 0; i < nGestures; i++)
    {
      gestureArray[i].clear();
    }
  }
}