/***************************************************************************
    copyright            : (C) 2003-2007 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 "alexandriaexporter.h"
#include "../document.h"
#include "../collection.h"
#include "../tellico_kernel.h"
#include "../imagefactory.h"
#include "../image.h"
#include "../tellico_utils.h"
#include "../tellico_debug.h"
#include "../progressmanager.h"

#include <tdelocale.h>
#include <tdemessagebox.h>
#include <tdeapplication.h>

#include <tqdir.h>

namespace {
  static const int ALEXANDRIA_MAX_SIZE_SMALL = 60;
  static const int ALEXANDRIA_MAX_SIZE_MEDIUM = 140;
}

using Tellico::Export::AlexandriaExporter;

TQString& AlexandriaExporter::escapeText(TQString& str_) {
  str_.replace('"', TQString::fromLatin1("\\\""));
  return str_;
}

TQString AlexandriaExporter::formatString() const {
  return i18n("Alexandria");
}

bool AlexandriaExporter::exec() {
  Data::CollPtr coll = collection();
  if(!coll || (coll->type() != Data::Collection::Book && coll->type() != Data::Collection::Bibtex)) {
    myLog() << "AlexandriaExporter::exec() - bad collection" << endl;
    return false;
  }

  const TQString alexDirName = TQString::fromLatin1(".alexandria");

  // create if necessary
  TQDir libraryDir = TQDir::home();
  if(!libraryDir.cd(alexDirName)) {
    if(!libraryDir.mkdir(alexDirName) || !libraryDir.cd(alexDirName)) {
      myLog() << "AlexandriaExporter::exec() - can't locate directory" << endl;
      return false;
    }
  }

  // the collection title is the name of the directory to create
  if(libraryDir.cd(coll->title())) {
    int ret = KMessageBox::warningContinueCancel(Kernel::self()->widget(),
                                                 i18n("<qt>An Alexandria library called <i>%1</i> already exists. "
                                                      "Any existing books in that library could be overwritten.</qt>")
                                                      .arg(coll->title()));
    if(ret == KMessageBox::Cancel) {
      return false;
    }
  } else if(!libraryDir.mkdir(coll->title()) || !libraryDir.cd(coll->title())) {
    return false; // could not create and cd to the dir
  }

  ProgressItem& item = ProgressManager::self()->newProgressItem(this, TQString(), false);
  item.setTotalSteps(entries().count());
  ProgressItem::Done done(this);
  const uint stepSize = TQMAX(1, entries().count()/100);
  const bool showProgress = options() & ExportProgress;

  GUI::CursorSaver cs;
  bool success = true;
  uint j = 0;
  for(Data::EntryVec::ConstIterator entryIt = entries().begin(); entryIt != entries().end(); ++entryIt, ++j) {
    success &= writeFile(libraryDir, entryIt.data());
    if(showProgress && j%stepSize == 0) {
      item.setProgress(j);
      kapp->processEvents();
    }
  }
  return success;
}

// this isn't true YAML export, of course
// everything is put between quotes except for the rating, just to be sure it's interpreted as a string
bool AlexandriaExporter::writeFile(const TQDir& dir_, Data::ConstEntryPtr entry_) {
  // the filename is the isbn without dashes, followed by .yaml
  TQString isbn = entry_->field(TQString::fromLatin1("isbn"));
  if(isbn.isEmpty()) {
    return false; // can't write it since Alexandria uses isbn as name of file
  }
  isbn.remove('-'); // remove dashes

  TQFile file(dir_.absPath() + TQDir::separator() + isbn + TQString::fromLatin1(".yaml"));
  if(!file.open(IO_WriteOnly)) {
    return false;
  }

  // do we format?
  bool format = options() & Export::ExportFormatted;

  TQTextStream ts(&file);
  // alexandria uses utf-8 all the time
  ts.setEncoding(TQTextStream::UnicodeUTF8);
  ts << "--- !ruby/object:Alexandria::Book\n";
  ts << "authors:\n";
  TQStringList authors = entry_->fields(TQString::fromLatin1("author"), format);
  for(TQStringList::Iterator it = authors.begin(); it != authors.end(); ++it) {
    ts << "  - " << escapeText(*it) << "\n";
  }
  // Alexandria crashes when no authors, and uses n/a when none
  if(authors.count() == 0) {
    ts << "  - n/a\n";
  }

  TQString tmp = entry_->field(TQString::fromLatin1("title"), format);
  ts << "title: \"" << escapeText(tmp) << "\"\n";

  // Alexandria refers to the binding as the edition
  tmp = entry_->field(TQString::fromLatin1("binding"), format);
  ts << "edition: \"" << escapeText(tmp) << "\"\n";

  // sometimes Alexandria interprets the isbn as a number instead of a string
  // I have no idea how to debug ruby, so err on safe side and add quotes
  ts << "isbn: \"" << isbn << "\"\n";

  tmp = entry_->field(TQString::fromLatin1("comments"), format);
  ts << "notes: \"" << escapeText(tmp) << "\"\n";

  tmp = entry_->field(TQString::fromLatin1("publisher"), format);
  // publisher uses n/a when empty
  ts << "publisher: \"" << (tmp.isEmpty() ? TQString::fromLatin1("n/a") : escapeText(tmp)) << "\"\n";

  tmp = entry_->field(TQString::fromLatin1("pub_year"), format);
  if(!tmp.isEmpty()) {
    ts << "publishing_year: \"" << escapeText(tmp) << "\"\n";
  }

  tmp = entry_->field(TQString::fromLatin1("rating"));
  bool ok;
  int rating = Tellico::toUInt(tmp, &ok);
  if(ok) {
    ts << "rating: " << rating << "\n";
  }

  file.close();

  TQString cover = entry_->field(TQString::fromLatin1("cover"));
  if(cover.isEmpty() || !(options() & Export::ExportImages)) {
    return true; // all done
  }

  TQImage img1(ImageFactory::imageById(cover));
  TQImage img2;
  TQString filename = dir_.absPath() + TQDir::separator() + isbn;
  if(img1.height() > ALEXANDRIA_MAX_SIZE_SMALL) {
    if(img1.height() > ALEXANDRIA_MAX_SIZE_MEDIUM) { // limit maximum size
      img1 = img1.scale(ALEXANDRIA_MAX_SIZE_MEDIUM, ALEXANDRIA_MAX_SIZE_MEDIUM, TQ_ScaleMin);
    }
    img2 = img1.scale(ALEXANDRIA_MAX_SIZE_SMALL, ALEXANDRIA_MAX_SIZE_SMALL, TQ_ScaleMin);
  } else {
    img2 = img1.smoothScale(ALEXANDRIA_MAX_SIZE_MEDIUM, ALEXANDRIA_MAX_SIZE_MEDIUM, TQ_ScaleMin); // scale up
  }
  if(!img1.save(filename + TQString::fromLatin1("_medium.jpg"), "JPEG")
     || !img2.save(filename + TQString::fromLatin1("_small.jpg"), "JPEG")) {
    return false;
  }
  return true;
}

#include "alexandriaexporter.moc"