#include "ApplicationInterface.h"
#include "SwordIndex.h"
#include <markupfiltmgr.h>
#include <swordce.h>
#include "swwinlog.h"

const CHAR* swordConfigDir="/Program Files/sword/books";

TCHAR* defBookNames[66]={
L"Gen",L"Exo",L"Lev",L"Num",L"Deu",L"Jos",L"Jud",L"Rut",L"1Sa",
L"2Sa",L"1Ki",L"2Ki",L"1Ch",L"2Ch",L"Ezr",L"Neh",L"Est",L"Job",L"Psa",L"Pro",L"Ecc",L"Son",L"Isa",L"Jer",
L"Lam",L"Eze",L"Dan",L"Hos",L"Joe",L"Amo",L"Oba",L"Jon",L"Mic",L"Nah",L"Hab",L"Zep",L"Hag",L"Zec",L"Mal",
L"Mat",L"Mar",L"Luk",L"Joh",L"Act",L"Rom",L"1Co",L"2Co",L"Gal",L"Eph",L"Phi",L"Col",
L"1Th",L"2Th",L"1Ti",L"2Ti",L"Tit",L"Phi",L"Heb",L"Jas",L"1Pe",L"2Pe",L"1Jo",L"2Jo",L"3Jo",L"Jud",L"Rev",
};

UString SwordIndex::verseToString(Verse* verse) {
	return UString(defBookNames[(verse->Book()-1)+otBookCount()*(verse->Testament()-1)]) + L" " 
		+ toUString(verse->Chapter()) + L":" 
		+ toUString(verse->Verse());
}

SWMgr* SwordIndex::manager;
SWModule *SwordIndex::greekLex = 0;
SWModule *SwordIndex::hebrewLex = 0;
SWModule *SwordIndex::greekMorph = 0;
SWModule *SwordIndex::hebrewMorph = 0;

int SwordIndex::indices=0;
std::map<const char*, sword::SWModule*, ltstr>* SwordIndex::texts;

SwordIndex::SwordIndex() {
	initManager();
	if (texts->begin()!=texts->end()) {
		bookNames=defBookNames;
		verse=new sword::VerseKey("Gen 1:1");
		verse->Persist(1);
		mark=new sword::VerseKey("Gen 1:1");
		mark->Persist(1);
		book=1;
		setModule(texts->begin()->second);
	}
	else
		bible=0;
}

SwordIndex::~SwordIndex() {
	leaveManager();
	if (verse) delete verse;
	if (mark) delete mark;
}

void SwordIndex::initManager() {
	if (indices==0) { //We need a manager
		texts=new ModuleMap();
		__try {
			manager=new sword::SWMgr(new sword::MarkupFilterMgr(sword::FMT_HTMLHREF, sword::ENC_UTF16));

			sword::ModMap::iterator it;
			sword::SWModule* curMod = 0;
			for (it = manager->Modules.begin(); it != manager->Modules.end(); it++) {
				curMod = (*it).second;
				if (!strcmp(curMod->Type(), "Biblical Texts")) {
					(*texts)[curMod->Name()]=curMod;
				}
				// next section added BD - Nov 07
				if (!strcmp(curMod->Type(), "Commentaries")) {
					(*texts)[curMod->Name()]=curMod;
				}			// end of added code
				if (curMod->getConfig().has("Feature", "GreekDef")) {
					greekLex = curMod;
				}
				if (curMod->getConfig().has("Feature", "GreekParse")) {
					greekMorph = curMod;
				}
				if (curMod->getConfig().has("Feature", "HebrewDef")) {
					hebrewLex = curMod;
				}
				if (curMod->getConfig().has("Feature", "HebrewParse")) {
					hebrewMorph = curMod;
				}
			}
		} 
		__except (EXCEPTION_EXECUTE_HANDLER) {
			manager=0;
			texts->clear();
		};
	}
	indices++;
}

void SwordIndex::leaveManager() {
	indices--;
	if (indices==0) {
		if (manager!=0) delete manager;
		delete texts;
	}
}

UString SwordIndex::toString() {
	return verseToString(verse);
}

UString SwordIndex::bookName(int book) {
	return UString(defBookNames[book-1]);
}

void SwordIndex::setBook(int book) {
	this->book=book;
	if (book<=otBookCount()) {
		verse->Testament(1);
		verse->Book((char)book);
	} else {
		verse->Testament(2);
		verse->Book((char)book-otBookCount());
	}
}

sword::sbook SwordIndex::getBook(int book) {
	book--; //we now need to start at 0
	if (book<otBookCount())
		return (verse->books[0][book]);
	else if (book<bookCount())
		return (verse->books[1][book-otBookCount()]);
	else return (verse->books[1][bookCount()-otBookCount()-1]);

}

int SwordIndex::chapCount() {
	return getBook(book).chapmax;
}

void SwordIndex::setChap(int chap) {
	verse->Chapter(chap);
}

int SwordIndex::getChap() {
	return verse->Chapter();
}

int SwordIndex::verseCount() {
	return getBook(book).versemax[verse->Chapter()-1];
}

void SwordIndex::setVerse(int verse) {
	this->verse->Verse(verse);
}

int SwordIndex::getVerse() {
	return verse->Verse();
}

UString SwordIndex::verseText() {
	UString utf16 = (WCHAR *)bible->RenderText();
	return utf16;
}

UString SwordIndex::verseText(sword::VerseKey* anyVerse) {
	setMark();
	verse->copyFrom(anyVerse);
	UString temp=verseText();
	jumpBack();
	return temp;
}

void SwordIndex::setVerseKey(sword::VerseKey* anyVerse) {
	verse->copyFrom(anyVerse);
}

void SwordIndex::setMark() {
	mark->copyFrom(verse);
}

void SwordIndex::jumpBack() {
	verse->copyFrom(mark);
}

void SwordIndex::next() {
	verse->increment(1);
}

void SwordIndex::setModule(Module m) {
	bible=m;
	bible->setKey(verse);
}

void SwordIndex::search(UString text, int range, int method, Searcher* searcher) {
	searcher->setProgress(10);
	Verse from=verse->clone();
	Verse to=verse->clone();
	if (range==RANGEBIBLE) from.Testament(1);
	if ((range==RANGETESTAMENT)||(range==RANGEBIBLE)) from.Book(1);
	from.Chapter(1);
	from.Verse(1);
	if (range==RANGEBIBLE) to.Testament(2);
	if ((range==RANGETESTAMENT)||(range==RANGEBIBLE)) to.Book((to.Testament()==2)?bookCount()-otBookCount():otBookCount());
	to.Chapter(to.books[to.Testament()-1][to.Book()-1].chapmax);
	to.Verse(to.books[to.Testament()-1][to.Book()-1].versemax[to.Chapter()-1]);
/*	FOR DEBUGGING
	searcher->addResult(verseToString(&from));
	searcher->addResult(verseToString(&to));
*/

	Verse verses(from,to);
	sword::ListKey results;
	searcher->setProgress(20);
// this next code block carries out the search - the call is to SWModule::search
	results=bible->search(
		toCString(text).c_str(), 
		(method==METHODMULTIWORD)?-2:-1, 
		2 /* case insensitive */, 
		&verses
	);
// end of search - returns a SWModule::ListKey variable (results)
	searcher->setProgress(90);

// the 'for' loop copies the results into the display window
	for (results = TOP; !results.Error(); results++) {
//		searcher->addResult(toUString(String(results.getText())));
		searcher->addResult(toUString((std::string)(results.getText())));
		}
// thanks to Troy for the above

// below was the original code from Johan Gorter
//	for (int i=0;i<results.Count();i++) {
//		searcher->addResult(toUString(String(results.getElement(i)->getText())));
//	}
	searcher->setProgress(100);
}

