import java.util.ArrayList;

class Staff2 extends Staff
{
  private int ticker;
  private ArrayList openNotes;
  private ArrayList playedNotes;
  
  private int[][] notes = new int[][] {
    {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0}, // F
    {0, 1, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, // E
    {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, // D
    {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0}, // C
    {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, // B
    {0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, // A
    {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0}, // G
    {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, // F
    {0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0} // E
  };
  
  // These values are quite touchy at the moment
  // If you leave the distanceFactor at 100 you can change the scrollSpeed to any multiple of two
  // If you set a custom distance factor you are on your own....
  public float scrollSpeed = 4;
  public int distanceFactor = 100;
  
  public Staff2()
  {
    ticker = 0;
    openNotes = new ArrayList();
    playedNotes = new ArrayList();
  }
  
  public boolean advance()
  {
    /*****************************
    ******* Advance the staff ****
    *****************************/
    ticker += getScrollSpeed();
    
    /*****************************
    * Advance each of its notes **
    *****************************/    
    for (int i=0;i<openNotes.size();i++) { ((Note) openNotes.get(i)).advance(); }
    for (int i=0;i<playedNotes.size();i++) { ((Note) playedNotes.get(i)).advance(); }
    
    /*****************************
    * Look for new notes coming on the board **
    *****************************/        
    int factoredTicker = ticker / distanceFactor;
    if (factoredTicker < notes[0].length)
    {
      if (ticker % distanceFactor == (distanceFactor % scrollSpeed))
      {      
        /*****************************
        * Look on the lines first **
        *****************************/        
        int lineInterval = Config.gameHeight / numberOfLines;
        lineInterval -= lineInterval / numberOfLines; // offset so that there is some top and bottom padding
        
        for (int line=0;line<numberOfLines*2;line += 2)
        {
          if (notes[line][factoredTicker] == 1)
          {
            openNotes.add(new Note(this, Config.gameWidth, lineInterval * (line/2), noteMap[line]));
          }
        }      
        
        /*****************************
        * Then look on the spaces **
        *****************************/        
        int spaceInterval = Config.gameHeight / 6;
        for (int line=1;line<=numberOfSpaces*2;line += 2)
        {
          if (notes[line][factoredTicker] == 1)
          {
            openNotes.add(new Note(this, Config.gameWidth, (spaceInterval * (line/2)) + 35, noteMap[line]));
          }
        }      
        
      }
      return true;
    } else { // This staff is finished, no more notes to display
      return false;
    }
  }
  
  public void draw()
  {
    /**********************************
    *****  Draw staff lines************
    **********************************/
    stroke(lineColor);
    strokeWeight(lineWeight);
    fill(lineColor);
        
    int interval = Config.gameHeight / numberOfLines;
    interval -= interval/numberOfLines; // offset so that there is some top and bottom padding
    
    for (int i=1;i<=numberOfLines;i++)
    {
      int height = interval * i;
      line(0, height, Config.gameWidth, height);
    }
  
    /**********************************
    *****  Draw treble clef ***********
    **********************************/
    PImage clef;
    clef = loadImage("treble-clef.png");
    image(clef, 10, 10, 120, interval * numberOfLines);

    /**********************************
    *****  Draw beginning bar *********
    **********************************/
    stroke(barColor);
    line(Config.boundaryX, interval, Config.boundaryX, Config.gameHeight - interval - 20);    
    
    /**********************************
    *****  Draw notes ************
    **********************************/
    for (int i=0;i<openNotes.size();i++) { ((Note) openNotes.get(i)).draw(); }
    for (int i=0;i<playedNotes.size();i++) { ((Note) playedNotes.get(i)).draw(); }
  }
  
  public void hitCorrectNote()
  {
    if (openNotes.size() == 0) { return; }

    Note note = (Note)openNotes.get(0);
    note.hit();
    playedNotes.add(note);
    
    openNotes.remove(0);
  }
}
