bool Mediator::removeBook(int ID)
{
	bool done = false;
	if(ID>0)
	{
		ByteString byteString = this->dataBookManager->getBook(ID);
		if(!byteString.isEmpty())
		{
			bool isRemoved = this->dataBookManager->removeRecord(ID);
			if(isRemoved)
			{
				Book book;
				book.Hidratate(byteString);
				this->indexWrapper->removeFromAll(book);
				done = true;
			}
		}
	}
	return done;
}
string Mediator::search(IndexWrapper::indexItem index, string toSearch)
{
	Key* k = NULL;
	string toReturn;
	list<int>* bookIds;
	//string separator;
	//list<string> wordsToFind;
	FileParser* fp;
	map<string, Term*> wordsToFind;
	list<Word*> words;
	list<int>* coincidenceDocs = NULL;
	list<int>* notCoincidenceDocs = NULL;
	list<BookGlobalWeight*>* bookByGlobalWeight = NULL;
	bool doSearch = false;
	int totalBooks;

	switch(index){
		case IndexWrapper::EDITORIAL:
			k = new Key(toSearch);
			bookIds = this->indexWrapper->searchAllIds(k, index);
			break;
		case IndexWrapper::AUTOR:
			k = new Key(toSearch);
			bookIds = this->indexWrapper->searchAllIds(k, index);
			break;
		case IndexWrapper::TITULO:
			k = new Key(toSearch);
			bookIds = this->indexWrapper->searchAllIds(k, index);
			break;
		case IndexWrapper::PALABRAS:
		{
			bookIds = new list<int>();

			//separator = " ";
			//wordsToFind = Utility::split(toSearch, separator);

			fp = new FileParser();
			fp->setWords(toSearch);
			wordsToFind = fp->getTerms();
			delete fp;

			// Se recorre todas las palabras de las busqueda, y se buscan en el hash
			for(map<string, Term*>::iterator it = wordsToFind.begin(); it != wordsToFind.end(); ++it)
			{
				Key* k = new Key((*it).first);
				list<int>* booksWords = this->indexWrapper->searchAllIds(k, index);
				Word* newWord = new Word((*it).first, booksWords);
				words.push_back(newWord);
				if (newWord->getBooks()->size() > 0)
					doSearch = true;
				delete k;
			}

			if (wordsToFind.size()>0 && doSearch)
			{
				//Obtiene los libros en que se encuentran en todas las palabras
				coincidenceDocs = this->findCoincidences(words);
				if (coincidenceDocs->size() > 0)
				{
					list<RankingBook>* listRanking;
					listRanking = findTermProxIdBooks(coincidenceDocs,words);
					list<RankingBook>::iterator itRanking;

					cout << "Ids book Encontrados por Terminos Proximos: ";
					for(itRanking=listRanking->begin();itRanking!=listRanking->end();++itRanking)
					{
						int idBook = (*itRanking).getIdBook();
						cout << idBook << " ";
						bookIds->push_back(idBook);
					}
					cout << endl;
				}

				//Obtiene los libros que se encuentran solo algunas de las palabras
				notCoincidenceDocs = this->findNotCoincidences(words, coincidenceDocs);
				if (notCoincidenceDocs->size() > 0)
				{
					//Ordena los documentos que no tienen coincidencia total en los terminos segun el peso global
					totalBooks = coincidenceDocs->size() + notCoincidenceDocs->size();
					bookByGlobalWeight = this->orderBookByGlobalWeight(notCoincidenceDocs, words, totalBooks);

					cout << "Ids book Encontrados por Peso Global: ";
					for(list<BookGlobalWeight*>::iterator itGW = bookByGlobalWeight->begin(); itGW!=bookByGlobalWeight->end(); ++itGW)
					{
						int idBook = (*itGW)->getIdBook();
						cout << idBook << " ";
						bookIds->push_back(idBook);
					}
					cout << endl;
				}
			}

			break;
		}
		default:
			break;
	}

	if(bookIds->size() > 0){
		for (list<int>::iterator it = bookIds->begin(); it != bookIds->end(); ++it)
		{
			ByteString bs = this->dataBookManager->getBook(*it);
			Book b;
			b.Hidratate(bs);
			toReturn.append(b.getBookFormatedText());
		}
	}else
		toReturn = "La busqueda no arrojo resultados";


	delete k;
	return toReturn;
}
bool Mediator::indexingListOnIndex(IndexWrapper::indexItem item)
{
	bool done = false;
	List<int>* flagsLs = this->dataBookManager->getListToFileFlag(item);
	if(!flagsLs->isEmpty())
	{
		cout << "Process Started: " << Utility::getDate() << endl;
		ListIterator<int> it = flagsLs->getIterator();
		int ID;
		while(it.hasNext())
		{
			ID = it.next();
			ByteString bs = this->dataBookManager->getBook(ID);
			Book book;
			book.Hidratate(bs);

			string clave;
			Record* record;
			ByteString bsIdBook;
			ByteString* bsId;
			bsIdBook.insertLast(&ID,sizeof(int));
			Key* key;
			switch(item){
			case IndexWrapper::AUTOR :
										clave = book.getAuthor();
										cout << "Book begin process: " << book.getTitle() << " - Author:" << clave << " - Start:" << Utility::getDate();

										key = new Key(clave);
										bsId = new ByteString(bsIdBook);
										record = new Record(key,bsId);
										done = this->indexWrapper->add(record,item);
										break;
			case IndexWrapper::EDITORIAL :
										clave = book.getEditorial();
										cout << "Book begin process: " << book.getTitle() << " - Editorial:" << clave << " - Start:" << Utility::getDate();

										key = new Key(clave);
										bsId = new ByteString(bsIdBook);
										record = new Record(key,bsId);
										done = this->indexWrapper->add(record,item);
										break;
			case IndexWrapper::TITULO :
										clave = book.getTitle();
										cout << "Book begin process: " << book.getTitle() << " - Start:" << Utility::getDate();

										key = new Key(clave);
										bsId = new ByteString(bsIdBook);
										record = new Record(key,bsId);
										done = this->indexWrapper->add(record,item);
										break;
			case IndexWrapper::PALABRAS :
										this->fileParser->setWords(book.getText());

										// ----------------------------------------------------------------------------------------------- //
										// Se incorpora la norma infinito del documento
										// ----------------------------------------------------------------------------------------------- //
										Key* keyIdBook = new Key(bsIdBook.toString());

										ByteString* bsInfinityNorm = new ByteString();
										unsigned int infinityNorm = this->fileParser->getInfinityNorm();
										bsInfinityNorm->insertLast(&infinityNorm, sizeof(unsigned int));

										Record* recInfinityNorm = new Record(keyIdBook, bsInfinityNorm);
										this->infinityNormIndex->add(recInfinityNorm);
										delete recInfinityNorm;
										// ----------------------------------------------------------------------------------------------- //

										map<string,Term*> terms = this->fileParser->getTerms();
										cout << "Book begin process: " << book.getTitle() << " - Words Count:" << Utility::intToString(terms.size()) << " - Start:" << Utility::getDate();
										int i = 0;
										for(map<string,Term*>::iterator it = terms.begin(); it != terms.end(); ++it)
										{
											i++;
											// ------------------------ //
											key = new Key(it->first);
											string word = it->first;
											list<int>* listDocuments = this->indexWrapper->searchAllIds(key, IndexWrapper::PALABRAS);
											int idTerm;

											// Si no tiene datos --> la palabra no existe en el hash
											if (listDocuments->size() == 0)
											{
												//delete poddo
												delete listDocuments;

												// Se agrega la palabra al vocabulario y se obtiene su id
												int possibleID = this->autoIncInteger + 1;

												// La clave es el id de termino y el dato la palabra
												ByteString bsIdTerm;
												bsIdTerm.insertLast(&possibleID, sizeof(int));
												Key* keyIdTerm = new Key(bsIdTerm.toString());

												ByteString* bsTerm = new ByteString();
												bsTerm->insertLast(word);

												Record* recVocabulary = new Record(keyIdTerm, bsTerm);
												this->vocabularyIndex->add(recVocabulary);
												delete recVocabulary;

												idTerm = possibleID;
												this->autoIncInteger++;
											}
											else
											{
												// Devuelve en la ultima posicion el id del termino y en las restantes los id de documentos
												Word* newWord = new Word(word, listDocuments);
												idTerm = newWord->getIdWord();
												delete newWord; // se elimina la lisdDocuments tambien
											}

											//Aca se agrega las ocurrencias del termino en el libro
											list<unsigned int> listOfPositions = it->second->getPositions();

											ByteString bs;
											bs.insertLast(&ID,sizeof(int));
											bs.insertLast(&idTerm,sizeof(int));
											Record* r = new Record();
											r->setKey(new Key(bs.toString()));

											this->ocurrenceTree->addList(r,listOfPositions);

											listOfPositions.clear();
											delete r;

											// ------------------------ //
											bsId = new ByteString(bsIdBook);
											bsId->insertLast(&idTerm, sizeof(int));
											record = new Record(key,bsId);

											done = this->indexWrapper->add(record,item);
											delete record;
										}

										break;
			}
			cout << "Book processed: " << book.getTitle() << " - Finish:" << Utility::getDate() << endl;
		}
		cout << "Process Ended: " << Utility::getDate();
	}

	//delete poddo
	if (flagsLs != NULL)
		delete flagsLs;

	return done;
}