/***************************************************************************
                          kqifprofileeditor.cpp  -  description
                             -------------------
    begin                : Tue Dec 24 2002
    copyright            : (C) 2002 by Thomas Baumgart
    email                : thb@net-bembel.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.                                   *
 *                                                                         *
 ***************************************************************************/

// ----------------------------------------------------------------------------
// QT Includes

#include <tqpushbutton.h>
#include <tqlistbox.h>
#include <tqlistview.h>
#include <tqcheckbox.h>
#include <tqtabwidget.h>

// ----------------------------------------------------------------------------
// KDE Includes

#include "kdecompat.h"
#include <tdelocale.h>
#include <tdeglobal.h>
#include <tdeconfig.h>
#include <klineedit.h>
#include <tdemessagebox.h>
#include <kcombobox.h>
#include <kurlrequester.h>
#include <kiconloader.h>
#include <tdeapplication.h>

#if KDE_IS_VERSION(3,2,0)
  #include <kinputdialog.h>
#else
  #include <klineeditdlg.h>
#endif
// ----------------------------------------------------------------------------
// Project Includes

#include "mymoneyqifprofileeditor.h"

MyMoneyQifProfileNameValidator::MyMoneyQifProfileNameValidator(TQObject *o, const char *name)
  : TQValidator(o, name)
{
}

MyMoneyQifProfileNameValidator::~MyMoneyQifProfileNameValidator()
{
}

TQValidator::State MyMoneyQifProfileNameValidator::validate(TQString& name, int&) const
{
  TDEConfig* config = TDEGlobal::config();
  config->setGroup("Profiles");
  TQStringList list = config->readListEntry("profiles");

  // invalid character?
  if(name.contains(",") != 0)
    return TQValidator::Invalid;

  // would not work in this form (empty or existing name)
  if(name.isEmpty() || list.contains(name))
    return TQValidator::Intermediate;

  // is OK
  return TQValidator::Acceptable;
}

MyMoneyQifProfileEditor::MyMoneyQifProfileEditor(const bool edit, TQWidget *parent, const char *name )
  : MyMoneyQifProfileEditorDecl(parent,name),
  m_inEdit(edit),
  m_isDirty(false),
  m_isAccepted(false),
  m_selectedAmountType(0)
{
  // we don't need the date and amounts tab anymore, so we just hide them for now
  profileTabs->removePage( tabMoney );
  profileTabs->removePage( tabDate );

  loadWidgets();
  loadProfileListFromConfig();

  // load button icons
  TDEIconLoader* il = TDEGlobal::iconLoader();
  KGuiItem newButtenItem( i18n( "&New" ),
                      TQIconSet(il->loadIcon("document-new", TDEIcon::Small, TDEIcon::SizeSmall)),
                      i18n("Create a new profile"),
                      i18n("Use this to create a new QIF import/export profile"));
  m_newButton->setGuiItem(newButtenItem);

  connect(m_profileListBox, TQT_SIGNAL(highlighted(const TQString&)), this, TQT_SLOT(slotLoadProfileFromConfig(const TQString&)));
  connect(m_resetButton, TQT_SIGNAL(clicked()), this, TQT_SLOT(slotReset()));
  connect(m_okButton, TQT_SIGNAL(clicked()), this, TQT_SLOT(slotOk()));
  connect(m_renameButton, TQT_SIGNAL(clicked()), this, TQT_SLOT(slotRename()));
  connect(m_deleteButton, TQT_SIGNAL(clicked()), this, TQT_SLOT(slotDelete()));
  connect(m_newButton, TQT_SIGNAL(clicked()), this, TQT_SLOT(slotNew()));
  connect(m_cancelButton, TQT_SIGNAL(clicked()), this, TQT_SLOT(reject()));
  connect(m_helpButton, TQT_SIGNAL(clicked()), this, TQT_SLOT(slotHelp()));

  connect(m_editDescription, TQT_SIGNAL(textChanged(const TQString&)), &m_profile, TQT_SLOT(setProfileDescription(const TQString&)));
  connect(m_editType, TQT_SIGNAL(textChanged(const TQString&)), &m_profile, TQT_SLOT(setProfileType(const TQString&)));
  connect(m_editOpeningBalance, TQT_SIGNAL(textChanged(const TQString&)), &m_profile, TQT_SLOT(setOpeningBalanceText(const TQString&)));
  connect(m_editAccountDelimiter, TQT_SIGNAL(textChanged(const TQString&)), &m_profile, TQT_SLOT(setAccountDelimiter(const TQString&)));
  connect(m_editVoidMark, TQT_SIGNAL(textChanged(const TQString&)), &m_profile, TQT_SLOT(setVoidMark(const TQString&)));

  //connect(m_editDateFormat, TQT_SIGNAL(highlighted(const TQString&)), &m_profile, TQT_SLOT(setDateFormat(const TQString&)));
  connect(m_editApostrophe, TQT_SIGNAL(highlighted(const TQString&)), &m_profile, TQT_SLOT(setApostropheFormat(const TQString&)));

  connect(m_editAmounts, TQT_SIGNAL(selectionChanged(TQListViewItem*)), this, TQT_SLOT(slotAmountTypeSelected(TQListViewItem*)));
  connect(m_decimalBox, TQT_SIGNAL(activated(const TQString&)), this, TQT_SLOT(slotDecimalChanged(const TQString&)));
  connect(m_thousandsBox, TQT_SIGNAL(activated(const TQString&)), this, TQT_SLOT(slotThousandsChanged(const TQString&)));

  connect(m_editInputFilterLocation, TQT_SIGNAL(textChanged(const TQString&)), &m_profile, TQT_SLOT(setFilterScriptImport(const TQString&)));
  connect(m_editInputFilterLocation, TQT_SIGNAL(urlSelected(const TQString&)), m_editInputFilterLocation, TQT_SLOT(setURL(const TQString&)));

  connect(m_editInputFilterFileType, TQT_SIGNAL(textChanged(const TQString&)), &m_profile, TQT_SLOT(setFilterFileType(const TQString&)));

  connect(m_editOutputFilterLocation, TQT_SIGNAL(textChanged(const TQString&)), &m_profile, TQT_SLOT(setFilterScriptExport(const TQString&)));
  connect(m_editOutputFilterLocation, TQT_SIGNAL(urlSelected(const TQString&)), m_editOutputFilterLocation, TQT_SLOT(setURL(const TQString&)));

  connect(m_attemptMatch, TQT_SIGNAL(toggled(bool)), &m_profile, TQT_SLOT(setAttemptMatchDuplicates(bool)));
}

MyMoneyQifProfileEditor::~MyMoneyQifProfileEditor()
{
  if(m_inEdit && m_isDirty && m_isAccepted) {
    TDEConfig* config = TDEGlobal::config();
    config->sync();
  } else {
    slotReset();
  }
  delete tabMoney;
  delete tabDate;
}

void MyMoneyQifProfileEditor::loadWidgets(void)
{
  if(m_inEdit)
    setCaption(i18n("QIF Profile Editor"));
  else
    setCaption(i18n("QIF Profile Selector"));

  m_editDateFormat->clear();
  m_editDateFormat->insertItem( "%d/%m/%yy" );
  m_editDateFormat->insertItem( "%d/%mmm/%yy" );
  m_editDateFormat->insertItem( "%d/%m/%yyyy" );
  m_editDateFormat->insertItem( "%d/%mmm/%yyyy" );
  m_editDateFormat->insertItem( "%d/%m%yy" );
  m_editDateFormat->insertItem( "%d/%mmm%yy" );
  m_editDateFormat->insertItem( "%d.%m.%yy" );
  m_editDateFormat->insertItem( "%d.%m.%yyyy" );
  m_editDateFormat->insertItem( "%m.%d.%yy" );
  m_editDateFormat->insertItem( "%m.%d.%yyyy" );
  m_editDateFormat->insertItem( "%m/%d/%yy" );
  m_editDateFormat->insertItem( "%mmm/%d/%yy" );
  m_editDateFormat->insertItem( "%m/%d/%yyyy" );
  m_editDateFormat->insertItem( "%m-%d-%yyyy" );
  m_editDateFormat->insertItem( "%mmm/%d/%yyyy" );
  m_editDateFormat->insertItem( "%m%d%yy" );
  m_editDateFormat->insertItem( "%mmm/%d%yy" );
  m_editDateFormat->insertItem( "%yyyy-%mm-%dd" );
  m_editDateFormat->insertItem( "%m/%d'%yyyy" );

  m_editApostrophe->clear();
  m_editApostrophe->insertItem( "1900-1949" );
  m_editApostrophe->insertItem( "1900-1999" );
  m_editApostrophe->insertItem( "2000-2099" );

  m_editAmounts->setColumnAlignment(1, TQt::AlignCenter);
  m_editAmounts->setColumnAlignment(2, TQt::AlignCenter);
  m_editAmounts->setColumnAlignment(3, TQt::AlignCenter);

  m_editAmounts->setColumnWidth(4, 0);
  m_editAmounts->setColumnWidthMode(4, TQListView::Manual);
  m_editAmounts->setSorting(4);
  m_editAmounts->sort();

  m_decimalBox->insertItem( " " );
  m_decimalBox->insertItem( "," );
  m_decimalBox->insertItem( "." );

  m_thousandsBox->insertItem( " " );
  m_thousandsBox->insertItem( "," );
  m_thousandsBox->insertItem( "." );

  m_editDescription->setEnabled(m_inEdit);
  m_editType->setEnabled(m_inEdit);
  m_editDateFormat->setEnabled(m_inEdit);
  m_editApostrophe->setEnabled(m_inEdit);
  m_editAmounts->setEnabled(m_inEdit);
  m_decimalBox->setEnabled(m_inEdit);
  m_thousandsBox->setEnabled(m_inEdit);
  m_editOpeningBalance->setEnabled(m_inEdit);
  m_editAccountDelimiter->setEnabled(m_inEdit);
  m_editVoidMark->setEnabled(m_inEdit);
  m_editInputFilterLocation->setEnabled(m_inEdit);
  m_editOutputFilterLocation->setEnabled(m_inEdit);
  m_editInputFilterFileType->setEnabled(m_inEdit);

  if(!m_inEdit) {
    m_renameButton->hide();
    m_deleteButton->hide();
    m_resetButton->hide();
    m_newButton->hide();
  }
}

void MyMoneyQifProfileEditor::loadProfileListFromConfig(void)
{
  TQFontMetrics fontMetrics(m_profileListBox->font());
  int w = 100;      // minimum is 100 pixels width for the list box

  if(m_profile.isDirty()) {
    m_profile.saveProfile();
    m_isDirty = true;
  }

  m_profileListBox->clear();

  TQStringList list;
  TDEConfig* config = TDEGlobal::config();
  config->setGroup("Profiles");
  list = config->readListEntry("profiles");

  if(list.count() == 0) {
    m_profile.clear();
    m_profile.setProfileDescription(i18n("The default QIF profile"));
    addProfile("Default");

    config->setGroup("Profiles");
    list = config->readListEntry("profiles");
  }

  list.sort();

  m_profileListBox->insertStringList(list);
  if(list.count() > 0) {
    m_profileListBox->setSelected(0, true);
    slotLoadProfileFromConfig(list[0]);
  }
  for(unsigned int i = 0; i < list.count(); ++i) {
    int nw = fontMetrics.width(list[i]) + 10;
    w = TQMAX( w, nw );
  }
  w = TQMIN(w, 200);
  m_profileListBox->setMinimumWidth(w);
}

void MyMoneyQifProfileEditor::slotLoadProfileFromConfig(const TQString& profile)
{
  TQString profileName = profile;

  if(m_profile.isDirty()) {
    m_profile.saveProfile();
    m_isDirty = true;
  }

  if(m_profileListBox->findItem(profileName, TQt::ExactMatch | TQt::CaseSensitive) == NULL) {
    profileName = m_profileListBox->text(0);
  }

  m_profile.loadProfile("Profile-" + profileName);

  TQListBoxItem *lbi = m_profileListBox->findItem(profileName, TQt::ExactMatch | TQt::CaseSensitive);
  int idx = m_profileListBox->index(lbi);
  showProfile();
  if(idx >= 0) {
    m_profileListBox->setSelected(idx, true);
  }
}

void MyMoneyQifProfileEditor::showProfile(void)
{
  m_editDescription->setText(m_profile.profileDescription());
  m_editType->setText(m_profile.profileType());
  m_editOpeningBalance->setText(m_profile.openingBalanceText());
  m_editAccountDelimiter->setText(m_profile.accountDelimiter());
  m_editVoidMark->setText(m_profile.voidMark());
  m_editInputFilterLocation->setURL(m_profile.filterScriptImport());
  m_editOutputFilterLocation->setURL(m_profile.filterScriptExport());
  m_editInputFilterFileType->setText(m_profile.filterFileType());

  m_editDateFormat->setCurrentText(m_profile.outputDateFormat());
  m_editApostrophe->setCurrentText(m_profile.apostropheFormat());

  m_attemptMatch->setChecked(m_profile.attemptMatchDuplicates());

  TQListViewItem* item;
  TQListViewItemIterator it(m_editAmounts);

  while((item = it.current()) != 0) {
    TQChar key = item->text(1)[0];
    item->setText(2, m_profile.amountDecimal(key));
    item->setText(3, m_profile.amountThousands(key));
    if(m_selectedAmountType == 0 && key == 'T' && m_inEdit) {
      m_editAmounts->setSelected(item, true);
      slotAmountTypeSelected(item);
    } else if(item == m_selectedAmountType) {
      slotAmountTypeSelected(item);
    }
    ++it;
  }
}

void MyMoneyQifProfileEditor::deleteProfile(const TQString& name)
{
  TDEConfig* config = TDEGlobal::config();

  config->deleteGroup("Profile-" + name);

  config->setGroup("Profiles");
  TQStringList list = config->readListEntry("profiles");
  list.remove(name);

  config->writeEntry("profiles", list);
  m_isDirty = true;
}

void MyMoneyQifProfileEditor::addProfile(const TQString& name)
{
  TDEConfig* config = TDEGlobal::config();
  config->setGroup("Profiles");
  TQStringList list = config->readListEntry("profiles");

  list += name;
  list.sort();
  config->writeEntry("profiles", list);

  m_profile.setProfileName("Profile-" + name);
  m_profile.saveProfile();

  m_isDirty = true;
}

void MyMoneyQifProfileEditor::slotOk(void)
{
  if(m_profile.isDirty())
    m_isDirty = true;

  m_profile.saveProfile();

  TDEConfig* config = TDEGlobal::config();
  config->sync();

  m_isAccepted = true;
  accept();
}

void MyMoneyQifProfileEditor::slotReset(void)
{
  // first flush any changes
  m_profile.saveProfile();

  TDEConfig* config = TDEGlobal::config();
  config->rollback();
  config->reparseConfiguration();

  TQString currentProfile = m_profile.profileName().mid(8);
  loadProfileListFromConfig();
  slotLoadProfileFromConfig(currentProfile);
  m_isDirty = false;
}

void MyMoneyQifProfileEditor::slotRename(void)
{
  bool ok;
  TQString newName = enterName(ok);

  if(ok == true) {
    deleteProfile(m_profile.profileName().mid(8));
    addProfile(newName);
    loadProfileListFromConfig();
    slotLoadProfileFromConfig(newName);
  }
}

void MyMoneyQifProfileEditor::slotNew(void)
{
  bool ok;
  TQString newName = enterName(ok);

  if(ok == true) {
    m_profile.clear();
    addProfile(newName);
    loadProfileListFromConfig();
    slotLoadProfileFromConfig(newName);
  }
}

const TQString MyMoneyQifProfileEditor::enterName(bool& ok)
{
  MyMoneyQifProfileNameValidator val(TQT_TQOBJECT(this), "Validator");
#if KDE_IS_VERSION(3,2,0)
  return KInputDialog::getText(i18n("QIF Profile Editor"),
                               i18n("Enter new profile name"),
                               TQString(),
                               &ok,
                               this,
                               0,
                               &val,
                               0);
#else
  TQString rc;

  // the blank in the next line as the value for the edit box is
  // there on purpose, so that with the following call to validateAndSet
  // the state is changed and the OK-Button is greyed
  KLineEditDlg* dlg = new KLineEditDlg(i18n("Enter new profile name"), " ", this);
  dlg->lineEdit()->setValidator(&val);
  dlg->lineEdit()->validateAndSet("", 0, 0, 0);

  ok = false;
  if(dlg->exec()) {
    ok = true;
  }
  rc = dlg->lineEdit()->text();
  delete dlg;

  return rc;
#endif
}

void MyMoneyQifProfileEditor::slotDelete(void)
{
  TQString profile = m_profile.profileName().mid(8);

  if(KMessageBox::questionYesNo(this, i18n("Do you really want to delete profile '%1'?").arg(profile)) == KMessageBox::Yes) {
    int idx = m_profileListBox->currentItem();
    m_profile.saveProfile();
    deleteProfile(profile);
    loadProfileListFromConfig();
    if(idx >= static_cast<int> (m_profileListBox->count()))
      idx = m_profileListBox->count() - 1;

    slotLoadProfileFromConfig(m_profileListBox->text(idx));
  }
}

void MyMoneyQifProfileEditor::slotHelp(void)
{
  kapp->invokeHelp("details.impexp.qifimp.profile");
}

void MyMoneyQifProfileEditor::slotAmountTypeSelected(TQListViewItem* item)
{
  m_decimalBox->setCurrentText(item->text(2));
  m_thousandsBox->setCurrentText(item->text(3));
  m_selectedAmountType = item;
}

void MyMoneyQifProfileEditor::slotDecimalChanged(const TQString& val)
{
  if(m_selectedAmountType != 0) {
    TQChar key = m_selectedAmountType->text(1)[0];
    m_profile.setAmountDecimal(key, val[0]);
    m_selectedAmountType->setText(2, val);
  }
}

void MyMoneyQifProfileEditor::slotThousandsChanged(const TQString& val)
{
  if(m_selectedAmountType != 0) {
    TQChar key = m_selectedAmountType->text(1)[0];
    m_profile.setAmountThousands(key, val[0]);
    m_selectedAmountType->setText(3, val);
  }
}

const TQString MyMoneyQifProfileEditor::selectedProfile() const
{
  return m_profileListBox->currentText();
}

#include "mymoneyqifprofileeditor.moc"
