/******************************************************************************
 *
 *  rawfiles.cpp -	code for class 'RawFiles'- a module that reads and writes
 *			entries each to separate files on the filesystem
 *
 * $Id: rawfiles.cpp 3821 2020-11-02 18:33:02Z scribe $
 *
 * Copyright 1998-2013 CrossWire Bible Society (http://www.crosswire.org)
 *	CrossWire Bible Society
 *	P. O. Box 2528
 *	Tempe, AZ  85280-2528
 *
 * 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 version 2.
 *
 * 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.
 *
 */

#include <ctype.h>
#include <stdio.h>
#include <fcntl.h>

#include <rawverse.h>
#include <rawfiles.h>
#include <filemgr.h>
#include <versekey.h>
#include <sysdata.h>

SWORD_NAMESPACE_START

 /******************************************************************************
 * RawFiles Constructor - Initializes data for instance of RawFiles
 *
 * ENT:	iname - Internal name for module
 *	idesc - Name to display to user for module
 *	idisp	 - Display object to use for displaying
 */

RawFiles::RawFiles(const char *ipath, const char *iname, const char *idesc, SWDisplay *idisp, SWTextEncoding enc, SWTextDirection dir, SWTextMarkup mark, const char* ilang) : RawVerse(ipath, FileMgr::RDWR), SWCom(iname, idesc, idisp, enc, dir, mark, ilang)
{
}


/******************************************************************************
 * RawFiles Destructor - Cleans up instance of RawFiles
 */

RawFiles::~RawFiles()
{
}


/** Is the module writable? :)
* @return yes or no
*/
bool RawFiles::isWritable() const {
	return ((idxfp[0]->getFd() > 0) && ((idxfp[0]->mode & FileMgr::RDWR) == FileMgr::RDWR));
}


/******************************************************************************
 * RawFiles::getRawEntry	- Retrieve the unprocessed entry contents at
 *					the current key position of this module
 *
 * RET: entry contents
 */

SWBuf &RawFiles::getRawEntryBuf() const {
	FileDesc *datafile;
	long  start = 0;
	unsigned short size = 0;
	const VerseKey *key = &getVerseKey();

	findOffset(key->getTestament(), key->getTestamentIndex(), &start, &size);

	entryBuf = "";
	if (size) {
		SWBuf tmpbuf = path;
		tmpbuf += '/';
		readText(key->getTestament(), start, size, entryBuf);
		tmpbuf += entryBuf;
		entryBuf = "";
		datafile = FileMgr::getSystemFileMgr()->open(tmpbuf.c_str(), FileMgr::RDONLY);
		if (datafile->getFd() > 0) {
			size = datafile->seek(0, SEEK_END);
			char *tmpBuf = new char [ size + 1 ];
			memset(tmpBuf, 0, size + 1);
			datafile->seek(0, SEEK_SET);
			datafile->read(tmpBuf, size);
			entryBuf = tmpBuf;
			delete [] tmpBuf;
//			preptext(entrybuf);
		}
		FileMgr::getSystemFileMgr()->close(datafile);
	}
	return entryBuf;
}


/******************************************************************************
 * RawFiles::setEntry(char *)- Update the module's current key entry with
 *				provided text
 */

void RawFiles::setEntry(const char *inbuf, long len) {
	FileDesc *datafile;
	long  start;
	unsigned short size;
	VerseKey *key = &getVerseKey();

	len = (len<0)?strlen(inbuf):len;

	findOffset(key->getTestament(), key->getTestamentIndex(), &start, &size);

	if (size) {
		SWBuf tmpbuf;
		entryBuf = path;
		entryBuf += '/';
		readText(key->getTestament(), start, size, tmpbuf);
		entryBuf += tmpbuf;
	}
	else {
		SWBuf tmpbuf;
		entryBuf = path;
		entryBuf += '/';
		tmpbuf = getNextFilename();
		doSetText(key->getTestament(), key->getTestamentIndex(), tmpbuf);
		entryBuf += tmpbuf;
	}
	datafile = FileMgr::getSystemFileMgr()->open(entryBuf, FileMgr::CREAT|FileMgr::WRONLY|FileMgr::TRUNC);
	if (datafile->getFd() > 0) {
		datafile->write(inbuf, len);
	}
	FileMgr::getSystemFileMgr()->close(datafile);
}


/******************************************************************************
 * RawFiles::linkEntry(SWKey *)- Link the modules current key entry with
 *				another module entry
 *
 * RET: *this
 */

void RawFiles::linkEntry(const SWKey *inkey) {

	long  start;
	unsigned short size;
	const VerseKey *key = &getVerseKey();

	findOffset(key->getTestament(), key->getTestamentIndex(), &start, &size);

	if (size) {
		SWBuf tmpbuf;
		readText(key->getTestament(), start, size + 2, tmpbuf);

		key = &getVerseKeyConst(inkey);
		doSetText(key->getTestament(), key->getTestamentIndex(), tmpbuf.c_str());
	}
}


/******************************************************************************
 * RawFiles::deleteEntry	- deletes this entry
 *
 * RET: *this
 */

void RawFiles::deleteEntry() {
	VerseKey *key = &getVerseKey();
	doSetText(key->getTestament(), key->getTestamentIndex(), "");
}


/******************************************************************************
 * RawFiles::getNextfilename - generates a valid filename in which to store
 *				an entry
 *
 * RET: filename
 */

const char *RawFiles::getNextFilename() {
	static SWBuf incfile;
	SW_u32 number = 0;
	FileDesc *datafile;

	incfile.setFormatted("%s/incfile", path);
	datafile = FileMgr::getSystemFileMgr()->open(incfile, FileMgr::RDONLY);
	if (datafile->getFd() != -1) {
		if (datafile->read(&number, 4) != 4) number = 0;
		number = swordtoarch32(number);
	}
	number++;
	FileMgr::getSystemFileMgr()->close(datafile);
	
	datafile = FileMgr::getSystemFileMgr()->open(incfile, FileMgr::CREAT|FileMgr::WRONLY|FileMgr::TRUNC);
	incfile.setFormatted("%.7d", number-1);

	number = archtosword32(number);
	datafile->write(&number, 4);

	FileMgr::getSystemFileMgr()->close(datafile);
	return incfile;
}


char RawFiles::createModule(const char *path) {
	char *incfile = new char [ strlen (path) + 16 ];

	SW_u32 zero = 0;
	zero = archtosword32(zero);

	FileDesc *datafile;

	sprintf(incfile, "%s/incfile", path);
	datafile = FileMgr::getSystemFileMgr()->open(incfile, FileMgr::CREAT|FileMgr::WRONLY|FileMgr::TRUNC);
	delete [] incfile;
	datafile->write(&zero, 4);
	FileMgr::getSystemFileMgr()->close(datafile);

    return RawVerse::createModule (path);
}



SWORD_NAMESPACE_END
