/*
 *
 *    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
 *
 */
#ifndef SONIK_PART_WIDGET_H
#define SONIK_PART_WIDGET_H

#ifdef HAVE_CONFIG_H
#include <config.h>
#endif

#include <sonik/types.h>

#include <qwidget.h>
#include <qvaluevector.h>


class QScrollBar;
class QGridLayout;
class QVBoxLayout;

namespace Sonik
{
  class Part;
  class TimeScale;
  class ValueScale;
  class Zoom;
  class WaveWidget;
  class Display;
  class ActionManager;

  class PartWidget : public QWidget
  {
    Q_OBJECT
  public:

    PartWidget(Part& part, ActionManager& actionManager,
               QWidget* parent = 0, const char* name = 0);
    virtual ~PartWidget();

    off_t   selectionStart() const;
    size_t  selectionLength() const;
    void          select(off_t start, size_t length);

    off_t        cursorPos() const;
    void    setCursorPos(off_t pos);

    off_t      playbackPos() const;
    void  setPlaybackPos(off_t pos);

    TimeFormat  timeFormat() const;
    void        setTimeFormat(TimeFormat format);

    ValueFormat valueFormat() const;
    void        setValueFormat(ValueFormat format);

    float       zoom() const;
    void        zoomIn();
    void        zoomOut();

    Sonik::Display* display() const;
    void setDisplay(Sonik::Display* display);

    void print(QPrinter *pPrinter);
    QSize sizeHint() const;

  protected:
    virtual void resizeEvent(QResizeEvent *pEvent);
    virtual void mousePressEvent(QMouseEvent *e);
    virtual void mouseReleaseEvent(QMouseEvent *e);
    virtual void mouseMoveEvent(QMouseEvent *e);
    virtual void wheelEvent(QWheelEvent* e);
    virtual void contextMenuEvent(QContextMenuEvent *e);
    virtual void keyPressEvent(QKeyEvent* e);
    virtual void keyReleaseEvent(QKeyEvent* e);

  public slots:
    void scrollPosChanged(int);
    void zoomChanged(float value);

    void dataSampleRateChanged(uint32_t sampleRate);
    void dataBitsChanged(uint8_t bits);
    void dataChannelsChanged(uint8_t channels);
    void dataLengthChanged(size_t length);
    void dataDataChanged(uint8_t channel, off_t start, size_t length);

    void audioIOPlaying();
    void audioIORecording();
    void audioIOPaused();
    void audioIOStopped();
    void audioIOPosition(off_t pos);

    void updateAll();
    void resetView();

  signals:
    void selectionChanged(off_t start, size_t length);
    void displaySelectionChanged(off_t start, size_t length);
    void cursorPosChanged(off_t pos);
    void playbackPosChanged(off_t pos);

  private:
    enum SelectMode
    {
      kSelectModeNone,
      kSelectModeMouse,
      kSelectModeKeyboard
    };

    enum SelectState
    {
      kSelectNone,
      kSelectDragNew,
      kSelectDragAll,
      kSelectDragStart,
      kSelectDragEnd
    };

    void changeSelection(off_t start, size_t length);
    void updateMouseSelection(int pos, int xpos, bool finish);
    WaveWidget* makeWaveWidget(uint8_t channel);

    bool isWaveWidget(QWidget* w) const;
    bool isValueScale(QWidget* w) const;

    void setScreenPosRange();
    void setMinZoom();
    void updateValueScaleLabels();

    size_t samplesOnScreen() const;
    int    screenOffsetToSample(int screenPos) const;
    int    selectionScreenLeft() const;
    int    selectionScreenRight() const;

    Part&                     mParent;
    ActionManager&            mActionManager;

    QGridLayout*              mMainLayout;
    QVBoxLayout*              mDisplayLayout;
    QVBoxLayout*              mScaleLayout;
    QGridLayout*              mBottomLayout;

    TimeScale*                mTimeScale;
    QValueVector<WaveWidget*> mWaveWidgets;
    QValueVector<ValueScale*> mValueScales;
    Zoom*                     mScreenZoom;
    QScrollBar*               mScreenPos;

    uint                      mNumDisplays;
    ValueFormat               mValueFormat;
    Sonik::Display*           mCurrentDisplay;

    off_t                     mSelectionStart;
    size_t                    mSelectionLength;
    off_t                     mDisplaySelectionStart;
    size_t                    mDisplaySelectionLength;
    off_t                     mCursorPos;
    uint                      mScrollPos;
    float                     mZoom;

    off_t                     mPlaybackStartPos;
    off_t                     mPlaybackPos;

    SelectMode                mSelectMode;
    SelectState               mSelectState;
    int                       mSelectRefPoint;
    int                       mSelectRefPointScreenOffset;
    int                       mSelectDragLength;
  };
}

#endif // SONIK_PART_WIDGET_H
