//  BMP
//  Copyright (C) 2005-2007 BMP development.
//
//  This program 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 2 of the License, or
//  (at your option) any later version.
//
//  This program 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 this program; if not, write to the Free Software
//  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
//
//  --
//
//  The BMPx project hereby grants permission for non GPL-compatible GStreamer
//  plugins to be used and distributed together with GStreamer and BMPx. This
//  permission is above and beyond the permissions granted by the GPL license
//  BMPx is covered by.

#ifdef HAVE_CONFIG_H
#  include <config.h>
#endif //HAVE_CONFIG_H

#include <boost/format.hpp>

#include <glibmm/ustring.h>
#include <glib/gmessages.h>

#include "jamendodata-libxml2-sax.hh"

using namespace std;
using namespace Glib;
using namespace Bmp::DB;

#include "parser/libxml2-sax-base.hh"
using Bmp::XPath;

#include "jamendodata-libxml2-sax.hh"
#include "jamendo-types.hh"

namespace
{
  using namespace Bmp;
  
  struct JamendoDataParserContext
    : public ParseContextBase
  {
    DB::Database          & m_db;
    JamendoData::Artist     m_artist;
    JamendoData::Album      m_album;
    JamendoData::Track      m_track;

    JamendoDataParserContext (DB::Database & db) : m_db (db) {}
  };

#define DEFAULT_REFS \
  JamendoDataParserContext & context (static_cast<JamendoDataParserContext&>(_context));  \
  Bmp::JamendoData::Artist &artist G_GNUC_UNUSED (context.m_artist);  \
  Bmp::JamendoData::Album  &album  G_GNUC_UNUSED (context.m_album);  \
  Bmp::JamendoData::Track  &track  G_GNUC_UNUSED (context.m_track);  \
  Bmp::DB::Database &db G_GNUC_UNUSED (context.m_db); \


  //////////////////////////////////////////////////////////////////////////////

  namespace Handlers
  {
    namespace Artists
    {
      HANDLER(artist)
      {
        DEFAULT_REFS
        artist            = Bmp::JamendoData::Artist();
        artist.id         = g_ascii_strtoull (props["id"].c_str(),NULL, 10);
        artist.name       = props["name"];
        artist.weblink    = props["link"];
        artist.image_url  = props["image"];
      }
    }

    namespace Albums
    {
      HANDLER(album)
      {
        DEFAULT_REFS
        album             = Bmp::JamendoData::Album();
        album.id          = g_ascii_strtoull (props["id"].c_str(),NULL, 10);
        album.artist_id   = g_ascii_strtoull (props["artistID"].c_str(),NULL, 10);
        album.weblink     = props["link"];
        album.pubdate     = props["publicDate"];
        album.releasedate = props["releaseDate"];
      }
    }

    namespace Tracks
    {
      HANDLER(track)
      {
        DEFAULT_REFS
        track             = Bmp::JamendoData::Track();
        track.id          = g_ascii_strtoull (props["id"].c_str(),NULL, 10);
        track.album_id    = g_ascii_strtoull (props["albumID"].c_str(),NULL, 10);
        track.trackno     = g_ascii_strtoull (props["trackno"].c_str(),NULL, 10);
        track.length      = g_ascii_strtoull (props["lengths"].c_str(),NULL, 10);
        track.weblink     = props["link"];
      }
    }
  }

  namespace HandlersEnd
  {
    namespace Artist
    {
      HANDLER_END(artist)
      {
        DEFAULT_REFS
      
        static char const * 
          insert_artist_f ( "INSERT INTO artist (name, id, link, dispname, genre, description, image) "
                            "VALUES ('%q', %llu, '%q', '%q', '%q', '%q', '%q');");
        db.exec_sql (mprintf (insert_artist_f , artist.name.c_str()
                                                  , artist.id
                                                  , artist.weblink.c_str()
                                                  , artist.dispname.c_str()
                                                  , artist.genre.c_str()
                                                  , artist.description.c_str()
                                                  , artist.image_url.c_str()));
      }
    }

    namespace Albums
    {
      HANDLER_END(album)
      {
        DEFAULT_REFS
      
        static char const * 
          insert_album_f ( "INSERT INTO album (name, id, link, pubdate, releasedate, artist_j) "
                                      "VALUES ('%q', %llu, '%q', '%q', '%q', '%llu');");
        db.exec_sql (mprintf (insert_album_f, album.dispname.c_str()
                                                , album.id
                                                , album.weblink.c_str()
                                                , album.pubdate.c_str()
                                                , album.releasedate.c_str()
                                                , album.artist_id));
      }
    }

    namespace Tracks
    {
      HANDLER_END(track)
      {
        DEFAULT_REFS
      
        static char const * 
          insert_track_f ( "INSERT INTO track (name, id, link, tracknumber, length, album_j) "
                                      "VALUES ('%q', %llu, '%q', '%llu', '%llu', '%llu');");
        db.exec_sql (mprintf (insert_track_f, track.dispname.c_str()
                                                , track.id
                                                , track.weblink.c_str()
                                                , track.trackno
                                                , track.length
                                                , track.album_id));
      }
    }

  }
  
  HandlerEndPair
  handlers_end[] =
  {
    HandlerEndPair( XPath("JamendoData/Artists/artist"), 
                      sigc::ptr_fun( &HandlersEnd::Artist::artist)),

    HandlerEndPair( XPath("JamendoData/Albums/album"), 
                      sigc::ptr_fun( &HandlersEnd::Albums::album)),

    HandlerEndPair( XPath("JamendoData/Tracks/track"), 
                      sigc::ptr_fun( &HandlersEnd::Tracks::track)) 
  };

  HandlerPair 
  handlers_start[] = 
  {
    HandlerPair( XPath("JamendoData/Artists/artist"), 
      sigc::ptr_fun( &Handlers::Artists::artist)), 

    HandlerPair( XPath("JamendoData/Albums/album"), 
      sigc::ptr_fun( &Handlers::Albums::album)),

    HandlerPair( XPath("JamendoData/Tracks/track"), 
      sigc::ptr_fun( &Handlers::Tracks::track)) 
  };
  
  namespace HandlersText
  {
    namespace Artist
    {
      HANDLER_Text(dispname)
      {
        DEFAULT_REFS
        artist.dispname += text;
      }

      HANDLER_Text(genre)
      {
        DEFAULT_REFS
        artist.genre += text;
      }

      HANDLER_Text(description)
      {
        DEFAULT_REFS
        artist.description += text;
      }
    }

    namespace Album
    {
      HANDLER_Text(dispname)
      {
        DEFAULT_REFS
        album.dispname += text;
      }

      HANDLER_Text(genre)
      {
        DEFAULT_REFS
        album.genre += text;
      }
    }

    namespace Track
    {
      HANDLER_Text(dispname)
      {
        DEFAULT_REFS
        track.dispname += text;
      }
    }
  }

  HandlerTextPair
  handlers_text[] = 
  {
    /// ARTIST

    HandlerTextPair( XPath("JamendoData/Artists/artist/dispname"), 
                      sigc::ptr_fun( &HandlersText::Artist::dispname)), 

    HandlerTextPair( XPath("JamendoData/Artists/artist/genre"), 
                      sigc::ptr_fun( &HandlersText::Artist::genre)),

    HandlerTextPair( XPath("JamendoData/Artists/artist/description"), 
                      sigc::ptr_fun( &HandlersText::Artist::description)), 

    /// ALBUM

    HandlerTextPair( XPath("JamendoData/Albums/album/dispname"), 
                      sigc::ptr_fun( &HandlersText::Album::dispname)),

    HandlerTextPair( XPath("JamendoData/Albums/album/genre"), 
                      sigc::ptr_fun( &HandlersText::Album::genre)),

    /// TRACK

    HandlerTextPair( XPath("JamendoData/Tracks/track/dispname"), 
                      sigc::ptr_fun( &HandlersText::Track::dispname)) 
  };
  //---------
}

namespace Bmp
{
  namespace JamendoData
  {
    int parse (DB::Database & db, std::string const& data)
    {
      JamendoDataParserContext context (db);

      for (unsigned int n = 0; n < G_N_ELEMENTS(handlers_start); context << handlers_start[n++]); 
      for (unsigned int n = 0; n < G_N_ELEMENTS(handlers_end); context << handlers_end[n++]); 
      for (unsigned int n = 0; n < G_N_ELEMENTS(handlers_text); context << handlers_text[n++]); 
       
      return SaxParserBase::xml_base_parse(data, context);
    }
  }
}
