/*
 *
 *    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 "insertpositonwidget.h"

#include "sonik_util.h"

#include <knuminput.h>
#include <klocale.h>

#include <qcombobox.h>
#include <qdatetimeedit.h>
#include <qlabel.h>
#include <qlayout.h>


using Sonik::InsertPositonWidget;

InsertPositonWidget::InsertPositonWidget(QWidget *parent, const char* name)
  : QWidget(parent, name),
    mSampleRate(1)
{
  createUi();

  mLastUnits = mLengthUnits->currentItem();
  lengthUnitsChanged(mLengthUnits->currentItem());

  connect(mLengthUnits, SIGNAL(activated(int)),
          this, SLOT(lengthUnitsChanged(int)));
}


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

  QLabel* positionLabel = new QLabel(this, "positionLabel");
  positionLabel->setText(i18n("Position:"));
  mainLayout->addWidget(positionLabel, 1, 0);

  QLabel* lengthLabel = new QLabel(this, "lengthLabel");
  lengthLabel->setText(i18n("Length:"));
  mainLayout->addWidget(lengthLabel, 0, 0);

  mPos = new QComboBox(FALSE, this, "mPos");
  mPos->insertItem(i18n("Insert at start"));
  mPos->insertItem(i18n("Insert at cursor"));
  mPos->insertItem(i18n("Insert at end"));
  mPos->insertItem(i18n("Overwrite from cursor"));
  mPos->insertItem(i18n("Replace selection"));
  mainLayout->addWidget(mPos, 1, 1);

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

  mLengthSamples = new KIntSpinBox(this, "mLengthSamples");
  mLengthSamples->setRange(0, 1 << 24);
  mLengthSamples->setSteps(10, 100);
  lengthLayout->addWidget(mLengthSamples);

  mLengthTime = new QTimeEdit(this, "mLengthTime");
  mLengthTime->setDisplay(QTimeEdit::Minutes | QTimeEdit::Seconds);
  mLengthTime->setRange(QTime(0, 0, 0), QTime(1, 0, 0));
  lengthLayout->addWidget(mLengthTime);

  mLengthSecs = new KDoubleSpinBox(this, "mLengthSecs");
  mLengthSecs->setRange(0, 3600, 1, 3);
  lengthLayout->addWidget(mLengthSecs);

  mLengthUnits = new QComboBox(FALSE, this, "mLengthUnits");
  mLengthUnits->insertItem(i18n("samples"));
  mLengthUnits->insertItem(i18n("mins"));
  mLengthUnits->insertItem(i18n("secs"));
  lengthLayout->addWidget(mLengthUnits);

  mainLayout->addLayout(lengthLayout, 0, 1);

//   languageChange();
//   resize(QSize(369, 74).expandedTo(minimumSizeHint()));
//   clearWState(WState_Polished);

  // tab order
  setTabOrder(mLengthSamples, mLengthTime);
  setTabOrder(mLengthTime, mLengthSecs);
  setTabOrder(mLengthSecs, mLengthUnits);
  setTabOrder(mLengthUnits, mPos);
}


void InsertPositonWidget::setSampleRate(uint32_t sampleRate)
{
  mSampleRate = sampleRate;
}


void InsertPositonWidget::setDefaults(uint32_t sampleRate, size_t selectionLength)
{
  setSampleRate(sampleRate);

  if (selectionLength > 0)
  {
    // selection set

    // default to replace selection
    mLengthSamples->setValue(selectionLength);
    mPos->setCurrentItem(4);
  }
  else
  {
    // no selection

    // default to 1.0s
    mLengthSamples->setValue(sampleRate);

    // remove replace selection option
    mPos->removeItem(4);
  }

  // default to seconds
  mLastUnits = 0;
  mLengthUnits->setCurrentItem(2);
  lengthUnitsChanged(2);
}


Sonik::InsertPosition InsertPositonWidget::position() const
{
  switch (mPos->currentItem())
  {
    case 0: return Sonik::kInsertStart;
    case 1: return Sonik::kInsertCursor;
    case 2: return Sonik::kInsertEnd;
    case 3: return Sonik::kOverwriteCursor;
    case 4: return Sonik::kReplaceSelection;
  }
  return Sonik::kInsertEnd;
}


void InsertPositonWidget::setPosition(Sonik::InsertPosition pos)
{
  mPos->setCurrentItem(pos);
}


int InsertPositonWidget::positionInt() const
{
  return static_cast<int>(position());
}


void InsertPositonWidget::setPositionInt(int pos)
{
  setPosition(static_cast<Sonik::InsertPosition>(pos));
}


size_t InsertPositonWidget::length() const
{
  return calculateLength(mLengthUnits->currentItem());
}


double InsertPositonWidget::lengthSecs() const
{
  if (mSampleRate == 0)
    return 0.0;
  else
    return (double)length() / mSampleRate;
}


void InsertPositonWidget::setLength(size_t length)
{
  switch (mLengthUnits->currentItem())
  {
    case 1:
      // time
      mLengthSamples->hide();
      mLengthTime->show();
      mLengthSecs->hide();
      mLengthTime->setTime(QTime(Sonik::hour(length, mSampleRate),
                                 Sonik::minute(length, mSampleRate),
                                 Sonik::sec(length, mSampleRate),
                                 Sonik::msec(length, mSampleRate)));
      break;

    case 2:
      // seconds
      mLengthSamples->hide();
      mLengthTime->hide();
      mLengthSecs->show();
      mLengthSecs->setValue((double)length / mSampleRate);
      break;

    case 0:
    default:
      // samples
      mLengthSamples->show();
      mLengthTime->hide();
      mLengthSecs->hide();
      mLengthSamples->setValue(length);
      break;
  }
}


void InsertPositonWidget::setLengthSecs(double secs)
{
  setLength((size_t)(secs * mSampleRate));
}


void InsertPositonWidget::selectionChanged(off_t /*start*/, size_t length)
{
  enableReplaceSelection(length != 0);
}


void InsertPositonWidget::enableReplaceSelection(bool enable)
{
  if (enable && mPos->count() == 4)
  {
    mPos->insertItem(i18n("Replace Selection"), 4);
  }
  else if (!enable && mPos->count() == 5)
  {
    // remove replace selection option
    if (mPos->currentItem() == 4)
      mPos->setCurrentItem(1); // insert at cursor

    mPos->removeItem(4);
  }
}


void InsertPositonWidget::lengthUnitsChanged(int index)
{
  setLength(calculateLength(mLastUnits));
  mLastUnits = index;
}


size_t InsertPositonWidget::calculateLength(int units) const
{
  size_t samples = 0;

  switch (units)
  {
    case 0:
      samples = (size_t)mLengthSamples->value();
      break;

    case 1:
      samples = Sonik::timeToSamples(mSampleRate,
                                     mLengthTime->time().hour(),
                                     mLengthTime->time().minute(),
                                     mLengthTime->time().second(),
                                     mLengthTime->time().msec());
      break;

    case 2:
      samples = Sonik::secondsToSamples(mSampleRate, mLengthSecs->value());
      break;
  }

  return samples;
}
