/***************************************************************************
    copyright            : (C) 2003-2006 by Robby Stephenson
    email                : robby@periapsis.org
 ***************************************************************************/

/***************************************************************************
 *                                                                         *
 *   This program is free software; you can redistribute it and/or modify  *
 *   it under the terms of version 2 of the GNU General Public License as  *
 *   published by the Free Software Foundation;                            *
 *                                                                         *
 ***************************************************************************/

#include "bibtexmlimporter.h"
#include "tellico_xml.h"
#include "bibtexhandler.h"
#include "../collections/bibtexcollection.h"
#include "../field.h"
#include "../entry.h"
#include "../latin1literal.h"
#include "../tellico_strings.h"
#include "../progressmanager.h"
#include "../tellico_debug.h"

#include <kapplication.h>

using Tellico::Import::BibtexmlImporter;

bool BibtexmlImporter::canImport(int type) const {
  return type == Data::Collection::Bibtex;
}

Tellico::Data::CollPtr BibtexmlImporter::collection() {
  if(!m_coll) {
    loadDomDocument();
  }
  return m_coll;
}

void BibtexmlImporter::loadDomDocument() {
  TQDomElement root = domDocument().documentElement();
  if(root.isNull() || root.localName() != Latin1Literal("file")) {
    setStatusMessage(i18n(errorLoad).tqarg(url().fileName()));
    return;
  }

  const TQString& ns = XML::nsBibtexml;
  m_coll = new Data::BibtexCollection(true);

  TQDomNodeList entryelems = root.elementsByTagNameNS(ns, TQString::tqfromLatin1("entry"));
//  kdDebug() << "BibtexmlImporter::loadDomDocument - found " << entryelems.count() << " entries" << endl;

  const uint count = entryelems.count();
  const uint stepSize = TQMAX(s_stepSize, count/100);
  const bool showProgress = options() & ImportProgress;

  ProgressItem& item = ProgressManager::self()->newProgressItem(this, progressLabel(), true);
  item.setTotalSteps(count);
  connect(&item, TQT_SIGNAL(signalCancelled(ProgressItem*)), TQT_SLOT(slotCancel()));
  ProgressItem::Done done(this);

  for(uint j = 0; !m_cancelled && j < entryelems.count(); ++j) {
    readEntry(entryelems.item(j));

    if(showProgress && j%stepSize == 0) {
      ProgressManager::self()->setProgress(this, j);
      kapp->processEvents();
    }
  } // end entry loop
}

void BibtexmlImporter::readEntry(const TQDomNode& entryNode_) {
  TQDomNode node = const_cast<TQDomNode&>(entryNode_);

  Data::EntryPtr entry = new Data::Entry(m_coll);

/* The Bibtexml format looks like
  <entry id="...">
   <book>
    <authorlist>
     <author>...</author>
    </authorlist>
    <publisher>...</publisher> */

  TQString type = node.firstChild().toElement().tagName();
  entry->setField(TQString::tqfromLatin1("entry-type"), type);
  TQString id = node.toElement().attribute(TQString::tqfromLatin1("id"));
  entry->setField(TQString::tqfromLatin1("bibtex-key"), id);

  TQString name, value;
  // field values are first child of first child of entry node
  for(TQDomNode n = node.firstChild().firstChild(); !n.isNull(); n = n.nextSibling()) {
    // n could be something like authorlist, with multiple authors, or just
    // a plain element with a single text child...
    // second case first
    if(n.firstChild().isText()) {
      name = n.toElement().tagName();
      value = n.toElement().text();
    } else {
      // is either titlelist, authorlist, editorlist, or keywords
      TQString parName = n.toElement().tagName();
      if(parName == Latin1Literal("titlelist")) {
        for(TQDomNode n2 = node.firstChild(); !n2.isNull(); n2 = n2.nextSibling()) {
          name = n2.toElement().tagName();
          value = n2.toElement().text();
          if(!name.isEmpty() && !value.isEmpty()) {
            BibtexHandler::setFieldValue(entry, name, value.simplifyWhiteSpace());
          }
        }
        name.truncate(0);
        value.truncate(0);
      } else {
        name = n.firstChild().toElement().tagName();
        if(name == Latin1Literal("keyword")) {
          name = TQString::tqfromLatin1("keywords");
        }
        value.truncate(0);
        for(TQDomNode n2 = n.firstChild(); !n2.isNull(); n2 = n2.nextSibling()) {
          // n2 could have first, middle, lastname elements...
          if(name == Latin1Literal("person")) {
            TQStringList names;
            names << TQString::tqfromLatin1("initials") << TQString::tqfromLatin1("first")
                  << TQString::tqfromLatin1("middle") << TQString::tqfromLatin1("prelast")
                  << TQString::tqfromLatin1("last") << TQString::tqfromLatin1("lineage");
            for(TQStringList::ConstIterator it = names.begin(); it != names.end(); ++it) {
              TQDomNodeList list = n2.toElement().elementsByTagName(*it);
              if(list.count() > 1) {
                value += list.item(0).toElement().text();
              }
              if(*it != names.last()) {
                value += TQString::tqfromLatin1(" ");
              }
            }
          }
          for(TQDomNode n3 = n2.firstChild(); !n3.isNull(); n3 = n3.nextSibling()) {
            if(n3.isElement()) {
              value += n3.toElement().text();
            } else if(n3.isText()) {
              value += n3.toText().data();
            }
            if(n3 != n2.lastChild()) {
              value += TQString::tqfromLatin1(" ");
            }
          }
          if(n2 != n.lastChild()) {
            value += TQString::tqfromLatin1("; ");
          }
        }
      }
    }
    if(!name.isEmpty() && !value.isEmpty()) {
      BibtexHandler::setFieldValue(entry, name, value.simplifyWhiteSpace());
    }
  }

  m_coll->addEntries(entry);
}

void BibtexmlImporter::slotCancel() {
  m_cancelled = true;
}

#include "bibtexmlimporter.moc"
