importClass(java.net.URL);
importClass(java.io.File);
importClass(java.io.FileOutputStream);

SONG_BASE_DIR = "../web/songs";
ART_BASE_DIR = "../web/albumArt";

BASE_URL = "http://cdbaby.com";

load("../src/rhino/rhinoRecord.js");

//hash of artists and genres (to avoid duplicates)
artists = {};
genres = {};

/**
   Downloads the file from the specified url to the specified file.
 */
function downloadFile(url, outputFileName) {
   var fileUrl = new URL(url);
   try {
      var input = fileUrl.openStream();
      var out = new FileOutputStream(outputFileName);
      var b;
      while ((b=input.read()) != -1) {
         out.write(b);
      }
   }
   finally {
      input.close();
      out.close();
   }
}

/**
   A song from cdbaby.com
 */
function Song(link, album) {
   var props = {};
   this.superclass = RhinoRecord;
   this.superclass(arguments.callee, props);
   
   this.album = album;
   
   matches = link.match(/<a href="(\/mp3lofi\/.*?-0*(\d+).m3u)">(.*?)<\/a>/i);
   this.playlistUrl = BASE_URL + matches[1];
   this.trackNum = matches[2];
   this.name = matches[3];

   this.display = function() {
      print(this.trackNum + ". " + this.name + " -- " + this.playlistUrl);
   }

   this.getMp3Url = function() {
      return readUrl(this.playlistUrl);
   }
   
   this.downloadMp3 = function(songDir) {
      this.filePath = songDir + "/" + this.trackNum + ".mp3";
      downloadFile(this.getMp3Url(), this.filePath);
   }
}
Song.prototype = new RhinoRecord();
Song.prototype.constructor = Song;

/**
   Artist from cdbaby.com
 */
function Artist(name) {
   var props = {};
   this.superclass = RhinoRecord;
   this.superclass(arguments.callee, props);
   this.name = name;
}
Artist.prototype = new RhinoRecord();
Artist.prototype.constructor = Artist;

/**
   Artist from cdbaby.com
 */
function Genre(name) {
   var props = {};
   this.superclass = RhinoRecord;
   this.superclass(arguments.callee, props);
   this.name = name;
}
Genre.prototype = new RhinoRecord();
Genre.prototype.constructor = Genre;

/**
   An album from cdbaby.com.  This will parse the specified url to get the needed information.
 */
function Album(url) {
   var props = {};
   this.superclass = RhinoRecord;
   this.superclass(arguments.callee, props);
   
   var page = readUrl(url);
   
   this.url = url;
   this.publicId = url.match(/.*\/(.*)/)[1];
   
   var title = page.match(/<title>.*?:\s*(.*?)\s*:\s*(.*?)\s*<\/title>/);
   
   var artistName = title[1];
   if(!(artistName in artists)) {
      this.artist = new Artist(artistName);
      artists[artistName] = this.artist;
   }
   else {
      this.artist = artists[artistName];
   }
   
   this.title = title[2];
   
   var genreName = page.match(/GENRES you need to try.*?>(\w+):/)[1];
   if(!(genreName in genres)) {
      this.genre = new Genre(genreName);
      genres[genreName] = this.genre;
   }
   else {
      this.genre = genres[genreName];
   } 
   
   this.albumCoverUrl = page.match(/<img src="(http:\/\/cdbaby.name\/.*?.jpg)" width="200" height="200" alt="album cover"/i)[1];

   var blurbMatch = page.replace(/\n/g, " ").match(/<!-- NOTES -->.*?>NOTES(.*)/);
   this.blurb = blurbMatch[1].replace(/<.*?>/g, ' ').replace(/^\s*/,'');
   if (this.blurb.match(/^REVIEWS!/)) this.blurb = "";
   
   this.songs = {};
   links = page.match(/<a href="\/mp3lofi\/.*?-\d+.m3u">.*?<\/a>/gi);
   for (var i in links) {
      l = links[i];
      song = new Song(l, this);
      this.songs[song.trackNum] = song;
   }
   
   this.saveSongs = function() {
      for (var trackNum in this.songs) {
         song = this.songs[trackNum];
         song.save();
      }
   }

   this.display = function() {
      print('"' + this.title + '" by ' + this.artist.name);
      print("available at " + this.url);
      print("public id: " + this.publicId);
      print("genre: " + this.genre.name);
      print("album cover: " + this.albumCoverUrl);
      print("----------------------------");
      for (var trackNum in this.songs) {
         song = this.songs[trackNum];
         song.display();
      }
      print("----------------------------");
      print("About this album: " + this.blurb);
      print();
   }
   
   this.downloadSongs = function(songBaseDir) {
      songBaseDir = songBaseDir || SONG_BASE_DIR;
      var songDir = songBaseDir + "/" + this.publicId;
      
      var dir  = new File(songDir);
      if (!dir.exists()) dir.mkdir();
      
      for (var i in this.songs) {
         var song = this.songs[i];
         song.downloadMp3(songDir);
      }
   }
   
   this.downloadAlbumArt = function(artDir) {
      artDir = artDir || ART_BASE_DIR;
      this.albumCoverPath = artDir + "/" + this.publicId + ".jpg"
      downloadFile(this.albumCoverUrl, this.albumCoverPath);
   }
}

Album.prototype = new RhinoRecord();
Album.prototype.constructor = Album;


var albums = []
var urlList = [
   "http://cdbaby.com/cd/markgrowden", "http://cdbaby.com/cd/markgrowden3",
   "http://cdbaby.com/cd/bedlammusic",
   "http://cdbaby.com/cd/daughterdarling",
   "http://cdbaby.com/cd/namelyus",
   "http://cdbaby.com/cd/fiddlehead",
   "http://cdbaby.com/cd/surfcinema"//*/
];
for (var i in urlList) {
   var url = urlList[i];
   var al = new Album(url);
   albums.push(al);
   al.display();
   al.downloadSongs();
   al.downloadAlbumArt();
   al.saveSongs();
}
