#include "pfsapi.h"
#include <pfs-1.2/pfs.h>

using namespace pfs;

const char* pfs_TagIteratorGetNext(pfs_TagIterator self) 
{
    return ((TagIterator*)self)->getNext();
}

int pfs_TagIteratorHasNext(pfs_TagIterator self)
{
    return ((TagIterator*)self)->hasNext();
}

const char *pfs_TagContainerGetString(pfs_TagContainer self, const char* tagName) 
{
    return ((TagContainer*) self)->getString(tagName);
}

void pfs_TagContainerSetString(pfs_TagContainer self, const char* tagName, const char* tagValue) 
{
    ((TagContainer*) self)->setString(tagName, tagValue);
}

void pfs_TagContainerRemoveTag(pfs_TagContainer self, const char* tagName) 
{
    ((TagContainer*) self)->removeTag(tagName);
}

pfs_TagIterator pfs_TagContainerGetIterator (pfs_TagContainer self) 
{
    TagIteratorPtr iter = (((TagContainer*) self)->getIterator());
    TagIterator *ptr = iter.release();
    return (void*) ptr; 
}

void pfs_freeTagIterator(pfs_TagIterator titer) {
    delete (TagIteratorPtr*) titer;
}

int pfs_Array2DGetCols(pfs_Array self) 
{
    return ((Array2D*)self)->getCols();
}

int pfs_Array2DGetRows(pfs_Array self)
{
    return ((Array2D*)self)->getRows();
}

float pfs_Array2DGet(pfs_Array self, int col, int row) 
{
    return ((Array2D*)self)->operator()(col,row);
}

float pfs_Array2DSet(pfs_Array self, int col, int row, float value)
{
    ((Array2D*)self)->operator()(col,row) = value;
    return value;
}

float pfs_Array1DGet(pfs_Array self, int ix) 
{
    return    (*((Array2D*)self))(ix);
}
float pfs_Array1DSet(pfs_Array self, int ix, float value)
{
    (*((Array2D*)self))(ix) = value;
    return value;
}

int pfs_ChannelGetWidth(pfs_Channel self) 
{
    return ((Channel*)self)->getWidth();
}

int pfs_ChannelGetHeight(pfs_Channel self) 
{
    return ((Channel*)self)->getHeight();
}
const char *pfs_ChannelGetName(pfs_Channel self) 
{
    return ((Channel*)self)->getName();
}
pfs_TagContainer pfs_ChannelGetTags(pfs_Channel self) 
{
    return (void*)(((Channel*)self)->getTags());
}

float* pfs_ChannelGetRawData(pfs_Channel self) 
{
    return ((Channel*)self)->getRawData();
}

pfs_Channel pfs_ChannelIteratorGetNext(pfs_ChannelIterator self) 
{
    return (void*)(((ChannelIterator*)self)->getNext());
}

int pfs_ChannelIteratorHasNext(pfs_ChannelIterator self)
{
    return ((ChannelIterator*)self)->hasNext();
}

int pfs_FrameGetWidth(pfs_Frame self) 
{
    return ((Frame*)self)->getWidth();
}
int pfs_FrameGetHeight(pfs_Frame self) 
{
    return ((Frame*)self)->getHeight();
}

void pfs_FrameGetXYZChannels(pfs_Frame self, pfs_Channel *xout, pfs_Channel *yout, pfs_Channel *zout)
{
    Channel *x, *y, *z;
    ((Frame*)self)->getXYZChannels(x,y,z);
    *xout = (void*)x;
    *yout = (void*)y;
    *zout = (void*)z;
}

void pfs_FrameCreateXYZChannels(pfs_Frame self, pfs_Channel *xout, pfs_Channel *yout, pfs_Channel *zout)
{
    Channel *x, *y, *z;
    ((Frame*)self)->createXYZChannels(x,y,z);
    *xout = (void*)x;
    *yout = (void*)y;
    *zout = (void*)z;
}

pfs_Channel pfs_FrameGetChannel(pfs_Frame self, const char* name)
{
    return (void*)(((Frame*)self)->getChannel(name));
}

pfs_Channel pfs_FrameCreateChannel(pfs_Frame self, const char* name)
{
    return (void*)(((Frame*)self)->createChannel(name));
}

void pfs_FrameRemoveChannel(pfs_Frame self, pfs_Channel channel) 
{
    ((Frame*)self)->removeChannel((Channel*)channel);
}

pfs_ChannelIterator pfs_FrameGetChannelIterator (pfs_Frame self) 
{
    ChannelIteratorPtr iter = (((Frame*) self)->getChannelIterator());
    ChannelIterator *ptr = iter.release();
    return (void*) ptr; 
}

void pfs_freeChannelIterator(pfs_ChannelIterator i) { 
    delete (ChannelIteratorPtr*)i;
}

pfs_TagContainer pfs_FrameGetTags(pfs_Frame self)
{
    return (void*)(((Frame*)self)->getTags());
}

pfs_DOMIO pfs_newDOMIO() {
    return (void*)(new DOMIO());
}

void pfs_deleteDOMIO(pfs_DOMIO self) {
    delete ((DOMIO*)self);
}

pfs_Frame pfs_DOMIOCreateFrame(pfs_DOMIO self, int width, int height) {
    return (void*)(((DOMIO*)self)->createFrame(width,height));
}

pfs_Frame pfs_DOMIOReadFrame(pfs_DOMIO self, FILE* inputStream) {
    return (void*)(((DOMIO*)self)->readFrame(inputStream));
}

void pfs_DOMIOWriteFrame(pfs_DOMIO self, pfs_Frame frame, FILE* outputStream) {
    ((DOMIO*)self)->writeFrame((Frame*)frame, outputStream);
}

void pfs_DOMIOFreeFrame(pfs_DOMIO self, pfs_Frame frame) {
    ((DOMIO*)self)->freeFrame((Frame*)frame);
}

pfs_FrameFile pfs_newFrameFile(FILE *fh, const char *fileName) {
    return (void*)(new FrameFile(fh,fileName));
}

FILE *pfs_FrameFileGetFileHandle(pfs_FrameFile self) {
    return ((FrameFile*)self)->fh;
}

const char *pfsFrameFileGetFileName(pfs_FrameFile self) {
    return ((FrameFile*)self)->fileName;
}

pfs_FrameFileIterator pfs_newFrameFileIterator(int *argc, char **argv, const char *fopenMode, const char *fileNamePrefix, FILE *stdinout, const char *optstring, const void *getopt_long) 
{
    return (void*)( new FrameFileIterator(*argc,argv,fopenMode,fileNamePrefix,stdinout,optstring,(option *)getopt_long));
}

pfs_FrameFile pfs_FrameFileIteratorGetNextFrameFile(pfs_FrameFileIterator self)
{
    return (void*) new FrameFile((((FrameFileIterator*)self)->getNextFrameFile()));
}

void pfs_FrameFileIteratorCloseFrameFile(pfs_FrameFileIterator self, pfs_FrameFile frameFile) 
{
    ((FrameFileIterator*)self)->closeFrameFile(*((FrameFile*)frameFile));
}


