//  "BMP" Copyright (C) 2003-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 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.

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

#include "bmp/bmp.hh"

#include "debug.hh"
#include "paths.hh"
#include "xml.hh"

#include <boost/format.hpp>
#include <boost/algorithm/string.hpp>

#include "bookmark-manager.hh"

using namespace Glib;

namespace Bmp
{
    BookmarkManager::BookmarkManager ()
    {
    }

    BookmarkManager::~BookmarkManager ()
    {
      save_bookmarks ();
    }

    BookmarkManager::SignalBookmarkLoaded&
    BookmarkManager::signal_bookmark_loaded ()
    {
      return Signals.BookmarkLoaded;
    }

    guint64
    BookmarkManager::add_bookmark (Bookmark const& bookmark)
    {
      m_bookmarks.push_back (bookmark); 
      m_indexmap.insert (std::make_pair (bookmark.m_url, m_bookmarks.size()-1));
      return guint64 (m_bookmarks.size());
    }

    void
    BookmarkManager::save_bookmarks () // private
    {
      xmlDocPtr   doc = xmlNewDoc   (BAD_CAST "1.0");
      xmlNodePtr  bkm = xmlNewNode  (0, BAD_CAST "bookmarks");
      xmlNsPtr    bmp = xmlNewNs    (bkm, BAD_CAST XML_NS_BMP, BAD_CAST "bmp");
      xmlNodePtr  q   = xmlNewChild (bkm, bmp, BAD_CAST "bookmark-list", 0);

      xmlDocSetRootElement (doc, bkm);
      xmlSetProp (bkm, BAD_CAST "version", BAD_CAST "1.0");

      for (BookmarkV::const_iterator i = m_bookmarks.begin(); i != m_bookmarks.end(); ++i)
      {
        static boost::format int_f ("%d");

        xmlNodePtr n = xmlNewChild (q, bmp, BAD_CAST "bookmark", 0);

        xmlSetProp (n, BAD_CAST "title",
                       BAD_CAST i->m_title.c_str());

        xmlSetProp (n, BAD_CAST "href",
                       BAD_CAST i->m_url.c_str());

        xmlSetProp (n, BAD_CAST "id",
                       BAD_CAST (int_f % i->m_id).str().c_str());
      }

      xmlCreateIntSubset (doc,
                          BAD_CAST "bkm",
                          NULL,
                          BAD_CAST "http://bmpx.backtrace.info/dtd/bookmarks-1.dtd" );

      std::string filename = build_filename (BMP_PATH_DATA_DIR, "bookmarks.xml");
      xmlThrDefIndentTreeOutput (1);
      xmlKeepBlanksDefault (0);
      debug("bookmarks","Saving Bookmarks to '%s'.", filename.c_str());
      int ret = xmlSaveFormatFileEnc (filename.c_str(), doc, "utf-8", 1);
      debug("bookmarks","Saved %d characters.", ret);
      xmlFreeDoc (doc);
    }

    void
    BookmarkManager::load_bookmarks () // private
    {
      xmlDocPtr             doc;
      xmlXPathObjectPtr     xo;
      xmlNodeSetPtr         nv;

      std::string filename = build_filename (BMP_PATH_DATA_DIR, "bookmarks.xml");
      if (file_test (filename, FILE_TEST_EXISTS))
      {
        doc = xmlParseFile (filename.c_str());
        if (!doc)
        {
          debug("bookmarks","%s: Couldn't parse %s", G_STRLOC, filename.c_str()); 
          return;
        }

        xo = xpath_query
              (doc,
               BAD_CAST "//bmp:bookmark",
               BAD_CAST "bmp=http://bmpx.backtrace.info/ns/0/");

        nv = xo->nodesetval;

        debug("bookmarks","%s: Got [%d] bookmarks", G_STRLOC, nv->nodeNr);

        for (int n = 0; n < nv->nodeNr; ++n) 
        {
          xmlChar * prop;
          xmlNodePtr node = nv->nodeTab[n];

          prop = xmlGetProp (node, BAD_CAST "title"); 
          std::string title = prop ? (char*)prop : std::string();
          g_free (prop);

          prop = xmlGetProp (node, BAD_CAST "href"); 
          std::string href  = prop ? (char*)prop : std::string();
          g_free (prop);

          prop = xmlGetProp (node, BAD_CAST "id"); 
          int id            = prop ? g_ascii_strtoull ((char*)prop, NULL, 10) : 0;
          g_free (prop);
    
          if( !title.empty() && !href.empty() && (id > 0))
          {
            Bookmark x (title, id, href);
            guint64 id = add_bookmark (x);
            Signals.BookmarkLoaded.emit (x, id);              
          }
        }
      }
    }

} // end namespace Bmp 
