Source: lib/parser.js

var eol = require('eol')
var Album = require('./album')
var Artist = require('./artist')
var Collection = require('./collection')
var Playlist = require('./playlist')
var Similar = require('./similar')
var SpotifyRequestHandler = require('./spotify')
var Top = require('./top')
var Track = require('./track')
var WebScraper = require('./scraper')

/**
 * Create a parser.
 * @constructor
 */
function Parser (token, handler) {
  /**
   * Spotify request handler.
   */
  this.spotify = handler || new SpotifyRequestHandler(null, null, token)
}

/**
 * Parse a string and create a playlist collection.
 * @param {string} [str] - A newline-separated string of
 * entries on the form `TITLE - ARTIST`. May also contain
 * `#ALBUM`, `#ARTIST`, `#ORDER` and `#GROUP` commands.
 * @return {Collection} A playlist collection.
 */
Parser.prototype.parse = function (str) {
  var collection = new Collection(this.spotify)
  str = str.trim()
  if (str) {
    var lines = eol.split(str)
    while (lines.length > 0) {
      var match = null
      var line = lines.shift().trim()
      if ((match = line.match(/^#(SORT|ORDER)\s+BY\s+([^\s]*)(\s+([^\s]*))?/i))) {
        collection.ordering = match[2].toLowerCase()
        collection.lastfmUser = match[4]
      } else if ((match = line.match(/^#GROUP\s+BY\s+(.*)/i))) {
        collection.grouping = match[1].toLowerCase()
      } else if ((match = line.match(/^#(ALTERNATE|INTERLEAVE)\s+BY\s+(.*)/i))) {
        collection.alternating = match[2].toLowerCase()
      } else if (line.match(/^#(DUP(LICATES?)?|NONUNIQUE|NONDISTINCT)/i)) {
        collection.unique = false
      } else if (line.match(/^#REVERSE/i)) {
        collection.reverse = true
      } else if (line.match(/^#SHUFFLE/i)) {
        collection.shuffle = true
      } else if (line.match(/^#(UNIQUE|DISTINCT)/i)) {
        collection.unique = true
      } else if (line.match(/^#DEDUP/i)) {
        collection.unique = false
      } else if (line.match(/^#(CSV|CVS)/i)) {
        collection.csv = true
      } else if (line.match(/^##/i) ||
                 line.match(/^#EXTM3U/i) ||
                 line.match(/^sep=,/i)) {
        // comment
      } else if ((match = line.match(/^#ALBUM((ID)?)([0-9]*)\s+(.*)/i))) {
        var album = new Album(this.spotify, match[4], null, parseInt(match[3]))
        if (match[2]) {
          album.fetchTracks = false
        }
        collection.add(album)
      } else if ((match = line.match(/^#ARTIST([0-9]*)\s+(.*)/i))) {
        collection.add(new Artist(this.spotify, match[2], null, parseInt(match[1])))
      } else if ((match = line.match(/^#TOP([0-9]*)\s+(.*)/i))) {
        collection.add(new Top(this.spotify, match[2], null, parseInt(match[1])))
      } else if ((match = line.match(/^#SIMILAR([0-9]*)\s+(.*)/i))) {
        collection.add(new Similar(this.spotify, match[2], null, parseInt(match[1])))
      } else if ((match = line.match(/^#PLAYLIST([0-9]*)\s+([0-9a-z]+)[\s/]([0-9a-z]+)/i))) {
        collection.add(new Playlist(this.spotify, line, match[3], match[2], parseInt(match[1])))
      } else if ((match = line.match(/^#PLAYLIST([0-9]*)\s+(.*)/i))) {
        collection.add(new Playlist(this.spotify, match[2], null, null, parseInt(match[1])))
      } else if ((match = line.match(/^#EXTINF(:[0-9]+,(.*))?/i))) {
        if (match[1]) {
          collection.add(new Track(this.spotify, match[2]))
          if (lines.length > 0 &&
              !lines[0].match(/^#/)) {
            lines.shift()
          }
        }
      } else if ((match = line.match(/spotify:artist:([0-9a-z]+)/i))) {
        collection.add(new Artist(this.spotify, line, match[1]))
      } else if ((match = line.match(/^([0-9]+ )?https?:\/\/(.*\.)?spotify\.com\/(.*\/)*artist\/(.*\/)*([0-9a-z]+)/i))) {
        collection.add(new Artist(this.spotify, line, match[5], parseInt(match[1])))
      } else if ((match = line.match(/spotify:album:([0-9a-z]+)/i))) {
        collection.add(new Album(this.spotify, line, match[1]))
      } else if ((match = line.match(/^([0-9]+ )?https?:\/\/(.*\.)?spotify\.com\/(.*\/)*album\/(.*\/)*([0-9a-z]+)/i))) {
        collection.add(new Album(this.spotify, line, match[5], parseInt(match[1])))
      } else if ((match = line.match(/spotify:user:([0-9a-z]+):playlist:([0-9a-z]+)/i))) {
        collection.add(new Playlist(this.spotify, line, match[2], match[1]))
      } else if ((match = line.match(/^([0-9]+ )?https?:\/\/(.*\.)?spotify\.com\/(.*\/)*user\/([0-9a-z]+)\/playlist\/([0-9a-z]+)/i))) {
        collection.add(new Playlist(this.spotify, line, match[5], match[4], parseInt(match[1])))
      } else if ((match = line.match(/spotify:track:([0-9a-z]+)/i))) {
        collection.add(new Track(this.spotify, line, match[1]))
      } else if ((match = line.match(/^([0-9]+ )?https?:\/\/(.*\.)?spotify\.com\/(.*\/)*([0-9a-z]+)/i))) {
        collection.add(new Track(this.spotify, line, match[4]))
      } else if ((match = line.match(/^([0-9]+ )?(https?:.*)/i))) {
        collection.add(new WebScraper(match[2], parseInt(match[1]), this))
      } else if (line) {
        collection.add(new Track(this.spotify, line))
      }
    }
  }
  return collection
}

module.exports = Parser