#ifndef ka_input_h
#define ka_input_h

#include "inttypes.h"
#include "ka_buffer.h"
#include "ka_error.h"

#include <stdio.h>

typedef struct ka_input_s ka_input_t;

typedef void (*ka_input_FNdelete)(ka_input_t** ppInput);
typedef int  (*ka_input_FNclose)(ka_input_t* pInput);
typedef uint64_t (*ka_input_FNgetLen)(ka_input_t* pInput);
typedef uint64_t (*ka_input_FNtell)(ka_input_t* pInput);
typedef int  (*ka_input_FNseek)(ka_input_t* pInput, uint64_t pos);
typedef int  (*ka_input_FNhasBytes)(ka_input_t* pInput, int nbr);
typedef int  (*ka_input_FNskip)(ka_input_t* pInput, int nbr);
typedef int  (*ka_input_FNread)(ka_input_t* pInput, void* ptr, int nbr);
typedef int  (*ka_input_FNbuffer)(ka_input_t* pInput, ka_buffer_t*, int* pdone);

typedef struct
{
  const char* name;
  ka_input_FNdelete   FNdelete;
  ka_input_FNclose    FNclose;
  ka_input_FNgetLen   FNgetLen;
  ka_input_FNtell     FNtell;
  ka_input_FNseek     FNseek;
  ka_input_FNhasBytes FNhasBytes;
  ka_input_FNskip     FNskip;
  ka_input_FNread     FNread;
  ka_input_FNbuffer   FNbuffer;
} kav_input_t;

struct ka_input_s
{
  const kav_input_t* vptr;
  ka_error_t* pErrorBlock;
};

void ka_delete_input(ka_input_t**);
uint64_t ka_input_getLen(ka_input_t* f);

int ka_input_close(ka_input_t*);
uint64_t ka_input_tell(ka_input_t*);
int ka_input_seek(ka_input_t*, uint64_t ps);
// 1 ok, 0 less than < nbr, -1 waiting
int ka_input_hasBytes(ka_input_t*, int nbr);
int ka_input_skip(ka_input_t*, int nbr);
int ka_input_read(ka_input_t*, void* ptr, int nbr);
int ka_input_buffer(ka_input_t*, ka_buffer_t*, int* pdone);

ka_input_t* ka_new_infile(ka_error_t* pErrorBlock);
int ka_infile_open(ka_input_t*, const char* inputname);

#endif
