/***************************************************************************
    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 "tellicozipexporter.h"
#include "tellicoxmlexporter.h"
#include "../collection.h"
#include "../imagefactory.h"
#include "../image.h"
#include "../filehandler.h"
#include "../stringset.h"
#include "../tellico_debug.h"
#include "../progressmanager.h"

#include <tdelocale.h>
#include <tdeconfig.h>
#include <kzip.h>
#include <tdeapplication.h>

#include <tqdom.h>
#include <tqbuffer.h>

using Tellico::Export::TellicoZipExporter;

TQString TellicoZipExporter::formatString() const {
  return i18n("Tellico Zip File");
}

TQString TellicoZipExporter::fileFilter() const {
  return i18n("*.tc *.bc|Tellico Files (*.tc)") + TQChar('\n') + i18n("*|All Files");
}

bool TellicoZipExporter::exec() {
  m_cancelled = false;
  Data::CollPtr coll = collection();
  if(!coll) {
    return false;
  }

  // TODO: maybe need label?
  ProgressItem& item = ProgressManager::self()->newProgressItem(this, TQString(), true);
  item.setTotalSteps(100);
  connect(&item, TQ_SIGNAL(signalCancelled(ProgressItem*)), TQ_SLOT(slotCancel()));
  ProgressItem::Done done(this);

  TellicoXMLExporter exp;
  exp.setEntries(entries());
  exp.setURL(url()); // needed in case of relative URL values
  long opt = options();
  opt |= Export::ExportUTF8; // always export to UTF-8
  opt |= Export::ExportImages; // always list the images in the xml
  opt &= ~Export::ExportProgress; // don't show progress for xml export
  exp.setOptions(opt);
  exp.setIncludeImages(false); // do not include the images themselves in XML
  TQCString xml = exp.exportXML().toCString(); // encoded in utf-8
  ProgressManager::self()->setProgress(this, 5);

  TQByteArray data;
  TQBuffer buf(data);

  if(m_cancelled) {
    return true; // intentionally cancelled
  }

  KZip zip(&buf);
  zip.open(IO_WriteOnly);
  zip.writeFile(TQString::fromLatin1("tellico.xml"), TQString(), TQString(), xml.length(), xml);

  if(m_includeImages) {
    ProgressManager::self()->setProgress(this, 10);
    // gonna be lazy and just increment progress every 3 images
    // it might be less, might be more
    uint j = 0;
    const TQString imagesDir = TQString::fromLatin1("images/");
    StringSet imageSet;
    Data::FieldVec imageFields = coll->imageFields();
    // already took 10%, only 90% left
    const uint stepSize = TQMAX(1, (coll->entryCount() * imageFields.count()) / 90);
    for(Data::EntryVec::ConstIterator it = entries().begin(); it != entries().end() && !m_cancelled; ++it) {
      for(Data::FieldVec::Iterator fIt = imageFields.begin(); fIt != imageFields.end(); ++fIt, ++j) {
        const TQString id = it->field(fIt);
        if(id.isEmpty() || imageSet.has(id)) {
          continue;
        }
        const Data::ImageInfo& info = ImageFactory::imageInfo(id);
        if(info.linkOnly) {
          myLog() << "TellicoZipExporter::exec() - not copying linked image: " << id << endl;
          continue;
        }
        const Data::Image& img = ImageFactory::imageById(id);
        // if no image, continue
        if(img.isNull()) {
          kdWarning() << "TellicoZipExporter::exec() - no image found for " << fIt->title() << " field" << endl;
          kdWarning() << "...for the entry titled " << it->title() << endl;
          continue;
        }
        TQByteArray ba = img.byteArray();
//        myDebug() << "TellicoZipExporter::data() - adding image id = " << it->field(fIt) << endl;
        zip.writeFile(imagesDir + id, TQString(), TQString(), ba.size(), ba);
        imageSet.add(id);
        if(j%stepSize == 0) {
          ProgressManager::self()->setProgress(this, TQMIN(10+j/stepSize, 99));
          kapp->processEvents();
        }
      }
    }
  } else {
    ProgressManager::self()->setProgress(this, 80);
  }

  zip.close();
  if(m_cancelled) {
    return true;
  }

  bool success = FileHandler::writeDataURL(url(), data, options() & Export::ExportForce);
  return success;
}

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

#include "tellicozipexporter.moc"
