/*
 * gbp_reader_stdio.cpp
 *
 */



#include "ghost_playback.h"

#define __USE_MINGW_ANSI_STDIO 1

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <errno.h>

#include <stdarg.h>

#include <inttypes.h>

#include <windows.h>

class GrifoPlaybackReaderStdin: public GrifoPlaybackStreamReader
{
public:
	const char* file_name;
	const char* node_name;
	FILE* fd;
	bool auto_rewind;
	bool fail;

	GrifoPlaybackReaderStdin():
		file_name(0),
		node_name(0),
		fd(0),
		auto_rewind(false),
		fail(false)
	{
	}

	void logError(const char* op, ...)
	{
		va_list args;
		va_start(args, op);

		printf("%s:%lld: ", node_name, currentPosition());
		vprintf(op, args);
		if (errno)
		{
			printf(" %s", strerror(errno));
			errno=0;
		}
		printf("\n");
		va_end(args);
	}


	const char* streamName() const
	{
		return node_name;
	}

	bool streamOpen(const char* name) override
	{
		setStreamName(name);
		fd=fopen64(file_name, "rb");
		fail=(fd==0);
		logError("streamOpen()");

		if (fail)
		{
			static char msg_buffer[2048];

			snprintf(msg_buffer, sizeof msg_buffer, "Error: %s - ", strerror(errno));

			/*int r=*/MessageBoxA(0, msg_buffer, "PLayback - Error", MB_ICONWARNING);
		}

		setvbuf(fd, 0, _IOFBF, 128*1024);

		return !fail;
	}

	bool isOpen() override
	{
		return !fail && (fd);
	}

	void setAutorewind(bool ena)
	{
		auto_rewind=ena;
	}

	void setStreamName(const char* name) override
	{
		file_name=strdup(name);
		char* p=strrchr(name, '\\');
		if (p==0)
			p=strrchr(name, '/');
		if (p)
			node_name=&p[1];
	}

	int read(void* datum, unsigned int size)
	{
		if (!datum)
			return -1;
		int n=fread(datum, 1, size, fd)<size ? -1 : 0;
		if (n)
		{
			if (!fail && auto_rewind)
			{
				rewind();
				n=fread(datum, 1, size, fd)<size ? -1 : 0;
				if (n)
				{
					fail=true;
				}
			}
		}
		return n; //fread(datum, 1, size, fd)<size ? -1 : 0;
	}

	template<typename T_> int readDatum(T_* datum) { return read(datum, sizeof *datum);}

	stream_offset_t currentPosition() const override
	{
		return ftello64(fd);
	}

	int setCurrentPosition(stream_offset_t pos)
	{
		return fseeko64(fd, pos, SEEK_SET);
	}

	int moveCurrentPosition(stream_offset_t offset) override
	{
		return fseeko64(fd, offset, SEEK_CUR);
	}

	bool eof() override
	{
		return feof(fd)==0 ? false : true;
	}

	virtual void rewind()
	{
		setCurrentPosition(0);
	}

	virtual bool error() { return ferror(fd)==0 ? false : true;}


	~GrifoPlaybackReaderStdin()
	{
		if (fd)
			fclose(fd);
	}

};


GrifoPlaybackStreamReader* GrifoPlaybackCreateStdioReader()
{
	static GrifoPlaybackReaderStdin* theInstance=new GrifoPlaybackReaderStdin;
	return theInstance;
}

