//  BMPx - The Dumb Music Player
//  Copyright (C) 2003-2007 BMPx development team.
//
//  This program is free software; you can redistribute it and/or modify
//  it under the terms of the GNU General Public License Version 2
//  as published by the Free Software Foundation.
//
//  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.

#ifndef BMP_LIBRARY_TYPES_HH
#define BMP_LIBRARY_TYPES_HH

#include "bmp/types/types-basic.hh"
#include "bmp/types/types-database.hh"

#include <vector>
#include <map>
#include <string>

#include <boost/optional.hpp>
#include <boost/format.hpp>
#include <boost/tuple/tuple.hpp>
#include <boost/tuple/tuple_comparison.hpp>
#include <glibmm.h>

using namespace Bmp::DB;

namespace TagLib
{
  class Tag;
  namespace ID3v2
  {
    class Tag;
  }
}

namespace Bmp
{
    struct AttributeInfo
    {
      char const*   title;
      char const*   id;
      DB::ValueType type;
      bool          use;
    };

    enum AttributeId
    {
      ATTRIBUTE_LOCATION,
      ATTRIBUTE_TITLE,
      ATTRIBUTE_TRACK,
      ATTRIBUTE_TIME,
      ATTRIBUTE_GENRE,
      ATTRIBUTE_COMMENT,
      ATTRIBUTE_RATING,
      ATTRIBUTE_DATE,
      ATTRIBUTE_MTIME,
      ATTRIBUTE_BITRATE,
      ATTRIBUTE_SAMPLERATE,
      ATTRIBUTE_COUNT,
      ATTRIBUTE_PLAYDATE,
      ATTRIBUTE_MUSICIP_PUID,
      ATTRIBUTE_NEW_ITEM,  
      ATTRIBUTE_HASH,     
      ATTRIBUTE_MB_TRACK_ID, 

      ATTRIBUTE_ARTIST,
      ATTRIBUTE_MB_ARTIST_ID,
      ATTRIBUTE_MB_ARTIST_SORTNAME,

      ATTRIBUTE_ALBUM,
      ATTRIBUTE_MB_ALBUM_ID,
      ATTRIBUTE_MB_RELEASE_DATE,
      ATTRIBUTE_ASIN,

      // Album_Artist 
      ATTRIBUTE_IS_MB_ALBUM_ARTIST,

      ATTRIBUTE_MB_ALBUM_ARTIST,
      ATTRIBUTE_MB_ALBUM_ARTIST_ID,
      ATTRIBUTE_MB_ALBUM_ARTIST_SORTNAME,

      // Misc
      ATTRIBUTE_ACTIVE,

      // MIME type
      ATTRIBUTE_TYPE,

      // HAL
      ATTRIBUTE_HAL_VOLUME_UDI,
      ATTRIBUTE_HAL_DEVICE_UDI,
      ATTRIBUTE_VOLUME_RELATIVE_PATH,

      N_ATTRIBUTES
    };

    class Artist
    {
      public:

        Artist (Row const& row);
        Artist () {}
        virtual ~Artist () {}

        opt_stdstring  artist;
        opt_stdstring  mb_artist_id;
        opt_stdstring  mb_artist_sort_name;

        guint64 bmpx_artist_id;

        operator std::string () const
        {
          return (mb_artist_sort_name ? mb_artist_sort_name.get () : (artist ? artist.get () : std::string()));
        }

        Row m_row;
    };

    class AlbumArtist
    {
      public:

        AlbumArtist (Row const& row);
        AlbumArtist () {}
        virtual ~AlbumArtist () {}

        opt_stdstring   album_artist;
        opt_stdstring   mb_album_artist_id;
        opt_stdstring   mb_album_artist_sort_name;

        guint64        is_mb_album_artist;
        guint64        bmpx_album_artist_id;

        operator std::string () const
        {
          return mb_album_artist_sort_name ? mb_album_artist_sort_name.get() : (album_artist  ? album_artist.get() : std::string());
        }

        Row m_row;
    };
    typedef std::vector <AlbumArtist> AlbumArtistV;

    class Album
    {
      public:

        Album (Row const& row);
        Album () {}
        virtual ~Album () {};

        opt_stdstring   album;
        opt_stdstring   mb_album_id;
        opt_stdstring   mb_release_date;
        opt_stdstring   asin;

        opt_stdstring   album_artist;
        opt_stdstring   mb_album_artist_id;
        opt_stdstring   mb_album_artist_sort_name;

        guint64 is_mb_album_artist;
        guint64 bmpx_album_id;    
        guint64 bmpx_album_artist_id;

        Row m_row;
    };
    typedef std::vector <Album> AlbumV;

    typedef boost::tuple <opt_stdstring, opt_stdstring, opt_stdstring > TripleT;
    typedef boost::tuple <opt_stdstring, opt_stdstring, opt_stdstring, opt_stdstring > QuadT;
    typedef boost::tuple <opt_stdstring, opt_stdstring, opt_stdstring, guint64> Quad2T;
    typedef std::map <TripleT, UID> TripleTUIDMapT; 
    typedef std::map <QuadT, UID> QuadTUIDMapT; 
    typedef std::map <Quad2T, UID> Quad2TUIDMapT; 

    class Track
    {
      public:

        // Location
  
        opt_stdstring   volume_udi;
        opt_stdstring   device_udi;
        opt_stdstring   volume_relative_path;
        opt_stdstring   location;

        // Metadata

        opt_stdstring   artist;
        opt_stdstring   album;
        opt_stdstring   title;
        opt_stdstring   genre;
        opt_stdstring   comment;
        opt_stdstring   asin;
        opt_stdstring   puid;
        opt_stdstring   mb_album_artist;
        opt_stdstring   mb_album_artist_id;
        opt_stdstring   mb_album_artist_sort_name;
        opt_stdstring   mb_track_id;
        opt_stdstring   mb_album_id;
        opt_stdstring   mb_artist_id;
        opt_stdstring   mb_artist_sort_name;
        opt_stdstring   mb_release_date;

        opt_uint64      tracknumber;
        opt_uint64      date;

        // Audio Properties

        opt_uint64      duration;
        opt_uint64      bitrate;
        opt_uint64      samplerate;

        // Our data

        opt_uint64      rating;
        opt_uint64      mtime;
        opt_uint64      count;

        opt_stdstring   hash;
        opt_stdstring   type;

        opt_uint64      playdate;
        opt_uint64      new_item;

        opt_uint64      active;

        // Library IDs

        guint64 bmpx_track_id;
        guint64 bmpx_artist_id;
        guint64 bmpx_album_id;

        Row m_row;
  
#ifdef HAVE_HAL
        Track (Row const& row, bool use_hal = true);
#else
        Track (Row const& row, bool use_hal = false);
#endif //HAVE_HAL

        Track () {};
        virtual ~Track () {}

        std::string get_canonical_filename (std::string const& ext = std::string()) const;
    };
    typedef std::vector <Track> TrackV;
} //namespace Bmp 

#endif //!BMP_LIBRARY_TYPES_HH
