//  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.

#ifndef BMP_MB_TAGGER_HH
#define BMP_MB_TAGGER_HH

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

#include <glibmm/ustring.h>
#include <gdkmm/pixbuf.h>
#include <gtkmm/button.h>
#include <gtkmm/checkbutton.h>
#include <gtkmm/dialog.h>
#include <gtkmm/entry.h>
#include <gtkmm/comboboxentry.h>
#include <gtkmm/image.h>
#include <gtkmm/label.h>
#include <gtkmm/liststore.h>
#include <gtkmm/progressbar.h>
#include <gtkmm/toggleaction.h>
#include <gtkmm/treeview.h>
#include <gtkmm/uimanager.h>
#include <libglademm/xml.h>

#include "musicbrainz/mbxml-v2.hh"
#include "library.hh"

#include "bmp/types/types-ui.hh"
#include "bmp/types/types-lastfm.hh"

using namespace Glib;

namespace Bmp
{
  class MusicBrainzTagger
    : public Gtk::Dialog
  {
        Glib::RefPtr<Gnome::Glade::Xml> m_ref_xml;

        typedef std::map<Glib::ustring, MusicBrainzXml::MusicBrainzRelease> ReleaseIdToReleaseMap;
        typedef std::map<Glib::ustring, UStrV> ArtistIdToReleasesMap;

    public:

        MusicBrainzTagger (BaseObjectType*                        obj,
                           Glib::RefPtr<Gnome::Glade::Xml> const& xml);
        static MusicBrainzTagger* Create ();
        virtual ~MusicBrainzTagger () {};

        int run (TrackV const& tracks, TrackV & modify_tracks);

    private:

        class ArtistCR
          : public Gtk::TreeModel::ColumnRecord
        {
          public:
            Gtk::TreeModelColumn<Glib::ustring> name;
            Gtk::TreeModelColumn<Glib::ustring> id; // Artist ID
            ArtistCR ()
            {
              add (name);
              add (id);
            }
        };

        class AlbumCR
          : public Gtk::TreeModel::ColumnRecord
        {
          public:
            Gtk::TreeModelColumn<Glib::ustring> name;
            Gtk::TreeModelColumn<Glib::ustring> id; // Release ID
            AlbumCR ()
            {
              add (name);
              add (id);
            }
        };

        class ReleaseTracksCR
          : public Gtk::TreeModel::ColumnRecord
        {
          public:
            Gtk::TreeModelColumn<MusicBrainzXml::MusicBrainzTrack> track;

            ReleaseTracksCR ()
            {
              add (track);
            }
        };

        class ReleaseEventCR
          : public Gtk::TreeModel::ColumnRecord
        {
          public:
            Gtk::TreeModelColumn<Glib::ustring> event_string;
            ReleaseEventCR ()
            {
              add (event_string);
            }
        };

        class LocalTracksCR
          : public Gtk::TreeModel::ColumnRecord
        {
          public:

            Gtk::TreeModelColumn<Track>     track;
            Gtk::TreeModelColumn<bool>	    modify;
            Gtk::TreeModelColumn<bool>      isTrack;
            Gtk::TreeModelColumn<int>       puidProgress;

            LocalTracksCR ()
            {
              add (modify);
              add (track);
              add (isTrack);
              add (puidProgress);
            }
        };

        enum ColumnId
        {
          COLUMN_NUMBER,
          COLUMN_TITLE,
          COLUMN_DURATION,
          COLUMN_PROGRESS,
        };

        enum OrderingType
        {
          ORDERING_AUTO         = -1,
          ORDERING_NONE         =  0,
          ORDERING_TRACKNUMBERS =  1,
          ORDERING_MATCH        =  2,
        };

        ArtistCR          mCrArtists;
        AlbumCR           mCrAlbums;
        ReleaseEventCR    mCrEvents;
        ReleaseTracksCR   mCrRelease;
        LocalTracksCR     mCrLocal;

        Glib::RefPtr<Gtk::ListStore> m_cb_artist_store;
        Glib::RefPtr<Gtk::ListStore> m_cb_album_store;
        Glib::RefPtr<Gtk::ListStore> m_cb_release_event_store;
        Glib::RefPtr<Gtk::ListStore> m_store_release;
        Glib::RefPtr<Gtk::ListStore> m_store_local;

        ReleaseIdToReleaseMap  m_releases;
        ArtistIdToReleasesMap  m_artist_to_releases_map;

        Gtk::ComboBoxEntry  * m_cb_artist;
        Gtk::ComboBoxEntry  * m_cb_album;
        Gtk::ComboBox       * m_cb_release_date;

        Gtk::Entry          * m_cb_artist_entry;
        Gtk::Entry          * m_cb_album_entry;
        Gtk::Entry          * m_entry_album_id;

        Gtk::TreeView	    * m_view_release;
        Gtk::TreeView       * m_view_local;

        Gtk::ComboBoxEntry  * m_cb_genre;
        Gtk::Entry          * m_cb_genre_entry;
        Gtk::CheckButton    * m_cb_modify_genre;

        Gtk::Image          * m_image;
        Gtk::Button         * b_up;
        Gtk::Button         * b_down;
        Gtk::Button         * b_search;

        TrackV m_tracks;
        TrackV m_tracks_original;

        MusicBrainzXml::MusicBrainzRelease m_release;

        Glib::RefPtr<Gtk::UIManager>    m_ui_manager;
        Glib::RefPtr<Gtk::ActionGroup>  m_actions;
        Glib::RefPtr<Gtk::ToggleAction> m_action_use_filenames;

        RefPixbuf m_defaultcover;
        OrderingType m_current_ordering;
        int m_processed;

        void
        on_artist_changed();

        void
        on_album_changed();

        void
        on_action_search();

        void
        on_action_down ();

        void
        on_action_up ();

        void
        on_action_remove ();

        void
        on_action_relayout (OrderingType order_type_specified);

        void
        on_action_restore ();

        void
        on_action_use_filenames_toggled ();

        void
        on_action_find ();


        bool
        on_popup (GdkEvent* );

        void
        on_modify_toggled (Glib::ustring const& path);

        void
        on_track_cell_edited (Glib::ustring const& strpath, Glib::ustring const& new_text);

        void
        on_local_selection_changed ();


        void
        scan_action_begin ();

        void  
        scan_action_end ();

        boost::optional<ustring>
        scan_file (Gtk::TreeIter & i);


        void
        set_iter_puid_progress (int position, Gtk::TreeIter & i);

        void
        set_processed ();


        void cellDataFuncLocal (Gtk::CellRenderer* cell, Gtk::TreeIter const& iter, ColumnId column);
        void cellDataFuncRelease (Gtk::CellRenderer* cell, Gtk::TreeIter const& iter, ColumnId column);

        void
        populate_matches (MusicBrainzXml::MusicBrainzReleaseV const& releases);

        void
        populate_local_store (OrderingType order_type_specified);
  };
}
#endif
