// Implements a play list for a radio station as a
// collection of songs stored in an array.  All songs are
// always stored at the beginning of the array.  But this
// array will grow as needed, depending on how many songs
// are added to the list

// To create the playlist the radio station can add songs to the front
// of the list.  The radio station can play the song at the end of the
// play list and then remove that song at the playlist. (Aside: The
// ability to add to the front and remove from the end is known as a
// QUEUE or First-In-First-Out (FIFO) list.)
// 
// When the radio station gets a request, it can also put a song at
// the end of the playlist.  (Aside: If we also allow the radio
// station to remove the first song on the playlist, then the ability
// to add and remove from the both the front and the end of playlist
// is known as a double-ended queue or DEQUE.)
//
// (Aside: If the abilities are only to add to or remove from the end
// of the play list, then the playlist is known as a STACK or
// Last-In-First-Out (LIFO) list.)
// 
// Playlist concept by: Tom Cortina
// Written by: Margaret Reid-Miller
//
public class PlayList {
    
    private Song[] songList;
    private int numSongs;
    
    // create an empty playlist that holds at most one song
    public PlayList() {
        songList = new Song[1];
        numSongs = 0;
    }    

    // Insert a song at the end of the playlist 
    public void insertAtEnd(Song newSong) {
        
        if (songList.length == numSongs) {  // is the array full?
            this.doubleLength();  // double the length of this object's songList
            // doubleLength();    // this is optional
 //           System.out.println("ERROR: The array is full. "
 //                  + "Song is not added to the playlist");
 //           return;
        }
       
        songList[numSongs] = newSong;
        numSongs++;           // Keep numSongs consistent with the data
    }

    // Return the first song on the playlist. Return null if there are no songs
    public Song getFirstSong() {
    	if (numSongs > 0) {
    		return songList[0];
    	}
    	else {
    		return null;
    	}
    }
  
    // Returns the average number of weeks the songs in songList are on
    // the charts.
    // Returns NaN (not-a-number) if there is no songs
    public double getAverageWeeks() {
        
        
        // initialize sum = 0.0 for the sum of no songs
        double sum = 0.0;
        
        // Before each iteration, sum is the sum of the first index
        // number of songs.  That is, if position = 2 sum is the sum
        // of the first 2 songs.
        for (int index = 0; index < numSongs; index++) {
            sum = sum + songList[index].getWeeksOnChart();
        }
        
        return sum / numSongs;
 
    }
 
    // Insert Example 2: Insert song in the first cell of the array,
    // shifting all other songs over one position to make room.
    public void insertAtFront(Song newSong) {
        

        if (numSongs == songList.length)    {    // is array full?
            doubleLength();                      // double the array length
        }
        
        // Make space at the front of the list by shifting all the songs
        // over one position towards the end of the list.
	// If there are 6 songs in the list then we will assign index
        //  to     from
        //   6      5  (numSongs-1)
        //   5      4
        //   ...
        //   1      0
        // So loop over 5 (numSongs-1) ... 0    
        for (int from = numSongs-1; from >= 0; from--)    {
            int to = from + 1; // move towards the end
            songList[to] = songList[from];  // copy from songList[from] 
                                            // to songList[to]
        }

        songList[0] = newSong;  // insert the new song
        numSongs++;             // now there is one more song
    }  

    // Remove Example 1: Remove the last song
    public void remove()    {
 
        if (numSongs > 0)    {    // make sure array has at least one song!   
            songList[numSongs-1] = null;  // Optional because never will
                                          // try to access this element
                                          // But setting to null allows the
                                          // garbage collector to remove the
                                          // song from memory.
            numSongs--;
        }
  
    }
  
    // Remove Example 2: Remove the first song
    public void removeAtFront() {

	if (numSongs > 0)    {    // make sure array has at least one song! 
  
            // Shift all the songs towards the front of the array.
	    // If there are 6 songs in the list then we will assign
	    //  to     from
	    //   0      1
	    //   1      2
	    //   ...
	    //   4      5  (numSongs-1)
	    // So loop over 1 ... (numSongs-1)
            for (int from = 1; from < numSongs; from++)    {
            	int to = from - 1; // move towards the front
                songList[to] = songList[from];  // copy from songList[from] 
                                                // to songList[to]
            }
      	
            songList[numSongs-1] = null;  // Optional 
            numSongs--;
        }

    }
    
    // returns a String representation of the entire playlist
    public String toString()    {

        String result = "NumSongs = " + numSongs
            + " / Length = " + songList.length + "\n";

        for (int i=0; i<numSongs; i++) {
            result += ("songList[" + i + "] = <"
                        + songList[i] + ">\n");
        }
        return result;
    }

    // HELPER METHOD:

    // A helper method that doubles the length of the array that holds songs 
    // Use this method only if the array is full before you do an insert
    private void doubleLength() {
     
        Song[] newarray = new Song[songList.length * 2];
        for (int i = 0; i < numSongs; i++)
               newarray[i] = songList[i];
        songList = newarray;
        
        // What happens to the old array?
    }
}