/*
 * This file is part of the KFTPGrabber project
 *
 * Copyright (C) 2003-2004 by the KFTPGrabber developers
 * Copyright (C) 2003-2004 Jernej Kos <kostko@jweb-network.net>
 * Copyright (C) 2004 Markus Brueffer <markus@brueffer.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
 * is provided AS IS, WITHOUT ANY WARRANTY; without even the implied
 * warranty of MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE, and
 * NON-INFRINGEMENT.  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., 51 Franklin Steet, Fifth Floor, Boston,
 * MA 02110-1301, USA.
 *
 * In addition, as a special exception, the copyright holders give
 * permission to link the code of portions of this program with the
 * OpenSSL library under certain conditions as described in each
 * individual source file, and distribute linked combinations
 * including the two.
 * You must obey the GNU General Public License in all respects
 * for all of the code used other than OpenSSL.  If you modify
 * file(s) with this exception, you may extend this exception to your
 * version of the file(s), but you are not obligated to do so.  If you
 * do not wish to do so, delete this exception statement from your
 * version.  If you delete this exception statement from all source
 * files in the program, then also delete it here.
 */

#include <qlayout.h>
#include <qpushbutton.h>
#include <qcheckbox.h>
#include <qgroupbox.h>
#include <qspinbox.h>
#include <qsplitter.h>
#include <qtextedit.h>
#include <qtabwidget.h>

#include <kglobal.h>
#include <kcharsets.h>
#include <klocale.h>
#include <kiconloader.h>
#include <klineedit.h>
#include <kpassdlg.h>
#include <kmessagebox.h>
#include <kpopupmenu.h>
#include <kcombobox.h>
#include <kurlrequester.h>
#include <kguiitem.h>
#include <kfiledialog.h>
#include <kio/job.h>

#include "kftpapi.h"
#include "kftpbookmarks.h"
#include "misc/config.h"
#include "misc.h"

#include "editor.h"
#include "listview.h"
#include "importwizard.h"
#include "editortls.h"

using namespace KFTPGrabberBase;

namespace KFTPWidgets {

namespace Bookmarks {

KActionCollection *BookmarkEditor::actionCollection()
{
  return KFTPAPI::getInstance()->mainWindow()->actionCollection();
}

BookmarkEditor::BookmarkEditor(QWidget *parent, const char *name)
 : KDialogBase(parent, name, true, "FTP Bookmark Editor", User2|User1|Ok|Apply|Cancel, Ok, true, KGuiItem(i18n("Import...")), KGuiItem(i18n("Export..."))),
   m_activeSite(0),
   m_activeItem(0L),
   m_portChanged(false)
{
  // We operate on a copy of the bookmarks
  m_bookmarks = new KFTPBookmarks::Manager(*KFTPBookmarks::Manager::self());

  QHBoxLayout *winLayout = new QHBoxLayout(this, 0, KDialog::spacingHint());

  QSplitter *splitter = new QSplitter(this);
  setMainWidget(splitter);
  winLayout->addWidget(splitter);

  // Create the list view for editing bookmarks
  m_tree = new ListView(m_bookmarks, splitter);

  m_properties = new BookmarkProperties(splitter);

  initDialog();

  connect(this, SIGNAL(user1Clicked()), this, SLOT(slotImportWizard()));
  connect(this, SIGNAL(user2Clicked()), this, SLOT(slotExportWizard()));

  connect(m_tree, SIGNAL(bookmarkClicked(QListViewItem*)), this, SLOT(slotTreeClicked(QListViewItem*)));
  connect(m_tree, SIGNAL(bookmarkNew(ListViewItem*, KFTPBookmarks::Site*)), this, SLOT(slotNewAction(ListViewItem*, KFTPBookmarks::Site*)));
  connect(m_tree, SIGNAL(bookmarkDuplicated(ListViewItem*, KFTPBookmarks::Site*)), this, SLOT(slotDuplicateAction(ListViewItem*, KFTPBookmarks::Site*)));
  connect(m_tree, SIGNAL(bookmarkDeleted()), this, SLOT(slotDeleteAction()));
  connect(m_tree, SIGNAL(bookmarkMoved()), this, SLOT(refresh()));
  connect(m_tree, SIGNAL(categoryRenamed()), this, SLOT(refresh()));

  // Get the new bookmark data
  m_tree->fillBookmarkData();
}

BookmarkEditor::BookmarkEditor(ListViewItem *item, QWidget *parent, const char *name)
 : KDialogBase(parent, name, true, i18n("FTP Bookmark Editor"), Ok|Apply|Cancel, Ok, true),
   m_activeSite(0),
   m_activeItem(item),
   m_tree(0L),
   m_portChanged(false)
{
  setCaption(m_activeItem->text(0));

  // We operate on a copy of the bookmarks
  m_bookmarks = new KFTPBookmarks::Manager(*KFTPBookmarks::Manager::self());

  QHBoxLayout *winLayout = new QHBoxLayout(this, 0, KDialog::spacingHint());

  m_properties = new BookmarkProperties(this);
  setMainWidget(m_properties);
  winLayout->addWidget(m_properties);

  initDialog();

  m_activeSite = m_activeItem->m_site;

  showActiveNode();
}

BookmarkEditor::~BookmarkEditor()
{
  delete m_bookmarks;
}

void BookmarkEditor::initDialog()
{
  m_properties->tabList->setTabIconSet(m_properties->general, loadSmallIcon("kfm"));
  m_properties->tabList->setTabIconSet(m_properties->advanced, loadSmallIcon("contents"));
  m_properties->tabList->setTabIconSet(m_properties->keepalive, loadSmallIcon("clock"));
  m_properties->protoAdvanced->setIconSet(loadSmallIcon("configure"));
  m_properties->retryGroup->setEnabled(false);
  m_properties->defLocalDir->setMode(KFile::Directory | KFile::ExistingOnly | KFile::LocalOnly );

  connect(m_properties->anonLogin, SIGNAL(clicked()), this, SLOT(slotChangeAnonLogin()));
  connect(m_properties->doRetry, SIGNAL(clicked()), this, SLOT(slotChangeActiveRetryGroup()));
  connect(m_properties->doKeepalive, SIGNAL(clicked()), this, SLOT(slotChangeActiveKeepaliveGroup()));
  connect(m_properties->protoAdvanced, SIGNAL(clicked()), this, SLOT(slotProtoAdvancedClicked()));
  connect(m_properties->serverProtocol, SIGNAL(activated(int)), this, SLOT(slotChangeServerProtocol(int)));
  connect(m_properties->serverPort, SIGNAL(valueChanged(int)), this, SLOT(slotPortChanged()));

  connect(this, SIGNAL(applyClicked()), this, SLOT(slotSaveActiveNode()));
  connect(this, SIGNAL(okClicked()), this, SLOT(slotSaveActiveNode()));

  // Populate charsets
  QStringList charsets = KGlobal::charsets()->descriptiveEncodingNames();
  m_properties->serverEncoding->insertStringList(charsets);

  // Deactivate everything until an item gets selected
  m_properties->setEnabled(false);
}

void BookmarkEditor::refresh()
{
  m_tree->clear();
  m_tree->fillBookmarkData();
}

void BookmarkEditor::slotImportWizard()
{
  ImportWizard *wizard = new ImportWizard(this);

  if (wizard->exec() == QDialog::Accepted) {
    // Refresh bookmarks
    m_bookmarks->setBookmarks(KFTPBookmarks::Manager::self());

    m_tree->clear();
    m_tree->fillBookmarkData();
  }

  delete wizard;
}

void BookmarkEditor::slotExportWizard()
{
  if (KMessageBox::questionYesNo(0, i18n("<qt>You are about to export your KFTPGrabber bookmarks. They may contain passwords or sensitive X509 certificates; exporting your bookmarks may compromise their safety.<br><br>Are you sure?</qt>"), i18n("Export Bookmarks")) == KMessageBox::No) {
    return;
  }

  QString savePath = KFileDialog::getSaveFileName(QString::null, "*.xml|KFTPGrabber Bookmarks", 0, i18n("Export Bookmarks"));

  if (!savePath.isEmpty()) {
    // Save and copy the bookmarks
    KFTPBookmarks::Manager::self()->save();
    KIO::copy(KURL(getStoreDir("bookmarks.xml")), KURL(savePath), false);
  }
}

void BookmarkEditor::slotNewAction(ListViewItem *item, KFTPBookmarks::Site *site)
{
  // Display the new server's properties
  m_activeItem = item;
  m_activeSite = site;

  showActiveNode();

  // Set Focus to servername
  m_properties->serverName->selectAll();
  m_properties->serverName->setFocus();
}

void BookmarkEditor::slotDuplicateAction(ListViewItem *item, KFTPBookmarks::Site *site)
{
  m_activeItem = item;

  // Display its properties
  m_activeSite = site;

  showActiveNode();
}

void BookmarkEditor::slotDeleteAction()
{
  m_activeItem = 0L;
  m_properties->setEnabled(false);
}

void BookmarkEditor::slotSaveActiveNode()
{
  if (!m_activeItem) {
    KFTPBookmarks::Manager::self()->setBookmarks(m_bookmarks);
    return;
  }

  m_activeSite->setAttribute("name", m_properties->serverName->text());
  m_activeSite->setProperty("host", m_properties->serverAddress->text());
  m_activeSite->setProperty("port", m_properties->serverPort->value());
  m_activeSite->setProperty("protocol", m_properties->serverProtocol->currentItem() == SP_SFTP ? "sftp" : "ftp");
  m_activeSite->setProperty("use_tls", m_properties->serverProtocol->currentItem() == SP_SSL_EXPLICIT);
  m_activeSite->setProperty("use_implicit", m_properties->serverProtocol->currentItem() == SP_SSL_IMPLICIT);
  m_activeSite->setProperty("anonlogin", m_properties->anonLogin->isChecked());

  m_activeSite->setProperty("username", m_properties->downUser->text());
  m_activeSite->setProperty("password", encodePassword(m_properties->downPass->password()));

  m_activeSite->setProperty("encoding", KGlobal::charsets()->encodingForName(m_properties->serverEncoding->currentText()));

  // Only save the local dir if it differs from the default one
  if (m_properties->defLocalDir->url() != KFTPCore::Config::defLocalDir())
    m_activeSite->setProperty("deflocalpath", m_properties->defLocalDir->url());

  m_activeSite->setProperty("defremotepath", m_properties->defRemoteDir->text());
  m_activeSite->setProperty("description", m_properties->description->text());

  m_activeSite->setProperty("doRetry", m_properties->doRetry->isChecked());
  m_activeSite->setProperty("retrytime", m_properties->retryDelay->value());
  m_activeSite->setProperty("retrycount", m_properties->retryCount->value());
  
  m_activeSite->setProperty("doKeepalive", m_properties->doKeepalive->isChecked());
  m_activeSite->setProperty("keepaliveTimeout", m_properties->keepaliveTimeout->value());
  
  m_activeSite->setProperty("disablePASV", m_properties->disablePASV->isChecked());
  m_activeSite->setProperty("disableEPSV", m_properties->disableEPSV->isChecked());
  m_activeSite->setProperty("pasvSiteIp", m_properties->pasvSiteIp->isChecked());
  m_activeSite->setProperty("disableForceIp", m_properties->disableForceIp->isChecked());
  m_activeSite->setProperty("disableThreads", m_properties->threadsDisable->isChecked());
  m_activeSite->setProperty("statListings", m_properties->statListings->isChecked());

  // Update the ListView node
  m_activeItem->setText(0, m_properties->serverName->text());

  if (m_tree)
    KFTPBookmarks::Manager::self()->setBookmarks(m_bookmarks);

  showActiveNode();

  // Save the bookmarks
  KFTPBookmarks::Manager::self()->save();
}

void BookmarkEditor::showActiveNode()
{
  if (m_activeItem->m_type == BT_CATEGORY || !m_activeSite) {
    m_properties->setEnabled(false);
    return;
  }

  m_properties->setEnabled(true);

  // Show all the data for the active node
  m_properties->serverName->setText(m_activeSite->getAttribute("name"));
  m_properties->serverAddress->setText(m_activeSite->getProperty("host"));

  if (m_activeSite->getProperty("protocol") == "sftp") m_properties->serverProtocol->setCurrentItem(SP_SFTP);
  else if (m_activeSite->getIntProperty("use_tls")) m_properties->serverProtocol->setCurrentItem(SP_SSL_EXPLICIT);
  else if (m_activeSite->getIntProperty("use_implicit")) m_properties->serverProtocol->setCurrentItem(SP_SSL_IMPLICIT);
  else m_properties->serverProtocol->setCurrentItem(SP_FTP);

  slotChangeServerProtocol(m_properties->serverProtocol->currentItem());


  m_properties->serverPort->setValue(m_activeSite->getIntProperty("port"));
  m_portChanged = false;

  m_properties->downUser->erase();
  m_properties->downPass->erase();
  m_properties->anonLogin->setChecked(m_activeSite->getIntProperty("anonlogin"));

  slotChangeAnonLogin();

  m_properties->downUser->setText(m_activeSite->getProperty("username"));
  m_properties->downPass->insert(m_activeSite->getProperty("password"));

  QString defLocalPath = m_activeSite->getProperty("deflocalpath");
  if (defLocalPath.isEmpty())
    defLocalPath = KFTPCore::Config::defLocalDir();

  m_properties->defLocalDir->setURL(defLocalPath);
  m_properties->defRemoteDir->setText(m_activeSite->getProperty("defremotepath"));
  m_properties->description->setText(m_activeSite->getProperty("description"));

  int retryTime = m_activeSite->getIntProperty("retrytime");
  int retryCount = m_activeSite->getIntProperty("retrycount");

  m_properties->doRetry->setChecked(m_activeSite->getIntProperty("doRetry"));

  if (m_properties->doRetry->isChecked()) {
    m_properties->retryGroup->setEnabled(true);
    m_properties->retryDelay->setValue(retryTime);
    m_properties->retryCount->setValue(retryCount);
  } else {
    m_properties->retryGroup->setEnabled(false);
    m_properties->retryDelay->setValue(KFTPCore::Config::retryTime());
    m_properties->retryCount->setValue(KFTPCore::Config::retryCount());
  }
  
  m_properties->doKeepalive->setChecked(m_activeSite->getIntProperty("doKeepalive"));
  
  if (m_properties->doKeepalive->isChecked()) {
    m_properties->keepaliveGroup->setEnabled(true);
    m_properties->keepaliveTimeout->setValue(m_activeSite->getIntProperty("keepaliveTimeout"));
  } else {
    m_properties->keepaliveGroup->setEnabled(false);
    m_properties->keepaliveTimeout->setValue(60);
  }

  QString serverEncoding = m_activeSite->getProperty("encoding");
  if (serverEncoding.isEmpty())
    serverEncoding = KFTPCore::Config::defEncoding();

  serverEncoding = QString("%1 ( %2 )").arg(KGlobal::charsets()->languageForEncoding(serverEncoding)).arg(serverEncoding);
  m_properties->serverEncoding->setCurrentText(serverEncoding);

  m_properties->disablePASV->setChecked(m_activeSite->getIntProperty("disablePASV"));
  m_properties->disableEPSV->setChecked(m_activeSite->getIntProperty("disableEPSV"));
  m_properties->pasvSiteIp->setChecked(m_activeSite->getIntProperty("pasvSiteIp"));
  m_properties->disableForceIp->setChecked(m_activeSite->getIntProperty("disableForceIp"));
  m_properties->threadsDisable->setChecked(m_activeSite->getIntProperty("disableThreads"));
  m_properties->statListings->setChecked(m_activeSite->getIntProperty("statListings"));
}

void BookmarkEditor::slotTreeClicked(QListViewItem *item)
{
  m_activeItem = static_cast<ListViewItem*>(item);

  if ( !m_activeItem || m_activeItem->m_type == BT_CATEGORY ) {
    // Deactivate all controls
     m_properties->setEnabled(false);
     return;
  }

  // Find the node and set it active
  if (m_activeItem->m_type == BT_CATEGORY) {
    // Category
    m_activeSite = 0L;
  } else {
    // Server
    m_activeSite = m_activeItem->m_site;
  }

  // Show the active node (if any)
  showActiveNode();
}

void BookmarkEditor::slotChangeActiveRetryGroup()
{
  m_properties->retryGroup->setEnabled(m_properties->doRetry->isChecked());
}

void BookmarkEditor::slotChangeActiveKeepaliveGroup()
{
  m_properties->keepaliveGroup->setEnabled(m_properties->doKeepalive->isChecked());
}

void BookmarkEditor::slotChangeAnonLogin()
{
  static QString tmpUser, tmpPass;

  if (m_properties->anonLogin->isChecked()) {
    m_properties->downUser->setEnabled(false);
    m_properties->downPass->setEnabled(false);
    tmpUser = m_properties->downUser->text();
    tmpPass = m_properties->downPass->text();
    m_properties->downUser->setText("anonymous");

    // Use the appropriate e-mail address for anonymous accounts
    if (!KFTPCore::Config::anonMail().isEmpty())
      m_properties->downPass->setText(KFTPCore::Config::anonMail());
    else
      m_properties->downPass->setText("userlogin@anonymo.us");
  } else {
    m_properties->downUser->setEnabled(true);
    m_properties->downPass->setEnabled(true);
    m_properties->downUser->setText(tmpUser);
    m_properties->downPass->setText(tmpPass);
  }
}

void BookmarkEditor::slotProtoAdvancedClicked()
{
  BookmarkEditorTLS *tlsDialog = new BookmarkEditorTLS(this);

  // Initialize dialog
  int mode = m_activeSite->getIntProperty("tls_data_mode");
  bool useCert = m_activeSite->getIntProperty("use_cert");
  QString certPath = m_activeSite->getProperty("tls_cert_path");

  tlsDialog->setTLSMode(mode);
  tlsDialog->setCertChecked(useCert);
  if (useCert)
    tlsDialog->setCertPath(certPath);
  tlsDialog->slotChangeActiveX509Group();

  if (tlsDialog->exec()) {
    // Save the modifications
    m_activeSite->setProperty("tls_data_mode", tlsDialog->getTLSMode());
    m_activeSite->setProperty("use_cert", tlsDialog->isCertChecked());

    if (tlsDialog->isCertChecked())
      m_activeSite->setProperty("tls_cert_path", tlsDialog->getCertPath());
  }

  delete tlsDialog;
}

void BookmarkEditor::slotPortChanged()
{
  m_portChanged = true;
}

void BookmarkEditor::slotChangeServerProtocol(int item)
{
  // Enable/Disable the SSL/TLS settings if needed
  m_properties->protoAdvanced->setEnabled( item == 1 || item == 2 );

  // Set the default port
  if (!m_portChanged) {
    switch (item) {
      case SP_SSL_IMPLICIT:
        if (m_properties->serverPort->value() == 21 || m_properties->serverPort->value() == 22)
          m_properties->serverPort->setValue(993);
        break;
      case SP_SFTP:
        if (m_properties->serverPort->value() == 21 || m_properties->serverPort->value() == 993)
          m_properties->serverPort->setValue(22);
        break;
      default:
        if (m_properties->serverPort->value() == 22 || m_properties->serverPort->value() == 993)
          m_properties->serverPort->setValue(21);
        break;
    }

    m_portChanged = false;
  }
}

}

}

#include "editor.moc"
