/*
 *
 *    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_H
#define SONIK_PART_H

#include <sonik/sonikpartiface.h>
#include <sonik/data.h>
#include <sonik/plugin.h>
#include <sonik/audioiomanager.h>
#include <sonik/actionmanager.h>

#include <sonik/util.h>
#include <sonik/types.h>

#include <kparts/part.h>
#include <dcopobject.h>

class QWidget;
class QPainter;
class KURL;
class QMultiLineEdit;
class KInstance;
class KAboutData;
class KAction;
class KRecentFilesAction;
class KToggleAction;
class KRadioAction;

namespace Sonik
{
  class PartWidget;
  class Display;
  class AudioIO;
  class RecordDialog;
  class ConfigDialog;

  /**
   * This is a "Part".  It that does all the real work in a KPart
   * application.
   *
   * @short Main Part
   * @author Rob Walker <rob@tenfoot.org.uk>
   * @version 0.1
   */
  class Part : public KParts::ReadWritePart,
               public SonikPartIface
  {
    Q_OBJECT
  public:

    enum ContextMenuType
    {
      kWaveWidget,
      kTimeScale,
      kValueScale,
    };

    Part(QWidget *parentWidget, const char *widgetName,
         QObject *parent, const char *name, const QStringList& args);
    virtual ~Part();

    static KAboutData* createAboutData();

    virtual void setModified(bool modified);

    Data&       data()        { return mData; }
    const Data& data() const  { return mData; }

    PartWidget*       partWidget();
    const PartWidget* partWidget() const;

    QString      fileFilter(bool write) const;

    PluginList  fileIOPlugins() const;
    PluginList audioIOPlugins() const;
    PluginList displayPlugins() const;
    PluginList    editPlugins() const;

    void        setDefaultDisplay(const QString& name);

    TimeFormat  timeFormat() const;
    void        setTimeFormat(Sonik::TimeFormat fmt);

    ValueFormat valueFormat() const;
    void        setValueFormat(Sonik::ValueFormat fmt);

    //
    // audio io control
    //
    void play(bool looping);
    void record(InsertPosition action);
    void stop();
    void seek(off_t pos);

    void contextMenu(ContextMenuType type, const QPoint& pos);

    bool formatDialog(QWidget *parent);

    //
    // DCOP functions
    //
  public:
    uint         cursorPos() const;
    uint         selectionStart() const;
    uint         selectionLength() const;

  public slots:
    //
    // ui slots
    //

    // file menu
    void uiFileSaveAs();

    // edit menu
    void uiEditUndo();
    void uiEditRedo();
    void uiEditCut();
    void uiEditCopy();
    void uiEditPaste();
    void uiEditDelete();
    void uiEditCrop();
    void uiEditSelectAll();
    void uiEditSelectNone();
    void uiEditSelectInvert();

    // view menu
    void uiViewZoomIn();
    void uiViewZoomOut();
    void uiViewTimeFormatChanged();
    void uiViewValueFormatChanged();

    // transport buttons
    void uiPlayStart();
    void uiPlayBack();
    void uiPlayForward();
    void uiPlayEnd();
    void uiPlayPlay();
    void uiPlayPlayLooped();
    void uiPlayPause();
    void uiPlayStop();
    void uiPlayRecord();

    // settings
    void uiSettingsConfigure();

    //
    // other slots
    //
    void initialized();

  protected slots:
    //
    // component signal handlers
    //
    void dataChannelsChanged(uint8_t channels);
    void dataLengthChanged(size_t length);
    void dataSampleRateChanged(uint32_t sampleRate);
    void dataBitsChanged(uint8_t bits);
    void dataDataChanged(uint8_t channel, off_t start, size_t length);

    void viewSelectionChanged(off_t start, size_t length);
    void viewDisplaySelectionChanged(off_t start, size_t length);
    void viewCursorPosChanged(off_t pos);
    void viewPlaybackPosChanged(off_t pos);

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

    void actionManagerUndoChanged(const QString& name);
    void actionManagerRedoChanged(const QString& name);

    // Dialog callbacks
    void recordDialogRecord();
    void recordDialogStop();
    void recordDialogFinished();

    void configDialogFinished();

    void selectDisplayPlugin(Sonik::Display* plugin);

  protected:
    virtual bool openFile();
    virtual bool saveFile();

  signals:
    void urlChanged(KURL& url);

    // forwarded signals

    // data
    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);

    // view
    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);

    // formats
    void timeFormatChanged(Sonik::TimeFormat fmt);
    void valueFormatChanged(Sonik::ValueFormat fmt);

    // audio io
    void playing();
    void recording();
    void paused();
    void stopped();
    void position(off_t pos);

  private:
    void           setupActions();
    void           setupPlugins();

    void           selectAudioIOPlugin(AudioIO* p);

    bool           fileSaveOptions(FileIO& fileIO);

    // File menu
    KAction*       mFileSave;

    // Edit menu
    KAction*       mEditUndo;
    KAction*       mEditRedo;
    KAction*       mEditCut;
    KAction*       mEditCopy;
    KAction*       mEditPaste;
    KAction*       mEditDelete;
    KAction*       mEditCrop;
    KAction*       mEditSelectAll;
    KAction*       mEditSelectNone;
    KAction*       mEditSelectInvert;
    KToggleAction* mViewToolBar;
    KToggleAction* mViewStatusBar;

    // View menu
    KAction*       mViewZoomIn;
    KAction*       mViewZoomOut;
    KRadioAction*  mViewTimeFormatSamples;
    KRadioAction*  mViewTimeFormatTime;
    KRadioAction*  mViewTimeFormatMillisec;
    KRadioAction*  mViewTimeFormatCDDAFrames;
    KRadioAction*  mViewTimeFormatPALFrames;
    KRadioAction*  mViewTimeFormatNTSCFrames;

    KRadioAction*  mViewValueFormatNormalised;
    KRadioAction*  mViewValueFormatReal;
    KRadioAction*  mViewValueFormatDb;

    // Play menu
    KAction*       mPlayStart;
    KAction*       mPlayBack;
    KAction*       mPlayForward;
    KAction*       mPlayEnd;
    KAction*       mPlayPlay;
    KAction*       mPlayPlayLooped;
    KAction*       mPlayPause;
    KAction*       mPlayStop;
    KAction*       mPlayRecord;

    ActionManager  mActionManager;
    Data           mData;

    uint           mId;
    bool           mOptionsDialogNeeded;

    PluginList     mFileIOPlugins;
    PluginList     mAudioIOPlugins;
    PluginList     mDisplayPlugins;
    PluginList     mEditPlugins;

    AudioIOManager mAudioIOManager;
    AudioIO*       mActiveAudioIOPlugin;

    FileIOFactory  mFileIOFactory;

    RecordDialog*  mRecordDialog;
    ConfigDialog*  mConfigDlg;

    off_t          mRecordStart;
    off_t          mLastPos;

    //
    // static data
    //
    static uint     sNextId;
    static bool     sNoAudioPluginsConfirmed;
  };
}

#endif // SONIK_PART_H
