/***************************************************************************
 *   Copyright (C) 2004 by Predrag Viceic                                  *
 *   viceic@net2000.ch                                             *
 *                                                                         *
 *   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.,                                       *
 *   59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.             *
 ***************************************************************************/
#ifndef DRAWSOUNDWIDGET_H
#define DRAWSOUNDWIDGET_H

#include <defs.h>
#include <sndfile.h>
#include <qpixmap.h>
#include <qbitmap.h>
#include <qwidget.h>
#include <qcanvas.h>
#include <qmutex.h>
#include <qpushbutton.h>
#include <qptrlist.h>
#include "beatline.h"
#include <qevent.h>
#include <qapplication.h>
#include <qprogressdialog.h>
#include <qcursor.h>
#include <limits.h>
#include <algorithm>
#include "wavecanvas.h"
#include "drawsoundwidgetabstract.h"
#include "playpositionchanged.h"
#include "loopmarker.h"
#include "measuremarker.h"
#include "selectionrectangle.h"
#include "verticalselectionrectangle.h"
#include "qtimer.h"
#include "playline.h"
#include "lockedbeatrect.h"
#include "beatlinelist.h"
#include "wavedrag.h"
#include "keyboardview.h"
#include "showinsertatrect.h"
#include "lockedbeatrectlist.h"
#ifdef HAS_MIDI
    #include "midiinputevent.h"
#endif
#include "pitchshiftrect.h"
#include <qapplication.h>

/**
@author Predrag Viceic
*/
class DrawSoundWidget : public DrawSoundWidgetAbstract{
Q_OBJECT
public:
        DrawSoundWidget(QWidget *parent,
                                            const char *name, SoundManager* sm);
        ~DrawSoundWidget();
        PlayLine* getPositionPointerCI();
        void fileLoaded();
        void updateBeatLines();
        void updateNewBeatLines();
        void setTreshold(int,bool);
        void setWindowDivider(int,bool);
        double computeBPM();
        double computeBPM2();
        void updateSelectionRectangles();
        void updateVerticalSelectionRectangles();
        void updateLoopMarkers();
        long zoomToSel();
        long zoomAll();


        void resized();
        void getNearestLinePos(QPoint,long& sample_pos, int& x);
        long getSelectionStartSample();
        long getSelectionEndSample();
        int getNbLockedBeats();
        void getBeats(long[]);
        void getLockedBeats(long[]);
        QValueList <int> getLockedMidiNotes();
        int getNbBeats();
        void customEvent(QCustomEvent*);
        double getComputedBPM();
        double getUsedBPM();
        bool hasLoopSet();
        long getLeftLoopMarkerSample();
        long getRightLoopMarkerSample();
        void swapMarkers();
        long findLeftBeatlinePos(long);
        long findRightBeatlinePos(long);
        long findNearestBeatlinePos(long);
        void setLoopMarkersOnMeasure(int);
    float getBeatDistance();
    void setComputedBPMModifier(double);
    void handleMouseMoveSelectionRectangles(QMouseEvent* me);
    void computePosFromMouse(QMouseEvent* me, int& pos_x, long& sample_pos);
    void handleMouseMoveVerticalSelectionRectangles(QMouseEvent* mouseEvent);
    void handleMouseMoveLoopMarkers(QMouseEvent* mouseEvent);
    void handleMouseMoveBeatRect(QMouseEvent* mouseEvent);
    BeatLine* getMovableBeatLine(QPoint pos);
    BeatLine* getLockableBeatLine(QPoint pos);
    BeatLine* getRemovableBeatLine(QPoint pos);
    BeatLine* getMovingBeatLine();
    BeatLine* getAssignableBeatLine(QPoint pos);
    LockedBeatRect* getMovableBeatRect(QPoint pos);
    LockedBeatRect* getPitchShiftableBeatRect(QPoint pos);
    LockedBeatRect* getMovingBeatRect();
    void handleMouseMoveBeatLine(QMouseEvent* mouseEvent);
    void checkAndScroll(QMouseEvent* ev);
    QValueList<long> toArray(QPtrList<BeatLine> beatlines);
    BeatLine* findNextLockedBeatLine(BeatLine* bl);
    QValueList<beatline_data> getLockedBeatList();
    LoopMarker* getLeftLoopMarker();
    LoopMarker* getRightLoopMarker();
    KeyboardView* keyboardView;
    QValueList <long> getBeatList();
    QValueList<beatline_data> toData(QPtrList <BeatLine>);
    QValueList<beatline_data> selectLockedBeatlinesList(long start, long end);
    QValueList<beatline_data> assignMissingMidi(QValueList <beatline_data>);
    BeatLine* findLeftLockedBeatLine(long pos);
    BeatLine* findRightLockedBeatLine(long pos);
    LockedBeatRectList getLockedBeatRects();
    LockedBeatRect* getLockedBeatRectFromTo(long start, long end);
    bool canUnlock(BeatLine* bl);
    LockedBeatRect* getLockedBeatRectFrom(long left);
    LockedBeatRect* getLockedBeatRectTo(long right);



    protected:
        void contentsMousePressEvent( QMouseEvent * );
        void contentsMouseReleaseEvent( QMouseEvent * );
        void contentsMouseMoveEvent( QMouseEvent * );
        void contentsDragEnterEvent(QDragEnterEvent* event);
        void contentsDragMoveEvent(QDragMoveEvent* event);
        void contentsDragLeaveEvent ( QDragLeaveEvent * );
        void contentsDropEvent(QDropEvent* event);
        void midiNoteReceived(int onnoff,int key, int velocity); 
        bool acceptDrop;

    public slots:
        void computeNewBPMLines(const QString &);
        void resample();
        void unlockBeatLines(bool force=FALSE);
        void lockBeatLines();
        void setBPMLines(bool on);
        void removeBPMLines();
        void removeSelectionRectangles();
        void removeBeatLines();
        void contentsMoved(int,int);
        void reinitCanvas();
        void setBeatLines(QMemArray<long>);
        void analysisFinished();
        void setPositionPointer(long);
        void addBeatLine(long);
        void addLockedBeatLine(long beat,int midiNote=-1);
        void cropped(long,long);
        void showBeatLines(bool);
        void scroll();
        void updateLockedBeatRects();
        void initLockedBeatLines(QValueList <beatline_data> lbl);
        void assignToScene(int sc);

	void setMainApplication(QApplication* theValue);
	
        
        



   signals:
        void bpmChange(const QString &);
        void visibleAreaChanged(long,long);
        void playFromPoint(long);
        void playFromTo(long,long);
        void stopPlay();
        void loopChange();
        void hasLockedBeatLines(bool);
        void receivedWave(QPoint,QString);
        void beatLinesChanged(QValueList<beatline_data> beatLines);
        void lockedBeatLinesChanged(QValueList<beatline_data> beatLines);
        void midiAssChanged(QValueList<beatline_data> bld);


private:
        QPixmap* soundpixmap;
        void zoomChanged();
        void midiEditingEnd();
    LockedBeatRect* getSNDBeatRect(QPoint pos);
        float savedRelativeSamplePos;
        QPoint scrollPos;
        QMouseEvent* storedMouse;

protected:
        PlayLine* playline;
        long playPosition;
        QMutex mutex;
        BeatLineList beatLines;
        BeatLineList lockedBeatLines;
        BeatLineList newBeatLines;
        LockedBeatRectList lockedBeatRects;
        SelectionRectangle* selection;
        QPtrList<VerticalSelectionRectangle>verticalSelections; // array of VerticalSelectionRectangles
        LoopMarker* loopMarkerL;
        LoopMarker* loopMarkerR;
        MeasureMarker* measureMarker;
        double computed_bpm;
        double new_to_oldBPM_ratio;
        int windowDivider;
        double treshold;
        QPtrList<BeatLine> bpmLines;
        bool showBeatLinesVal;
        float computedBPMModifier;
        SampleValueView* sampleValueView;
        QTimer* scrollTimer;
        ShowInsertAtRect* showInsertAtRect;
        PitchShiftRect* pitchshiftRect;
        QApplication* mainApplication;
        

protected slots:
    void sceneSwitched(int sc);
    void addStackElement(long start, long end, QString filename, long index, int scene, bool current);
};

#endif
