/******************************************************************************
 *  rawtext.cpp - code for class 'RawGenBook'- a module that reads raw text files:
 *		  ot and nt using indexs ??.bks ??.cps ??.vss
 */


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

#include <rawgenbook.h>
#include <rawstr.h>
#include <utilstr.h>
#include <filemgr.h>
#include <sysdata.h>
#include <treekeyidx.h>
#include <versetreekey.h>

SWORD_NAMESPACE_START

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

RawGenBook::RawGenBook(const char *ipath, const char *iname, const char *idesc, SWDisplay *idisp, SWTextEncoding enc, SWTextDirection dir, SWTextMarkup mark, const char* ilang, const char *keyType)
		: SWGenBook(iname, idesc, idisp, enc, dir, mark, ilang) {

	char *buf = new char [ strlen (ipath) + 20 ];

	path = 0;
	stdstr(&path, ipath);
	verseKey = !strcmp("VerseKey", keyType);

	if (verseKey) Type("Biblical Texts");

	if ((path[strlen(path)-1] == '/') || (path[strlen(path)-1] == '\\'))
		path[strlen(path)-1] = 0;

	delete key;
	key = CreateKey();


	sprintf(buf, "%s.bdt", path);
	bdtfd = FileMgr::getSystemFileMgr()->open(buf, FileMgr::RDWR, true);

	delete [] buf;

}


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

RawGenBook::~RawGenBook() {

	FileMgr::getSystemFileMgr()->close(bdtfd);

	if (path)
		delete [] path;

}


bool RawGenBook::isWritable() {
	return ((bdtfd->getFd() > 0) && ((bdtfd->mode & FileMgr::RDWR) == FileMgr::RDWR));
}


/******************************************************************************
 * RawGenBook::getRawEntry	- Returns the correct verse when char * cast
 *					is requested
 *
 * RET: string buffer with verse
 */

SWBuf &RawGenBook::getRawEntryBuf() {

	__u32 offset = 0;
	__u32 size = 0;

	TreeKey *key = 0;
	SWTRY {
		key = SWDYNAMIC_CAST(TreeKey, (this->key));
	}
	SWCATCH ( ... ) {}

	if (!key) {
		VerseTreeKey *tkey = 0;
		SWTRY {
			tkey = SWDYNAMIC_CAST(VerseTreeKey, (this->key));
		}
		SWCATCH ( ... ) {}
		if (tkey) key = tkey->getTreeKey();
	}

	if (!key) {
		key = (TreeKeyIdx *)CreateKey();
		(*key) = *(this->key);
	}

	int dsize;
	key->getUserData(&dsize);
	entryBuf = "";
	if (dsize > 7) {
		memcpy(&offset, key->getUserData(), 4);
		offset = swordtoarch32(offset);

		memcpy(&size, key->getUserData() + 4, 4);
		size = swordtoarch32(size);

		entrySize = size;        // support getEntrySize call

		entryBuf.setFillByte(0);
		entryBuf.setSize(size);
		bdtfd->seek(offset, SEEK_SET);
		bdtfd->read(entryBuf.getRawData(), size);

		rawFilter(entryBuf, 0);	// hack, decipher
		rawFilter(entryBuf, key);

//		   if (!isUnicode())
			RawStr::prepText(entryBuf);
	}

	if (key != this->key) // free our key if we created a VerseKey
		delete key;

	return entryBuf;
}


void RawGenBook::setEntry(const char *inbuf, long len) {

	__u32 offset = archtosword32(bdtfd->seek(0, SEEK_END));
	__u32 size = 0;
	TreeKeyIdx *key = ((TreeKeyIdx *)this->key);

	char userData[8];

	if (len < 0)
		len = strlen(inbuf);

	bdtfd->write(inbuf, len);

	size = archtosword32(len);
	memcpy(userData, &offset, 4);
	memcpy(userData+4, &size, 4);
	key->setUserData(userData, 8);
	key->save();
}


void RawGenBook::linkEntry(const SWKey *inkey) {
	TreeKeyIdx *srckey = 0;
	TreeKeyIdx *key = ((TreeKeyIdx *)this->key);
	// see if we have a VerseKey * or decendant
	SWTRY {
		srckey = SWDYNAMIC_CAST(TreeKeyIdx, inkey);
	}
	SWCATCH ( ... ) {}
	// if we don't have a VerseKey * decendant, create our own
	if (!srckey) {
		srckey = (TreeKeyIdx *)CreateKey();
		(*srckey) = *inkey;
	}

	key->setUserData(srckey->getUserData(), 8);
	key->save();

	if (inkey != srckey) // free our key if we created a VerseKey
		delete srckey;
}


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

void RawGenBook::deleteEntry() {
	TreeKeyIdx *key = ((TreeKeyIdx *)this->key);
	key->remove();
}


char RawGenBook::createModule(const char *ipath) {
	char *path = 0;
	char *buf = new char [ strlen (ipath) + 20 ];
	FileDesc *fd;
	signed char retval;

	stdstr(&path, ipath);

	if ((path[strlen(path)-1] == '/') || (path[strlen(path)-1] == '\\'))
		path[strlen(path)-1] = 0;

	sprintf(buf, "%s.bdt", path);
	FileMgr::removeFile(buf);
	fd = FileMgr::getSystemFileMgr()->open(buf, FileMgr::CREAT|FileMgr::WRONLY, FileMgr::IREAD|FileMgr::IWRITE);
	fd->getFd();
	FileMgr::getSystemFileMgr()->close(fd);

	retval = TreeKeyIdx::create(path);
	delete [] path;
	return retval;	
}


SWKey *RawGenBook::CreateKey() {
	TreeKeyIdx *newKey = new TreeKeyIdx(path);
	return (verseKey) ? (SWKey *)new VerseTreeKey(newKey) : newKey;
}

SWORD_NAMESPACE_END
