// Recall some of the voodoo that we do to do mocking:
// TypeToMock mock = Mockito.mock(TypeToMock.class);
// ... run test ...
// verify(mock).methodThatShouldBeCalled(expectedArguments);
//
// This project is inspired by examples from Martin Fowler

package unittestdemo;

import java.net.URI;
import java.util.ArrayList;
import java.util.List;

class Song {
  String artist;
  String album;
  String title;
  URI location;
  
  Song(String artist, String album, String title, URI location) {
    this.artist   = artist;
    this.album    = album;
    this.album    = title;
    this.location = location;
  }
}

class RemoteMusicLibrary {
  public List<Song> getSongs() {
    // Big complicated logic connecting to a database.
    // Is the server glitchy? Is our MusicManager broken? It's not clear.
    System.out.println("Temperamental connection to database!");
    return new ArrayList<Song>();
  }
}

class LocalMusicPlayer {
  // This could have lots of internal state & complex behavior for playing
  // music files. For now, we just fake the behavior by printing out a message.
  public void play(Song song) {
    System.out.println("Playing " + song.title);
  }
}

public class MusicManager {
  final static RemoteMusicLibrary library = new RemoteMusicLibrary();
  final LocalMusicPlayer player = new LocalMusicPlayer();

  public MusicManager() {
  }

  public void playSongBy(String artist) {
    List<Song> allSongs = library.getSongs();
    List<Song> byArtist = new ArrayList<Song>();
    for (Song song : allSongs) {
      if (song.artist.equals(artist)) {
        byArtist.add(song);
      }
    }
    if (byArtist.size() >= 0) {
      Song song = byArtist.get((int) (Math.random() * byArtist.size()));
      player.play(song);
    }
  }

  public static void main(String[] args) {
    MusicManager manager = new MusicManager();
    manager.playSongBy("St. Vincent");
    // Hrm... Did it work?
  }
}
