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

#include <iostream>

#include <gtkmm.h>
#include <glibmm/i18n.h>
#include <libglademm.h>

#include <boost/format.hpp>

#include "paths.hh"
#include "stock.hh"

#include "library.hh"

#include "dialog-progress.hh"
#include "ui-tools.hh"

namespace
{
  static boost::format format_progress_text  ("%d / %d");
  static boost::format format_progress_done1 (N_("Done: %d files total, %d added"));
  static boost::format format_progress_done2 (N_("Done: %d files total, %d added, %d updated"));
}

namespace Bmp
{
      ProgressDialog*
      ProgressDialog::create ()
      {
        char const* path = BMP_GLADE_DIR G_DIR_SEPARATOR_S "dialog-progress.glade";

        Glib::RefPtr<Gnome::Glade::Xml> xml = Gnome::Glade::Xml::create (path);

        ProgressDialog* dialog = 0;
        xml->get_widget_derived ("progress_dialog", dialog);

        return dialog;
      }

      void
      ProgressDialog::on_cancel_clicked ()
      {
        signal_cancel_.emit ();
      }

      ProgressDialog::ProgressDialog (BaseObjectType*                        obj,
                                      Glib::RefPtr<Gnome::Glade::Xml> const& xml)
        : Gtk::Dialog (obj),
          m_ref_xml   (xml)
      {
        dynamic_cast<Gtk::Button*> (m_ref_xml->get_widget ("progress-cancel"))->signal_clicked ().connect
          (sigc::mem_fun (this, &ProgressDialog::on_cancel_clicked));

        m_ref_xml->get_widget("progressbar", m_progress);

        m_progress->set_fraction (0.);
        m_progress->set_text ((format_progress_text % 0 % 0).str());

        m_store = Gtk::ListStore::create (columns);

        Gtk::TreeViewColumn*     column = 0;
        Gtk::CellRendererPixbuf* cell_pixbuf = 0;
        Gtk::CellRendererText*   cell_text = 0;

        m_ref_xml->get_widget("treeview", m_view);

        cell_pixbuf = Gtk::manage (new Gtk::CellRendererPixbuf ());
        m_view->append_column ("", *cell_pixbuf);
        column = m_view->get_column (0);
        column->set_cell_data_func (*cell_pixbuf,
          sigc::mem_fun (this, &ProgressDialog::cell_data_func_state));
        column->set_resizable (false);
        column->set_sort_column (0);

        cell_text = Gtk::manage (new Gtk::CellRendererText ());
        m_view->append_column (_("State"), *cell_text);
        column = m_view->get_column (1);
        column->add_attribute (*cell_text, "text", 1);
        column->set_sort_column (1);

        cell_text = Gtk::manage (new Gtk::CellRendererText ());
        m_view->append_column (_("Filename"), *cell_text);
        column = m_view->get_column (2);
        column->add_attribute (*cell_text, "text", 2);
        column->set_sort_column (2);
        m_view->set_model (m_store);

        Util::window_set_icon_list (*this, "player");
        show ();
      }

      void
      ProgressDialog::cell_data_func_state (Gtk::CellRenderer*   _cell,
                                            Gtk::TreeIter const& m_iter)
      {
        switch ((*m_iter)[columns.addop])
        {
          case LIBRARY_ADD_ERROR:
            dynamic_cast<Gtk::CellRendererPixbuf *>(_cell)->property_pixbuf() =
              render_icon (Gtk::StockID (BMP_STOCK_ERROR), Gtk::ICON_SIZE_SMALL_TOOLBAR);
            return;

          case LIBRARY_ADD_IMPORT:
            dynamic_cast<Gtk::CellRendererPixbuf *>(_cell)->property_pixbuf() =
              render_icon (Gtk::StockID (BMP_STOCK_OK), Gtk::ICON_SIZE_SMALL_TOOLBAR);
            return;

          case LIBRARY_ADD_UPDATE:
            dynamic_cast<Gtk::CellRendererPixbuf *>(_cell)->property_pixbuf() =
              render_icon (Gtk::StockID (BMP_STOCK_APPROVE_PARTIAL), Gtk::ICON_SIZE_SMALL_TOOLBAR);
            return;

          case LIBRARY_ADD_NOCHANGE:
            break;

          case LIBRARY_ADD_NOOP:
            break; // FIXME: When exactly can this happen? 
        }
      }

      void
      ProgressDialog::set_progress (guint64 n_items,
                                    guint64 nth_item)
      {
        m_progress->set_fraction (double (nth_item) / n_items);
        m_progress->set_text ((format_progress_text % nth_item % n_items).str ());

        while (gtk_events_pending())
          gtk_main_iteration ();
      }

      int
      ProgressDialog::done (guint64 n_items_added,
                            guint64 n_items_updated,
                            guint64 n_items_total,
                            bool    disp_undo)
      {
        m_progress->set_fraction (1.);

        if (n_items_updated == 0)
          m_progress->set_text (_((format_progress_done1 % n_items_total % n_items_added).str().c_str()));
        else
          m_progress->set_text (_((format_progress_done2 % n_items_total % n_items_added % n_items_updated)
                                .str().c_str()));

        set_response_sensitive (Gtk::RESPONSE_CLOSE, true);

        if (disp_undo)
        {
          dynamic_cast<Gtk::Button*> (m_ref_xml->get_widget ("progress-cancel"))->set_use_stock ();
          dynamic_cast<Gtk::Button*> (m_ref_xml->get_widget ("progress-cancel"))->set_label (GTK_STOCK_UNDO);
        }
        else
        {
          set_response_sensitive (Gtk::RESPONSE_CANCEL, true);
        }

        if ((n_items_total != (n_items_added + n_items_updated)) && (n_items_updated != 0) && (n_items_added != 0))
        {
          m_ref_xml->get_widget ("hbox-warning")->show_all();
        }

        int response = Gtk::Dialog::run();

        set_response_sensitive (Gtk::RESPONSE_CLOSE, false);
        set_response_sensitive (Gtk::RESPONSE_CANCEL, false);

        return response;
      }

      void
      ProgressDialog::add_file (AddOp       op,
                                std::string const& name,
                                std::string const& state)
      {
        Glib::ustring utf8_filename;

        try{
          utf8_filename = Glib::filename_to_utf8(name);
          }
        catch (Glib::ConvertError& cxe)
          {
            g_log (G_LOG_DOMAIN, G_LOG_LEVEL_WARNING, "%s: Error converting filename %s to UTF-8 for display", G_STRFUNC, name.c_str());
            return;
          }

        Gtk::TreeIter m_iter (m_store->append());
        (*m_iter)[columns.addop]  = op;
        (*m_iter)[columns.state]  = state;
        (*m_iter)[columns.name]   = utf8_filename;
      }
}
