/*
	Twilight Prophecy 3D/Multimedia SDK
	A multi-platform development system for virtual reality and multimedia.

	Copyright (C) 1997-2001 by Twilight 3D Finland Oy Ltd.

	This program is free software; you can redistribute it and/or modify
	it under the terms of the GNU General Public License as published by
	the Free Software Foundation; either version 2 of the License, or
	(at your option) any later version.

	This program is distributed in the hope that it will be useful,
	but WITHOUT ANY WARRANTY; without even the implied warranty of
	MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
	GNU General Public License for more details.

	You should have received a copy of the GNU General Public License
	along with this program; if not, write to the Free Software
	Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA

	Please read the file LICENSE.TXT for additional details.


	source:
		default filestream implementation

	revision history:
		Jan/24/2001 - Jukka Liimatta - initial revision/renaissance build
*/
#include <cstdio>
#include <prcore/prcore.hpp>
using namespace prcore;



//////////////////////////////////////////////////////
// stream implementation                           //
////////////////////////////////////////////////////

	class File : public Stream
	{
		public:
		
		File(FILE* file);
		~File();

		int			Seek(int delta, SeekMode mode);
		int			Read(void* target, int bytes);
		int			Write(const void* source, int bytes);
		int			GetOffset() const;
		int			GetSize() const;
		bool		IsOpen() const;
		bool		IsEOS() const;
		
		private:
		
		FILE*		mpFile;
	};


File::File(FILE* file)
: mpFile(file)
{
}


File::~File()
{
	if ( mpFile )
		fclose( mpFile );
}


int File::Seek(int delta, SeekMode mode)
{
	switch( mode )
	{
		case START:		fseek(mpFile,delta,SEEK_SET); break;
		case CURRENT:	fseek(mpFile,delta,SEEK_CUR); break;
		case END:		fseek(mpFile,delta,SEEK_END); break;
	}
	return ftell(mpFile);
}


int File::Read(void* target, int bytes)
{
	return fread(target,1,bytes,mpFile);
}


int File::Write(const void* source, int bytes)
{
	return fwrite(source,1,bytes,mpFile);
}


int File::GetOffset() const
{
	return ftell(mpFile);
}


int File::GetSize() const
{
	int offset = ftell(mpFile);
	
	fseek(mpFile,0,SEEK_END);
	int size = ftell(mpFile);
	
	fseek(mpFile,offset,SEEK_SET);
	
	return size;
}


bool File::IsOpen() const
{
	return mpFile != NULL;
}


bool File::IsEOS() const
{
	int offset = ftell(mpFile);
	fseek(mpFile,0,SEEK_END);

	int size = ftell(mpFile);
	fseek(mpFile,offset,SEEK_SET);

	return offset >= size;
}


//////////////////////////////////////////////////////
// factory                                         //
////////////////////////////////////////////////////

static int NumEXT()
{
	return 0;
}


static const char* GetEXT(int index)
{
	return "";
}


static bool IsReader()
{
	return true;
}


static bool IsWriter()
{
	return true;
}


static Stream* CreateFile(const char* path, const char* filename, Stream::AccessMode mode, void* password)
{
	FILE* file = NULL;

	switch( mode )
	{
		case Stream::READ:		file = fopen(filename,"rb"); break;
		case Stream::WRITE:		file = fopen(filename,"wb"); break;
		case Stream::READWRITE:	file = fopen(filename,"r+b"); break;
		default: break;
	}
	
	if ( !file )
		return NULL;

	File* stream = new File(file);
	return stream;
}


FileFactory CreateFileFactoryFILE()
{
	FileFactory factory;

	factory.NumEXT = NumEXT;
	factory.GetEXT = GetEXT;
	factory.IsReader = IsReader;
	factory.IsWriter = IsWriter;
	factory.CreateFile = CreateFile;

	return factory;
}
