#ifndef __GSK_URL_DOWNLOAD_H_
#define __GSK_URL_DOWNLOAD_H_

typedef struct _GskUrlDownloadInfo GskUrlDownloadInfo;
typedef struct _GskUrlDownloadFuncs GskUrlDownloadFuncs;
typedef struct _GskUrlDownloadIface GskUrlDownloadIface;
typedef struct _GskUrlDownload GskUrlDownload;

#include "gskurl.h"
#include "../gskmainloop.h"
#include "../gskinterface.h"

GskInterfaceType gsk_url_download_iface_get_type ();
#define GSK_TYPE_URL_DOWNLOAD_IFACE 		(gsk_url_download_iface_get_type ())
#define GSK_IS_URL_DOWNLOAD(obj)		GSK_INTERFACE_TEST (obj, GSK_TYPE_URL_DOWNLOAD_IFACE)
#define GSK_URL_DOWNLOAD(obj)		GSK_INTERFACE_CAST (GskUrlDownload, obj, GSK_TYPE_URL_DOWNLOAD_IFACE)
#define GSK_URL_DOWNLOAD_GET_IFACE(obj)	GSK_INTERFACE_GET_IFACE (GskUrlDownloadIface, obj, GSK_TYPE_URL_DOWNLOAD_IFACE)

typedef enum
{
  /* permission denied errors */
  GSK_URL_DOWNLOAD_ERR_ACCESS,

  /* socket/file io errors */
  GSK_URL_DOWNLOAD_ERR_IO,

  /* not found errors */
  GSK_URL_DOWNLOAD_ERR_NOT_FOUND,

  /* temporarily unavailable */
  GSK_URL_DOWNLOAD_ERR_TEMP_UNAVAILABLE,

  /* remote errors for which we got a failure message: eg `500 Server Error' */
  GSK_URL_DOWNLOAD_ERR_REMOTE,

  /* other internal errors of an undetermined nature */
  GSK_URL_DOWNLOAD_ERR_INTERNAL

  /* NOTE: there's no redirect: follow symlinks and redirects
           in the downloader implementation. */

} GskUrlDownloadErr;
const char *gsk_url_download_err_str (GskUrlDownloadErr err_code);

struct _GskUrlDownloadInfo
{
  guint         has_content_length : 1;
  guint64       content_length;
};

struct _GskUrlDownloadFuncs 
{
  /* The functions will be called exactly in this order:

         start?
	 process*
	 error | end
	 destroy

     `process*' means process may be called 0 or more times, like a regex.
   */

  gboolean   (*start)   (GskUrlDownloadInfo   *info,
			 gpointer              func_data);
  gboolean   (*process) (gconstpointer         input_data,
			 guint                 input_length,
			 gpointer              func_data);
  void       (*error)   (GskUrlDownloadErr     err_code,
			 gpointer              func_data);
  void       (*end)     (gpointer              func_data);
  void       (*destroy) (gpointer              func_data);
};

struct _GskUrlDownloadIface
{
  gboolean   (*start)   (GskUrlDownload       *url_download,
			 GskUrl               *url,
			 GskMainLoop          *main_loop,
			 GskUrlDownloadFuncs  *funcs,
			 gpointer              func_data);
  gboolean   (*cancel)  (GskUrlDownload       *download);
};

/* Downloading urls */
GskUrlDownload *gsk_url_download_start      (GskUrl          *url,
			                     GskMainLoop     *main_loop,
			                     GskUrlDownloadFuncs *funcs,
			                     gpointer         func_data);
void            gsk_url_download_cancel     (GskUrlDownload  *download);

/* register http, ftp, and file uri types */
void            gsk_url_download_init       ();

/* registering new schemes */
void            gsk_url_download_scheme_register (GskUrlScheme     scheme,
						  GtkType          impl_type);

#endif
