/*
 *
 *    soniK digital audio editor
 *    Copyright (C) 2003-2006  Robert Walker <rob@tenfoot.org.uk>
 *
 *    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., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
 *
 */

#include "editapplydialog.h"

// #include "editapplydialogbase.h"

#include <kmessagebox.h>
#include <klocale.h>
#include <kpushbutton.h>
#include <kstdguiitem.h>

#include <qframe.h>
#include <qcombobox.h>
#include <qpushbutton.h>
#include <qlineedit.h>
#include <qlayout.h>
#include <qlabel.h>

// #include <qobjectlist.h>

using Sonik::EditApplyDialog;


EditApplyDialog::EditApplyDialog(Edit::PluginContext* context,
                                 Edit::PresetManager* presetManager,
                                 QWidget* parent, const char* name)
  : QDialog(parent, name, false, Qt::WDestructiveClose),
    mContext(context),
    mPresetManager(presetManager),
    mWidget(0)
{

  createUi();

  mPresetNames = mPresetManager->presetNames();

  for (QStringList::const_iterator it = mPresetNames.begin();
       it != mPresetNames.end();
       ++it)
    mPreset->insertItem(*it);
  mPreset->setCurrentText("");
}


EditApplyDialog::~EditApplyDialog()
{
  delete mPresetManager;
  delete mContext;
}


void EditApplyDialog::createUi()
{
  QGridLayout* mainLayout = new QGridLayout(this, 1, 1, 11, 6, "mainLayout");

  mPluginFrame = new QFrame(this, "pluginFrame");
  mPluginFrame->setSizePolicy(QSizePolicy(QSizePolicy::MinimumExpanding, QSizePolicy::MinimumExpanding));
  mPluginFrame->setFrameShape(QFrame::NoFrame);
  mPluginFrame->setFrameShadow(QFrame::Raised);

  mainLayout->addWidget(mPluginFrame, 1, 0);

  QVBoxLayout* buttonLayout = new QVBoxLayout(0, 0, 6, "buttonLayout");

  KPushButton* buttonOk = new KPushButton(this, "buttonOk");
  buttonOk->setSizePolicy(QSizePolicy(QSizePolicy::Minimum, QSizePolicy::Minimum));
  buttonOk->setText(QString::null);
  buttonOk->setAutoDefault(true);
  buttonOk->setDefault(true);
  buttonOk->setGuiItem(KStdGuiItem::ok());
  connect(buttonOk, SIGNAL(clicked()),
          this, SLOT(accept()));
  buttonLayout->addWidget(buttonOk);

  KPushButton* buttonCancel = new KPushButton(this, "buttonCancel");
  buttonCancel->setSizePolicy(QSizePolicy(QSizePolicy::Minimum, QSizePolicy::Minimum));
  buttonCancel->setText(QString::null);
  buttonCancel->setGuiItem(KStdGuiItem::cancel());
  connect(buttonCancel, SIGNAL(clicked()),
          this, SLOT(reject()));
  buttonLayout->addWidget(buttonCancel);

  buttonLayout->addItem(new QSpacerItem(20, 20, QSizePolicy::Minimum, QSizePolicy::Expanding));

  mainLayout->addMultiCellLayout(buttonLayout, 0, 1, 1, 1);

  QHBoxLayout* presetLayout = new QHBoxLayout(0, 0, 6, "presetLayout");

  QLabel* presetLabel = new QLabel(this, "presetLabel");
  presetLabel->setText(i18n("Preset"));
  presetLayout->addWidget(presetLabel);

  mPreset = new QComboBox(FALSE, this, "preset");
  mPreset->setSizePolicy(QSizePolicy(QSizePolicy::MinimumExpanding, QSizePolicy::Fixed));
  mPreset->setEditable(true);
  connect(mPreset, SIGNAL(activated(int)),
          this, SLOT(presetChanged(int)));
  presetLayout->addWidget(mPreset);

  QPushButton* presetSaveBtn = new QPushButton(this, "presetSaveBtn");
  presetSaveBtn->setSizePolicy(QSizePolicy(QSizePolicy::Minimum, QSizePolicy::Fixed));
  presetSaveBtn->setText(i18n("Save"));
  connect(presetSaveBtn, SIGNAL(clicked()),
          this, SLOT(presetSave()));
  presetLayout->addWidget(presetSaveBtn);

  mainLayout->addLayout(presetLayout, 0, 0);

  setCaption(i18n("Apply Plugin"));
  setSizeGripEnabled(true);
}


void EditApplyDialog::setWidget(QWidget * w)
{
  mWidget = w;
  mWidget->reparent(mPluginFrame, QPoint(0, 0));
  QVBoxLayout* layout = new QVBoxLayout(mPluginFrame);
  layout->addWidget(mWidget);
}


void EditApplyDialog::releaseWidget()
{
  mWidget->reparent(0, QPoint(0, 0));
}


void EditApplyDialog::accept()
{
  // warn if preset name has changed, but is not saved
  if (mPreset->currentText() != "" &&
      mPreset->lineEdit()->isModified())
  {
    int res = KMessageBox::questionYesNoCancel(
      this, i18n("Save preset %1").arg(mPreset->currentText())
      );

    if (res == KMessageBox::Yes)
    {
      if (!presetSave())
        return;
    }
    else if (res == KMessageBox::Cancel)
    {
      return;
    }
  }

  mPresetManager->savePresets();

  emit applyPlugin(mContext);

  QDialog::accept();
}


void EditApplyDialog::presetChanged(int index)
{
  Edit::Preset preset = mPresetManager->preset(mPresetNames[index]);
  Edit::Preset::const_iterator param = preset.begin();
  for ( ; param != preset.end(); ++param)
  {
    UiControl* c = mContext->controls.find(param.key());
    if (c)
      c->setValue(*param);
  }
}


bool EditApplyDialog::presetSave()
{
  QString presetName;
  if (!mPreset->lineEdit()->isModified() &&
      mPreset->currentItem() < (int)mPresetNames.size())
  {
    presetName = mPresetNames[mPreset->currentItem()];
  }
  else
  {
    // TODO: what if current text (in German) is the same as English name of
    // another preset??
    presetName = mPreset->currentText();

    int existingIndex = mPresetNames.findIndex(presetName);
    if (existingIndex == -1)
    {
      mPresetNames.push_back(presetName);
      mPreset->insertItem(presetName);
      mPreset->setCurrentItem(mPreset->count()-1);
    }
    else
    {
      // TODO: allow user to choose another name
      int res = KMessageBox::questionYesNo(
        this, i18n("Preset %1 already exists. Overwrite?").arg(presetName)
        );
      if (res == KMessageBox::Yes)
        mPreset->setCurrentItem(existingIndex);
      else
        return false;
    }
  }

  Edit::Preset preset = mPresetManager->preset(presetName);

  UiControlPtrList::const_iterator c = mContext->controls.begin();
  for ( ; c != mContext->controls.end(); ++c)
    preset[(*c)->id()] = (*c)->value();

  mPresetManager->setPreset(presetName, preset);

  return true;
}
