/*
 *
 *    soniK digital audio editor
 *    Copyright (C) 2003-2004, 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
 *
 */
#ifndef SONIK_DATA_H
#define SONIK_DATA_H

#ifdef HAVE_CONFIG_H
# include "config.h"
#endif

#include "fileio.h"
#include "sonik_types.h"

#include <qobject.h>

#include <sys/types.h>

namespace Sonik
{
  class ActionManager;

  class Data : public QObject
  {
    Q_OBJECT
  public:
    Data(ActionManager& actionManager);
    virtual ~Data();

    uint8_t channels() const                  { return mChannels; }
    /*
     * add n channels after channel c
     */
    void   addChannels(uint8_t c, uint8_t n);
    /*
     * remove n channels from channel c (inclusive)
     */
    void   removeChannels(uint8_t c, uint8_t n);

    size_t length() const                    { return mLength; }
    void   insert(off_t start, size_t length);
    void   remove(off_t start, size_t length);

    uint32_t sampleRate() const                { return mSampleRate; }
    void     setSampleRate(uint32_t sampleRate);

    uint8_t  bits() const                      { return mBits; }
    void     setBits(uint8_t bits);

    Format   format() const;
    void     setFormat(const Format& format);

    /**
     * Retrieves the data from the given channel, converted to the appropriate
     * format.
     */
    void data(off_t start, size_t length,
              SampleSegment& data) const;
    void data(uint8_t channel, off_t start, size_t length,
              SampleBuffer& data) const;
    void data(uint8_t channel, off_t start, size_t length,
              Sample8Buffer& data) const;
    void data(uint8_t channel, off_t start, size_t length,
              Sample16Buffer& data) const;
    void data(uint8_t channel, off_t start, size_t length,
              Sample24Buffer& data) const;

    /**
     * Sets the data in a channel.
     * <i>data</i> is converted to the correct format if necessary.
     * <i>mData</i> is extended if necessary.
     */
    void setData(off_t start,
                 const SampleSegment& data);
    void setData(uint8_t channel, off_t start,
                 const SampleBuffer&   data);
    void setData(uint8_t channel, off_t start,
                 const Sample8Buffer&  data);
    void setData(uint8_t channel, off_t start,
                 const Sample16Buffer& data);
    void setData(uint8_t channel, off_t start,
                 const Sample24Buffer& data);

    void fillData(off_t start, size_t length,
                  const Sample& val=SampleTraits<Sample>::zero());
    void fillData(uint8_t channel, off_t start, size_t length,
                  const Sample& val=SampleTraits<Sample>::zero());
    void fillData(uint8_t channel, off_t start, size_t length,
                  const Sample8&  val=SampleTraits<Sample8>::zero());
    void fillData(uint8_t channel, off_t start, size_t length,
                  const Sample16& val=SampleTraits<Sample16>::zero());
    void fillData(uint8_t channel, off_t start, size_t length,
                  const Sample24& val=SampleTraits<Sample24>::zero());

    void compact();

    void reset(uint8_t channels, size_t length);

    IOResult open(FileIO::Reader& reader);
    IOResult save(FileIO::Writer& writer) const;

    void suspendSignals();
    void resumeSignals();

    //
    // Debug functions
    //
    size_t   chunkSize() const;
    uint32_t chunkCount() const;
    void     chunkInfo(uint32_t chunk, off_t& start, size_t& length) const;

  signals:
    void channelsChanged(uint8_t channels);
    void lengthChanged(size_t length);
    void sampleRateChanged(uint32_t sampleRate);
    void bitsChanged(uint8_t bits);
    void dataChanged(uint8_t channel, off_t start, size_t length);

  private:
    class DataPrivate;

    void recordSetDataUndoAction(uint8_t channel,
                                 off_t start, size_t length);

    ActionManager& mActionManager;

    uint8_t        mChannels;
    size_t         mLength;
    uint32_t       mSampleRate;
    uint8_t        mBits;

    DataPrivate*   d;
  };
}

#endif // SONIK_DATA_H
