/*
 *
 *    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 "reverse.h"
#include "data.h"
#include "partwidget.h"
#include "actionmanager.h"

#include "sonik_sigproc.h"

#include <kaction.h>
#include <klocale.h>
#include <kgenericfactory.h>
#include <kdebug.h>

using Sonik::ReversePlugin;

ReversePlugin::ReversePlugin(QObject* parent, const char* name,
                             const QStringList& args)
  : Sonik::Edit("reverse", i18n("Reverse"), parent, name, args)
{
  new KAction(i18n("Reverse"), 0,
              this, SLOT(uiTransformReverse()),
              actionCollection(),
              "transform_reverse");
}

ReversePlugin::~ReversePlugin()
{
}

QWidget* ReversePlugin::makeConfigPage(QWidget*)
{
  return 0;
}

void ReversePlugin::applyConfigPage()
{
}

void ReversePlugin::uiTransformReverse()
{
  off_t  start;
  std::size_t length;
  if (mWidget->selectionLength() > 0)
  {
    start = mWidget->selectionStart();
    length = mWidget->selectionLength();
  }
  else
  {
    start = 0;
    length = mData->length();
  }

  mActionManager->beginCompoundAction(i18n("Reverse"));

  const std::size_t kBlocksize = 1024;

  SampleSegment seg1(mData->channels(), kBlocksize);
  SampleSegment seg2(mData->channels(), kBlocksize);

  off_t       pos1  = start;
  off_t       pos2  = start + length;
  std::size_t left = length / 2;
  while (left)
  {
    std::size_t cnt = (left <= kBlocksize) ? left : kBlocksize;

    mData->data(pos1, cnt, seg1);
    mData->data(pos2-cnt, cnt, seg2);

    for (uint8_t ch = 0; ch < mData->channels(); ++ch)
    {
      Sonik::reverse(seg1.data(ch), cnt);
      Sonik::reverse(seg2.data(ch), cnt);
    }

    mData->setData(pos1, seg2);
    mData->setData(pos2-cnt, seg1);

    left -= cnt;
    pos1 += cnt;
    pos2 -= cnt;
  }

  mActionManager->endCompoundAction();
}

//
// Factory definition
//
K_EXPORT_COMPONENT_FACTORY(libsonik_editreverse,
                           KGenericFactory<ReversePlugin>(
                             "sonikpart-edit-reverse")
                           );
