/* ****************************************************************************
  This file is part of KBabel

  Copyright (C) 2002-2003 by Marco Wegner <mail@marcowegner.de>

  This program is free software; you can redistribute it and/or modify
  it under the terms of the GNU General Public License as published by
  the Free Software Foundation; either version 2 of the License, or
  (at your option) any later version.

  This program is distributed in the hope that it will be useful,
  but WITHOUT ANY WARRANTY; without even the implied warranty of
  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  GNU General Public License for more details.

  You should have received a copy of the GNU General Public License
  along with this program; if not, write to the Free Software
  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.

**************************************************************************** */


#include <qdir.h>
#include <qfile.h>
#include <qfileinfo.h>
#include <qregexp.h>
#include <qstring.h>
#include <qstringlist.h>

#include <kapplication.h>
#include <kconfig.h>
#include <kglobal.h>
#include <kio/netaccess.h>
#include <klineedit.h>
#include <klineeditdlg.h>
#include <klocale.h>
#include <kmessagebox.h>
#include <kstandarddirs.h>
#include <ktar.h>
#include <kurl.h>

#include "catalogsettings.h"
#include "kbmailer.h"

using namespace KBabel;

KBabelMailer::KBabelMailer(QString configFile)
  : _configFile(configFile)
{
  editDialog = 0;
  editCompletion = 0;

  tempDir = locateLocal("tmp", QString::null);
  readConfig();
}

KBabelMailer::~KBabelMailer()
{
  saveConfig( );

  delete editCompletion;
  delete editDialog;

  // clean up before leaving
  removeTempFiles();
}

void KBabelMailer::sendOneFile(const QString& fileName)
{
  if (!singleFileCompression) {
    kapp->invokeMailer("", "", "", "", "", "", fileName);
  } else {
    QString archive = createArchive(QStringList(fileName), QFileInfo(fileName).baseName( ));
    if (!archive.isNull()) {
      kapp->invokeMailer("", "", "", "", "", "", archive);
    }
  }
}

void KBabelMailer::sendFiles(QStringList fileList, const QString& initialName)
{
  QString archive = createArchive(fileList, initialName);
  if (!archive.isNull()) {
    kapp->invokeMailer("", "", "", "", "", "", archive);
  }
}

QString KBabelMailer::createArchive(QStringList fileList, QString initialName)
{
  // do nothing if there are no files in the list
  if (fileList.empty())
    return QString::null;

  // determine the name of the archive, do nothing if none is given
  // or Cancel was pressed
  initialName = ( initialName.isEmpty() ? QString("translations") : initialName );
  if ( !editDialog ) {
    editDialog = new KLineEditDlg(i18n("Enter the name of the archive "
      "without file extension"), initialName, 0);
    editCompletion = editDialog->lineEdit( )->completionObject( );
    editCompletion->setItems( archiveList );
  }
  editDialog->lineEdit( )->setText( initialName );
  if ( editDialog->exec( ) != KDialog::Accepted || editDialog->text( ).isEmpty( ) )
    return QString::null;

  // file extensions are determined from the type of compression
  QString archiveName = editDialog->text( ).remove( QRegExp( "\\.tar\\.(gz|bz2)$" ) );

  // Update the list of archive names, keep only the ten most recent ones.
  archiveList.remove( archiveName );
  archiveList.prepend( archiveName );
  if ( archiveList.count( ) > 10 )
    archiveList.remove( archiveList.last( ) );
  editCompletion->setItems( archiveList );

  // set the correct extension and mimetype
  QString mimetype;
  if (bzipCompression) {
    archiveName += ".tar.bz2";
    mimetype = "application/x-bzip2";
  } else {
    archiveName += ".tar.gz";
    mimetype = "application/x-gzip";
  }

  // create a new archive
  KTar archive(tempDir + archiveName, mimetype);
  if (!archive.open(IO_WriteOnly)) {
    KMessageBox::error(0, i18n("Error while trying to create archive file."));
    return QString::null;
  }

  // add files to this archive
  QStringList::Iterator it;
  for (it = fileList.begin(); it != fileList.end(); ++it) {
    KURL url(*it);
    QString poTempName;
    if (!KIO::NetAccess::download(url, poTempName)) {
      KMessageBox::error(0, i18n("Error while trying to read file %1.").arg(url.prettyURL()));
      continue;
    }
    QFile poFile(poTempName);
    if (!poFile.open(IO_ReadOnly)) {
      KMessageBox::error(0, i18n("Error while trying to open file %1.").arg(poTempName));
    } else {
      // The files in the archive are stored relatively to the PO base dir
      // but only if "PoBaseDir" in the config file is set and the files
      // actually reside in one of its subdirectories. Else they are stored
      // without relative path.
      QString poArchFileName = poFile.name( );
      if (_poBaseDir.isEmpty( ) || poArchFileName.find(_poBaseDir) != 0)
        poArchFileName = QFileInfo(poFile.name( )).fileName( );
      else
        poArchFileName.remove(QRegExp("^" + _poBaseDir + "/?"));
      // Finally write the file to the archive and close the file.
      // N.B.: "user" and "group" are just sort of placeholders here.
      // While doing "tar xf[jz]" the correct UID and GID of the user
      // who is unpacking are assigned.
      archive.writeFile(poArchFileName, "user", "group", poFile.size( ), poFile.readAll( ));
      poFile.close( );
    }
    KIO::NetAccess::removeTempFile(poTempName);
  }
  archive.close();

  // add archive's filename to the list of files to be deleted later
  tempFileNames << archive.fileName();
  return archive.fileName();
}

void KBabelMailer::readConfig()
{
  // The relevant variables are never stored in catalogmanagerrc but in
  // kbabelrc or the equivalent profile's config file. Therefore they are
  // read from KConfig(_configFile) instead of from KGlobal::config( ).
  _config = new KConfig(_configFile);

  _config->setGroup("Misc");
  bzipCompression = _config->readBoolEntry("BZipCompression", Defaults::Misc::useBzip);
  singleFileCompression = _config->readBoolEntry("CompressSingleFile", Defaults::Misc::compressSingleFile);
  archiveList = _config->readListEntry("MailArchiveNames");

  _config->setGroup("CatalogManager");
  _poBaseDir = _config->readEntry("PoBaseDir", QString::null);

  delete _config;
}

void KBabelMailer::saveConfig()
{
  // For an explanation see readConfig( )
  _config = new KConfig(_configFile);

  _config->setGroup("Misc");
  _config->writeEntry("MailArchiveNames", archiveList);

  delete _config;
}

void KBabelMailer::removeTempFiles()
{
  if (tempFileNames.empty())
    return;

  QDir d(tempDir);
  QStringList::Iterator it;
  for (it = tempFileNames.begin(); it != tempFileNames.end(); ++it)
    d.remove(*it);
}
