#ifndef LIBNW_H
#define LIBNW_H
#include <glib.h>
#include <sys/time.h>
#include <id3tag.h>
#include <stdio.h>
#include <sys/stat.h>

/* predeclare the structs */
struct _nwdev;
struct _nwfolder;
struct _nwtrack;
struct _nwfile;

/* API type */
typedef enum {
  NW_GUESS,                 /* try and figure out from context */
  NW_MPLE,                  /* original MPLE 1.1 code */
  NW_MPLE_V2,               /* newer version (NW-HD5 and friends) */
  NW_MAXVERSION,
} nw_api_t;

/* Device structure */
typedef struct _nwdev nw_device_t;
typedef struct _nwfolder nw_folder_t;
typedef struct _nwtrack nw_track_t;

/* filesystem support */
typedef struct _nwfile {
  nw_track_t *tptr;

  FILE *fp;            /* file pointer */
  size_t ptr;          /* ftell pointer */

  /* Write support. There's a little too much for my liking in here... */
  gboolean writing;    /* internal flag to indicate writable file handle */
  gulong bufsize;      /* size of buffer */
  guint8 *buffer;      /* buffered data (while scanning for id3 data) */

  /* very much internal use only, thanks */
  gboolean midframe;
  guint32 framerates[16];
  guint32 frames;
  guint32 frate;
  guint32 flen;
  struct _mp3file *mp3f;
  gboolean format_ok;
} NWFILE;

/* API */
GList *nw_get_devs( gchar * );
nw_device_t *nw_dev_init( gchar *, nw_api_t );
gboolean nw_dev_sync( nw_device_t * );
void nw_dev_free( nw_device_t * );

/* device-specific data */
typedef enum {
  NW_UNDEF = 0,
  NW_BOOLEAN,
  NW_INTEGER,
  NW_STRING,
  NW_POINTER,
  NW_FUNCTION,
  NW_MAXATTRTYPE,
} nw_attrtype_t;

typedef struct _nw_attr_t {
  gchar *name;
  nw_attrtype_t type;
  guint32 size;
  union {
    gboolean gb;
    gchar *gc;
    gpointer ptr;
  } data;
} nw_attr_t;

gboolean nw_set_attr( nw_device_t *, gchar *, nw_attr_t * );
nw_attr_t *nw_get_attr( nw_device_t *, gchar * );

/* convenience */
#define NW_BOOL_ATTR( x ) ( x->data->gb )
#define NW_STR_ATTR( x ) ( x->data.gc )
#define NW_PTR_ATTR( x ) ( x->data.ptr )

gboolean nw_set_boolean( nw_device_t *, gchar *, gboolean );
gboolean nw_get_boolean( nw_device_t *, gchar * );

void nw_set_progress_func( nw_device_t *, void (*progress)( double, void * ));

/* NWFILE support */
NWFILE *nw_fopen( nw_device_t *, guint32, guint32, const gchar *, gchar * );
int nw_fclose( NWFILE * );
int nw_stat( nw_device_t *, guint32, struct stat * );
int nw_fseek( NWFILE *, long, int );
long nw_ftell( NWFILE * );
size_t nw_fread( void *, size_t, size_t, NWFILE * );
size_t nw_fwrite( void *, size_t, size_t, NWFILE * );

/* folder interaction */
GList *nw_parse_directory( nw_device_t * );
GList *nw_get_folderlist( nw_device_t * );
guint32 nw_get_folder( nw_device_t *, gchar *, guint32 );
guint32 nw_add_folder( nw_device_t *, gchar *, guint32 );
gboolean nw_del_folder( nw_device_t *, guint32 );
guint32 nw_mv_folder( nw_device_t *, guint32, guint32 );
guint32 nw_ren_folder( nw_device_t *, guint32, gchar * );
guint32 nw_add_to_folder( nw_device_t *, guint32, nw_track_t *, guint32,
                          guint32 );
/* accessors */
gchar *nw_get_folder_name( nw_folder_t * );
void nw_set_folder_name( nw_folder_t *, gchar * );
GList *nw_get_folder_tracklist( nw_folder_t * );

/* track interaction */
nw_track_t *nw_get_track_ptr( nw_device_t *, guint32 );
guint32 nw_add_track( nw_device_t *, gchar *, nw_track_t *, guint32, guint32 );
gboolean nw_del_track( nw_device_t *, guint32 );
guint32 nw_mv_track( nw_device_t *, guint32, guint32, guint32 );
guint32 nw_ren_track( nw_device_t *, guint32, nw_track_t * );

guint32 nw_track_size( nw_track_t * );
guint32 nw_track_time( nw_track_t * );
guint32 nw_track_frames( nw_track_t * );
void nw_track_free( nw_track_t * );

/* metadata */
nw_track_t *nw_get_metadata_NAME( gchar * );
nw_track_t *nw_get_metadata_FILE( FILE * );

guint16 nw_get_tracknum( nw_track_t * );
id3_utf8_t *nw_get_tag( nw_track_t *, gchar * );
void nw_set_tag( nw_track_t *, gchar *, id3_utf8_t * );

/* for accessing pseudo-tag in nw_track_t */
#define NW_FILENAME "FILENAME"
#define NW_FULLPATH "FULLPATH"

guint8 *nw_get_id3data( nw_track_t *, signed long * );
struct id3_tag *nw_get_id3tag( nw_track_t * );

void libnw_update_metadata( nw_track_t *, struct id3_tag * );

#ifdef DEBUG
#define dprintf(x...) fprintf(x)
#else
#define dprintf(x...)
#endif

#endif

