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

#include <cstring>

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

#include "src/database.hh"
#include "src/uri.hh"
#include "src/util-string.hh"
#include "src/util-file.hh"
#include "src/vfs.hh"

using namespace Glib;
using namespace Bmp;

namespace Bmp
{
  namespace VFS
  {
      class PluginContainerM3U
          : public Bmp::VFS::PluginContainerBase
      {
        public:

          virtual bool
          can_process (ustring const& uri)
          {
            URI u (uri);
            return Util::str_has_suffix_nocase (u.path, ".m3u");
          }

          virtual void 
          handle_read	(Handle & handle, VUri & list) throw (ProcessingError)
          {
            char **uris;
            int    n = 0;

            if (!handle.get_buffer())
            {
              throw ProcessingError ("Empty Buffer"); 
            }

            uris = g_uri_list_extract_uris ((const char*)handle.get_buffer());

            std::string pathname;

            try{
              pathname = path_get_dirname (filename_from_uri (handle.get_uri()));
              }
            catch (Glib::ConvertError & cxe)
              {
                throw ProcessingError ("Invalid Handle URI"); 
              }
          
            while (uris[n])
            {
              char *uri = uris[n];

              //Strip leading spaces/tabs
              while ((uri[0] == ' ') || (uri[0] == '\t') || (uri[0] == '<')) uri++;

              //Skip comments, extended information or null lenght uris
              if ((uri[0] == '#') || (uri[0] == '\0'))
              {
                n++;
                continue;
              }

              if (path_is_absolute (uri) && file_test (uri, FILE_TEST_EXISTS))
              {
                try{
                  list.push_back (filename_to_uri (uri));
                  }
                catch (ConvertError& cxe) 
                  {
                    throw ProcessingError ((boost::format (_("Couldn't uri %s to name")) % uri).str());
                  }
              }
              else		
              {
                if (!g_ascii_strncasecmp ("http:", uri, 5))
                {
                  list.push_back (uri);
                }
                else try
                {
                  std::string name = build_filename (pathname, uri);
                  if (file_test (name, FILE_TEST_EXISTS))
                  {
                    list.push_back (filename_to_uri (name));
                  }
                }
                catch (ConvertError& cxe)
                {
                  throw ProcessingError ((boost::format (_("Couldn't process uri %s")) % uri).str());
                }
              }
              n++;
            }

            g_strfreev (uris);
          }

          virtual bool
          can_write ()
          {
            return true;
          }

          virtual void
          handle_write (Handle & handle, TrackV const& list) throw (ProcessingError)
          {
            std::stringstream out;
            std::string outstr;

            out << "#EXTM3U\n";

            for (TrackV::const_iterator i = list.begin (); i != list.end (); ++i)
            {
              Track const& track (i.operator*());

              if (!track.artist || !track.album || !track.title)
                continue;

              out << "#EXTINF:"
                  << track.artist.get()
                  << "," 
                  << track.album.get() 
                  << " - " 
                  << track.title.get() << "\n";

              URI uri (track.location.get());
              if (uri.get_protocol() != URI::PROTOCOL_FILE)
                {
                  out << (track.location.get()) << "\n";
                }
              else	    
                {
                  try{
                    out << filename_from_uri (track.location.get()) << "\n";
                    }
                  catch (...)
                    {
                      throw ProcessingError ((boost::format (_("Couldn't convert uri %s to name")) % (track.location.get())).str());
                    }
                }
            }
            outstr = out.str(); 
            handle.set_buffer((const unsigned char *)strdup(outstr.c_str()), strlen(outstr.c_str())+1);
          }

          virtual Bmp::VFS::ExportData const&
          get_export_data ()
          {
            static Bmp::VFS::ExportData export_data ("M3U Playlist", "m3u"); 
            return export_data;
          }
      };
  }
}
  
extern "C" VFS::PluginContainerBase* plugin_create ()
{
  return new VFS::PluginContainerM3U;
}

extern "C" void plugin_delete (VFS::PluginContainerM3U* p)
{
  delete p;
}
