/*
 * This file is part of GNAC - Gnome Audio Converter
 *
 * Copyright (C) 2007 - 2012 Gnac
 *    
 *    - DUPASQUIER  Benoit    <bdupasqu@src.gnome.org>
 *    - JOAQUIM     David     <djoaquim@src.gnome.org>
 *    - ROUX        Alexandre <alexroux@src.gnome.org>
 *
 * GNAC is free software; you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation; either version 3 of the License, or
 * (at your option) any later version.
 *
 * GNAC is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with GNAC; if not, write to the Free Software
 * Foundation, Inc., 51 Franklin St, Fifth Floor, 
 * Boston, MA  02110-1301  USA
 */

#ifdef HAVE_CONFIG_H
#include "config.h"
#endif

#include <glib/gi18n.h>

#include "gnac-main.h"
#include "gnac-playlist.h"


typedef struct {
  const gchar  *mime;
  void        (*handler)(GFile *file);
} GnacPlaylistMimeHandler;

static void gnac_playlist_parse_asx(GFile *file);
static void gnac_playlist_parse_m3u(GFile *file);
static void gnac_playlist_parse_pls(GFile *file);
static void gnac_playlist_parse_xspf(GFile *file);

static GnacPlaylistMimeHandler mime_playlist[] = {
  { "audio/x-ms-asx"      , &gnac_playlist_parse_asx  },
  { "audio/x-mpegurl"     , &gnac_playlist_parse_m3u  },
  { "audio/x-scpls"       , &gnac_playlist_parse_pls  },
  { "application/xspf+xml", &gnac_playlist_parse_xspf },
  { NULL, NULL }
};


static void
gnac_playlist_resolve_uri_and_add(GFile *parent,
                                  gchar *filename)
{
  g_return_if_fail(filename);

  g_strstrip(filename);

  if (!g_utf8_validate(filename, -1, NULL)) {
    g_printerr("%s: %s\n", _("Invalid UTF-8 filename"), filename);
    return;
  }

  GFile *file;

  if (g_str_has_prefix(filename, "file://")) {
    file = g_file_new_for_uri(filename);
  } else {
    file = g_file_get_child(parent, filename);
  }

  gnac_add_file(file);
}


static gchar *
gnac_playlist_read_file(GFile *file)
{
  gsize  size;
  gchar *contents;

  if (!g_file_load_contents(file, NULL, &contents, &size, NULL, NULL)) {
    return NULL;
  }

  if (size == 0) {
    g_free(contents);
    return NULL;
  }
  
  return contents;
}


gboolean
gnac_playlist_is_mime_playlist(const gchar *mime)
{
  if (!mime) return FALSE;

  guint i;
  for (i = 0; mime_playlist[i].mime; i++) {
    if (g_ascii_strcasecmp(mime, mime_playlist[i].mime) == 0) {
      return TRUE;
    }
  }

  return FALSE;
}


void
gnac_playlist_parse(GFile       *file,
                    const gchar *mime)
{
  guint i;
  for (i = 0; mime_playlist[i].mime; i++) {
    if (g_ascii_strcasecmp(mime, mime_playlist[i].mime) == 0) {
      mime_playlist[i].handler(file);
      return;
    }
  }
}


static void
gnac_playlist_parse_asx(GFile *file)
{
  GFile *parent = g_file_get_parent(file);
  gchar *contents = gnac_playlist_read_file(file);
  if (!contents) return;

  gchar **lines = g_strsplit(contents, "\n", -1);

  guint i;
  for (i = 0; lines[i]; i++) {
    /* skip empty lines */
    if (!*lines[i]) continue;

    gchar *line = g_strstrip(lines[i]);

    gchar *lc_line = g_utf8_strdown(line, -1);

    if (g_str_has_prefix(lc_line, "<ref href")) {
      gchar **tmp1 = g_strsplit(line, "\"", -1);
      gchar *tmp2 = g_strdup(tmp1[1]);
      guint j;
      for (j = 2; tmp1[j]; j++) {
        gchar *tmp3 = g_strconcat(tmp2, tmp1[j], NULL);
        g_free(tmp2);
        tmp2 = g_strdup(tmp3);
        g_free(tmp3);
      }
      line = tmp2;
      gnac_playlist_resolve_uri_and_add(parent, line);
      g_free(tmp2);
      g_strfreev(tmp1);
    }

    g_free(lc_line);
  }

  g_strfreev(lines);
  g_free(contents);
}


static void
gnac_playlist_parse_m3u(GFile *file)
{
  GFile *parent = g_file_get_parent(file);
  gchar *contents = gnac_playlist_read_file(file);
  if (!contents) return;

  gchar **lines = g_strsplit(contents, "\n", -1);

  guint i;
  for (i = 0; lines[i]; i++) {
    /* skip comments and empty lines */
    if (!*lines[i] || *lines[i] == '#') continue;

    gnac_playlist_resolve_uri_and_add(parent, lines[i]);
  }

  g_strfreev(lines);
  g_free(contents);
}


static void
gnac_playlist_parse_pls(GFile *file)
{
  GFile *parent = g_file_get_parent(file);
  gchar *contents = gnac_playlist_read_file(file);
  if (!contents) return;

  gchar **lines = g_strsplit(contents, "\n", -1);

  guint i;
  for (i = 0; lines[i]; i++) {
    /* skip empty lines */
    if (!*lines[i]) continue;

    gchar **pair = g_strsplit(lines[i], "=", 2);
    gchar *key = g_utf8_strdown(pair[0], -1);

    if (pair[1] && g_str_has_prefix(key, "file")) {
      gnac_playlist_resolve_uri_and_add(parent, pair[1]);
    }

    g_free(key);
    g_strfreev(pair);
  }

  g_strfreev(lines);
  g_free(contents);
}


static void
gnac_playlist_parse_xspf(GFile *file)
{
  GFile *parent = g_file_get_parent(file);
  gchar *contents = gnac_playlist_read_file(file);
  if (!contents) return;

  gchar **lines = g_strsplit(contents, "\n", -1);

  guint i;
  for (i = 0; lines[i]; i++) {
    /* skip empty lines */
    if (!*lines[i]) continue;

    gchar *line = g_strstrip(lines[i]);
    gchar *lc_line = g_utf8_strdown(lines[i], -1);

    if (g_str_has_prefix(lc_line, "<location>")) {
      gchar **tmp1 = g_strsplit(line, ">", 2);
      gchar **tmp2 = g_strsplit(tmp1[1], "<", 2);
      g_strfreev(tmp1);
      line = tmp2[0];
      gnac_playlist_resolve_uri_and_add(parent, line);
      g_strfreev(tmp2);
    }

    g_free(lc_line);
  }

  g_strfreev(lines);
  g_free(contents);
}
