//
// C++ Implementation: bibentrydeftable
//
// Description:
//
//
// Author: Thach Nguyen <thach.nguyen@rmit.edu.au>, (C) 2007
//
// Copyright: See COPYING file that comes with this distribution
//
//
#include "bibentrydeftable.h"
#include <qdom.h>
#include <qfile.h>
#include <iostream>

BibEntryDefTable* BibEntryDefTable::s_self = 0;

QString BibEntryDef::getRequired ( int i )
{
	if ( i < 0 || i >= ( int ) required.size() )
		return 0;
	return required[i];
}

QString BibEntryDef::getOptional ( int i )
{
	if ( i < 0 || i >= ( int ) optional.size() )
		return 0;
	return optional[i];
}


int BibEntryDef::getFieldIdx ( QString fn )
{
	QString s;
	for ( int i=0; i < numRequired(); i++ )
	{
		s = required[i];
		if ( fn.lower() == s.lower() )
			return i;
	}
	for ( int i=0; i < numOptional(); i++ )
	{
		s = optional[i];
		if ( fn.lower() == s.lower() )
			return i+numRequired();
	}
	return -1;
}

BibEntryDefTable::BibEntryDefTable()
{
	entryDefs.setAutoDelete ( true );
	refFields.setAutoDelete ( true );
}


BibEntryDefTable::~BibEntryDefTable()
{}

QString BibEntryDefTable::getEntryTypeName ( int i )
{
	if ( i < 0 or i >= ( int ) entryDefTab.count() )
		return 0;
	return entryDefTab[i];
}

QString BibEntryDefTable::getFieldName ( int i )
{
	if ( i < 0 || i >= ( int ) refFields.count() )
		return 0;
	return fieldNameTab[i];

}



void BibEntryDefTable::newEntryDef ( QString name, QStringList required, QStringList optional, bool readOnly, bool overwrite )
{
	bool exist = false;
	QString xname = name.lower();
	BibEntryDef* def;
	if ( entryDefTab.contains ( xname ) )
		exist = true;

	if ( exist && !overwrite )
		return;

	if ( overwrite )
	{
		def = getBibEntryDef ( xname );
		if ( !def )
			def = new BibEntryDef();
	}
	else
		def = new BibEntryDef();

	def->name = xname;
	def->required = required;
	def->optional = optional;
	def->readOnly = readOnly;

	if ( !exist )
	{
		entryDefs.insert ( xname, def );
		entryDefTab.append ( xname );
	}
}


void BibEntryDefTable::deleteEntryDef ( QString name )
{
	QString xname = name.lower();
	entryDefs.remove ( xname );
	QStringList::iterator it = entryDefTab.find ( xname );
	entryDefTab.erase ( it );
}

void BibEntryDefTable::readEntryDefFile ( QString filename )
{
	QFile file ( filename );
	if ( !file.open ( IO_ReadOnly ) )
	{
		return;
	}

	QDomDocument doc ( "mydocument" );
	if ( !doc.setContent ( &file ) )
	{
		file.close();
		return;
	}
	file.close();
	for ( QDomNode n = doc.documentElement().firstChild(); !n.isNull(); n = n.nextSibling() )
	{
		if ( n.nodeName() == QString::fromLatin1 ( "entry" ) )
		{
			QStringList required, optional;
			QString name;
			bool readOnly=false;
			for ( QDomNode f = n.firstChild(); !f.isNull(); f = f.nextSibling() )
			{
				QDomElement e = f.toElement();
				if ( e.isNull() )
				{
					continue;
				}
				if ( e.tagName() == QString::fromLatin1 ( "Name" ) )
				{
					name = e.text().lower();
				}
				else if ( e.tagName() == QString::fromLatin1 ( "Required" ) )
				{
					required.append ( e.text().lower() );
				}
				else if ( e.tagName() == QString::fromLatin1 ( "Optional" ) )
				{
					optional.append ( e.text().lower() );
				}
				else if ( e.tagName() == QString::fromLatin1 ( "ReadOnly" ) )
				{
					
					if ( e.text() == QString::fromLatin1 ( "YES" ) ){
						readOnly = true;
					}
					else{
						readOnly = false;
					}
				}
			}
			newEntryDef ( name, required, optional, readOnly, true );

		}
		else if ( n.nodeName() == QString::fromLatin1 ( "field" ) )
		{
			//RefField *field = new RefField;
			QString name;
			int type = TEXT;
			QString connectingString;
			bool autoCompletion=false;
			bool allowGrouping=false;	

			for ( QDomNode f = n.firstChild(); !f.isNull(); f = f.nextSibling() )
			{

				QDomElement e = f.toElement();
				if ( e.isNull() )
				{
					continue;
				}
				if ( e.tagName() == QString::fromLatin1 ( "Name" ) )
				{
					name = e.text().lower();
				}
				else if ( e.tagName() == QString::fromLatin1 ( "Type" ) )
				{
					type = e.text().toInt();
				}
				
				else if ( e.tagName() == QString::fromLatin1 ( "ConnectingString" ) )
				{
					connectingString = e.text();
				}
				else if ( e.tagName() == QString::fromLatin1 ( "AutoCompletion" ) )
				{
					if ( e.text() == QString::fromLatin1 ( "YES" ) )
						autoCompletion = true;
					else
						autoCompletion = false;
				}
				else if ( e.tagName() == QString::fromLatin1 ( "AllowGrouping" ) )
				{
					if ( e.text() == QString::fromLatin1 ( "YES" ) )
						allowGrouping = true;
					else
						allowGrouping = false;
				}
				
			}
			//refFields.append ( field );
			newRefField(name, type, connectingString, autoCompletion, allowGrouping, true);

		}
	}

}

void BibEntryDefTable::writeEntryDefFile ( QString filename )
{
	QFile file ( filename );
	if ( file.open ( IO_WriteOnly ) )
	{
		QTextStream stream ( &file );
		stream << QString::fromLatin1 ( "<?xml version=\"1.0\"?>\n" );
		stream << QString::fromLatin1 ( "<entryDefTable>\n" );

		for ( QStringList::Iterator it = entryDefTab.begin(); it != entryDefTab.end(); ++it )
		{
			BibEntryDef *def = entryDefs[*it];
			stream << QString::fromLatin1 ( "<entry>\n" );
			stream << QString::fromLatin1 ( "\t<Name>" ) << def->name << QString::fromLatin1 ( "</Name>\n" );
			if ( ( def->required ).count() > 0 )
			{
				stream << QString::fromLatin1 ( "\t<Required>" );
				stream << ( def->required ).join ( QString::fromLatin1 ( "</Required>\n\t<Required>" ) );
				stream << QString::fromLatin1 ( "</Required>\n" );
			}
			if ( ( def->optional ).count() > 0 )
			{
				stream << QString::fromLatin1 ( "\t<Optional>" );
				stream << ( def->optional ).join ( QString::fromLatin1 ( "</Optional>\n\t<Optional>" ) );
				stream << QString::fromLatin1 ( "</Optional>\n" );
			}
			
			stream << QString::fromLatin1 ( "\t<ReadOnly>" );
			if ( def->readOnly )
				stream << QString::fromLatin1 ( "YES" );
			else
				stream << QString::fromLatin1 ( "NO" );
			stream << QString::fromLatin1 ( "</ReadOnly>\n" );
			
			stream << QString::fromLatin1 ( "</entry>\n" );
		}

		
		for ( QStringList::Iterator it = fieldNameTab.begin(); it != fieldNameTab.end(); ++it )
		{
			RefField *field = refFields[*it];
		
			stream << QString::fromLatin1 ( "<field>\n" );
			stream << QString::fromLatin1 ( "\t<Name>" ) << field->name << QString::fromLatin1 ( "</Name>\n" );
			stream << QString::fromLatin1 ( "\t<Type>" ) << field->type << QString::fromLatin1 ( "</Type>\n" );
			
			stream << QString::fromLatin1 ( "\t<ConnectingString>" ) << field->connectingString << QString::fromLatin1 ( "</ConnectingString>\n" );

			stream << QString::fromLatin1 ( "\t<AutoCompletion>" );
			if ( field->autoCompletion )
				stream << QString::fromLatin1 ( "YES" );
			else
				stream << QString::fromLatin1 ( "NO" );
			stream << QString::fromLatin1 ( "</AutoCompletion>\n" );

			stream << QString::fromLatin1 ( "\t<AllowGrouping>" );
			if ( field->allowGrouping )
				stream << QString::fromLatin1 ( "YES" );
			else
				stream << QString::fromLatin1 ( "NO" );
			stream << QString::fromLatin1 ( "</AllowGrouping>\n" );

			stream << QString::fromLatin1 ( "</field>\n" );
		}
		stream << QString::fromLatin1 ( "</entryDefTable>\n" );
	}
	file.close();
}

void BibEntryDefTable::clear()
{
	entryDefs.clear();
	entryDefTab.clear();

}

void BibEntryDefTable::clearRefFields(){
	refFields.clear();
	fieldNameTab.clear();	
}

void BibEntryDefTable::newRefField(QString name, 	int type,  QString connectingString, bool autoCompletion, bool allowGrouping,  bool overwrite){
	bool exist = false;
	QString xname = name.lower();
	RefField* field;
	if ( fieldNameTab.contains ( xname ) )
		exist = true;

	if ( exist && !overwrite )
		return;

	if ( overwrite )
	{
		field = getRefField ( xname );
		if ( !field )
			field = new RefField;
	}
	else
		field = new RefField;
	
	field->name = name;
	field->type = type;
	field->connectingString = connectingString;
	field->autoCompletion = autoCompletion;
	field->allowGrouping = allowGrouping;

	if ( !exist )
	{
		refFields.insert ( xname, field );
		fieldNameTab.append ( xname );
	}
	
}
