/***************************************************************************
 * trackveditiew.h: implementation of TrackEditView class
 *
 * This file is part of KTabEdit, a KDE tabulature editor
 *
 * copyright (C) 2003-2007 the KTabEdit development team <mrgwen@gmail.com>
 ***************************************************************************/

/***************************************************************************
 * 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.
 *
 * See the file COPYING for more information.
 ***************************************************************************/

#ifndef TRACKEDITVIEW_H
#define TRACKEDITVIEW_H

#include <QGraphicsView>
#include <QList>

#include "trackselection.h"

#include "tablature/tabproperties.h"
#include "tablature/tabduration.h"
#include "tablature/tabdynamic.h"
#include "tablature/tabslide.h"
#include "tablature/tabfingering.h"
#include "tablature/tabharmonic.h"
#include "tablature/tabvibrato.h"

#include "tablatureModel/tabtrackobserver.h"
#include "tablatureModel/trackposmodel.h"
#include "tablatureModel/trackposobserver.h"

#include "track/trackpagelist.h"

class QUndoStack;

class TabTrack;
class TabTrackModel;
class QPointCm;
class TimeSignature;
class TabChord;
class TabBend;
class TabGraceNote;
class TabTrill;
class QSizeCm;
class Cm;
class TabBar;
class TrackPageView;
class TrackSystemView;
class QRectCm;
class TrackBarView;
class TrackCursorView;
class TrackProperties;

class TrackEditView : public QGraphicsView, public TabTrackObserver, public TrackPosObserver {
	Q_OBJECT
public:
	TrackEditView(QUndoStack* commandHistory, QWidget* parent);
	virtual ~TrackEditView();
	
	virtual void songChanged(TabProperties* songProperties, TabTrack* tabTrack);
	virtual const TabProperties* songProperties() const;
	virtual TabTrack* tabTrack() const;
	virtual TrackProperties* tabTrackProperties() const;
	
	virtual TrackPos cursorPosition() const;
	
	virtual bool isReadOnly() const;
	virtual bool isModified() const;
	
	virtual void getSelection(TrackPos* begin, TrackPos* end) const;
	virtual bool hasSelection() const;
	
	virtual bool isViewScore() const;
	virtual bool isViewTablature() const;
	
	virtual QPointCm transformsXY(const QPoint& point) const;
	virtual void emitSignalsOfCurrentTime();
	
	virtual void connectTrack() const;
	virtual void disconnectTrack() const;
	
	virtual void noteEffectChanged(int bar, int time, int chord);
	virtual void noteChanged(int bar, int time, int note);
	virtual void timeChordChanged(int bar, int time);
	virtual void timeEffectChanged(int bar, int time);
	virtual void timeChanged(int bar, int time);
	virtual void barPropertyChanged(int bar);
	virtual void barMixChanged(int bar);
	virtual void barChanged(int bar);
	virtual void trackPropertyChanged();
	virtual void trackChanged();
	
	virtual void positionUpdated();
	
public slots:
	virtual void songPropertiesChanged(TabProperties* songProperties);
	virtual void songPropertyChanged();
	virtual void setTabTrack(TabTrack* tabTrack);
	
	virtual void setReadOnly(bool b);
	virtual void viewScore(bool on);
	virtual void viewTablature(bool b);
	
	virtual void zoomIn(int range);
	virtual void zoomOut(int range);
	
	virtual void setCursorPosition(const TrackPos& cursorPosition);
	virtual void setSelection(const TrackPos& begin, const TrackPos& end);
	virtual void selectAll(bool select=true);
	virtual void copy();
	virtual void cut();
	virtual void del();
	virtual void paste();
	
	virtual void insertTime();
	virtual void insertBar();
	virtual void deleteNote();
	virtual void deleteTime();
	virtual void deleteBar();
	
	virtual void setArmor(uchar armor);
	virtual void setTimeSignature(const TimeSignature& timeSignature);
	virtual void setDuration(Duration duration);
	virtual void switchDotted();
	virtual void setNTuplet(uint i);
	virtual void setRest();
	virtual void setDeadNote();
	virtual void setChord(const TabChord& tabChord);
	
	/***************************************************************************
	 *                                                                         *
	 * Effects actions                                                         *
	 *                                                                         *
	 ***************************************************************************/
	virtual void setAccentuated(bool b);
	virtual void setGhostNote(bool b);
	virtual void setTieNote(bool b);
	virtual void setHammerOnPullOff(bool b);
	virtual void setSlide(Slide slide);
	virtual void setLetRing(bool b);
	virtual void setDynamic(Dynamic dynamic);
	virtual void setFingeringLeft(TabFingering fingering);
	virtual void setFingeringRight(TabFingering fingering);
	virtual void setLeftHandVibrato(bool b);
	virtual void setPalmMute(bool b);
	virtual void setStaccato(bool b);
	virtual void setTremoloPicking(uchar c);
	virtual void setHarmonic(Harmonic harmonic);
	virtual void setBend(const TabBend& bend);
	virtual void setGraceNote(const TabGraceNote& graceNote);
	virtual void setTrill(const TabTrill& trill);
	virtual void setRasgueado(bool b);
	virtual void setPickStroke(bool b);
	virtual void setTremolo(uint i);
	virtual void setTapping(bool b);
	virtual void setPopping(bool b);
	virtual void setSlapping(bool b);
	virtual void setStroke(bool b);
	virtual void setVibrato(TabVibrato vibrato);
	virtual void setFadeIn(bool b);
	
	void refreshView();
signals:
	void isAccentuated(bool b);
	void isGhostNote(bool b);
	void isTieNote(bool b);
	void isHammerOnPullOff(bool b);
	void isSlide(bool b);
	void isLetRing(bool b);
	void isDynamic(bool b);
	void isFingeringLeft(bool b);
	void isFingeringRight(bool b);
	void isLeftHandVibrato(bool b);
	void isPalmMute(bool b);
	void isStaccato(bool b);
	void isTremoloPicking(bool b);
	void isHarmonic(bool b);
	void isBend(bool b);
	void isGraceNote(bool b);
	void isTrill(bool b);
	void isRasgueado(bool b);
	void isPickStroke(bool b);
	void isTremolo(bool b);
	void isTapping(bool b);
	void isPopping(bool b);
	void isSlapping(bool b);
	void isStroke(bool b);
	void isVibrato(bool b);
	void isFadeIn(bool b);
	
	/**
		This signal is emitted when bar or time is selected or de-selected in track view.
		
		When bar or time is selected this signal will be emitted with yes to TRUE. If no bar or time
		has been selected or if it bar or time is de-selected this signal is emitted with yes to FALSE.
		
		if yes is TRUE then copy() can be used to copy the selection to the clipboard. If yes is FALSE then
		copy() does nothing.
	*/
	void copyAvailable(bool yes);
	
protected:
	virtual void keyPressEvent(QKeyEvent* e);
	
	virtual void mousePressEvent(QMouseEvent* e);
	virtual void mouseMoveEvent(QMouseEvent* e);
	virtual void mouseReleaseEvent(QMouseEvent* e);
	
	virtual void paintEvent(QPaintEvent* event);
private:
	// Forwards declarations of all undo/redo commands
	//
	class InsertNoteCommand;
	class InsertTabCommand;
	class InsertBarCommand;
	class DeleteNoteCommand;
	class DeleteTimeCommand;
	class DeleteBarCommand;
	
	class SetLengthCommand;
	class MoveFingerCommand;
	class AddFXCommand;
	class SetFlagCommand;
	class DeleteNoteCommand;
	class AddColumnCommand;
	class DeleteColumnCommand;
	class SetTimeSigCommand;
	class InsertStrumCommand;
	class InsertRhythm;
	class NTupletCommand;
	
	class DeadNoteCommand;
	class RestNoteCommand;
	class DottedNoteCommand;
	class BendNoteCommand;
	class GhostNoteCommand;
	class TieNoteCommand;
	class HammerNoteCommand;
	class LetRingNoteCommand;
	
	static const uint sDpi;
	
	static const Cm sMargins;
	static const QSizeCm sPageSize;
	
	void initCanvasView();
	void initCursorView();
	void initPageViewer();
	
	/***************************************************************************
	 *                                                                         *
	 * Key actions                                                             *
	 *                                                                         *
	 ***************************************************************************/
	
	void keyLeft();
	void keyRight();
	void keyUp();
	void keyDown();
	
	void keyHome();
	void keyEnd();
	void keyCtrlHome();
	void keyCtrlEnd();
	
	void keyShiftLeft();
	void keyShiftRight();
	
	void keyPlus();
	void keyMinus();
	
	void keySemiColon();
	void keyNumber(uchar num);
	
	void smartDelete();
	
	/*!
		Calcul the size of a bar.
		\param tabBar the current bar.
		\return size the size of the bar.
	*/
	uint barSize(const TabBar&);
	
	/*!
		I DON'T KNOW
	*/
	void melodyEditorAction(int num, int fret, int action);
	
	/*!
		Display the current on the fretboard
	*/
	void currentTime();
	
	Cm barHeight() const;
	
	TrackPageView* allocAndInitPage(uint pageNumber);
	TrackPageView* createFirstPage(QRectCm* position);
	TrackPageView* createPage(uint pageNumber, QRectCm* position);
	
	TrackSystemView* createSystem(const QPointCm& position, QList<TrackBarView*>& system);
	bool appendIfBarIsGreater(TrackPageView* trackPage, QList<TrackBarView*>* barList, TrackBarView* barView);
	bool appendSystemOnPage(QRectCm* position, TrackPageView* trackPage, QList<TrackBarView*>* barList, TrackBarView* barView, uint barNumber, Cm* width, bool greaterBar);
	
	TrackBarView* barViewCreate(uint nb, uint firstBar);
	
	void clearView();
	
	void refreshPageAt(const TrackPos& position);
	
	void updateSystemAt(const TrackPos& position);
	void updateBarAt(const TrackPos& position);
	
	void refreshCursor();
	
	QUndoStack* mCommandHistory;
	
	QGraphicsScene* mCanvas;
	
	const TabProperties* mSongProperties;
	//TabTrack* mTabTrack;
	TabTrackModel* mTabTrack;
	
	TrackPosModel mCursorPosition;
	TrackCursorView* mCursorView;
	
	bool mReadOnly; /**< Track editor is in read-only mode if set to true */
	bool mModified; /**< Track has been modified if set to true */
	bool mViewScore; /**< Viewing the score if set to true */
	bool mViewTablature; /**< Viewing the tablature if set to true */
	QSize size; /**< Size of the widget */
	uint widthBar; /**< Width of the bars */
	
	bool mStartSelection;
	QRectF mSelection;
	TrackSelection mGraphicsSelection;
	TrackPos mBeginSelection;
	TrackPos mEndSelection;
	
	bool mIsSelection; /**< Something is selected if set to true */
	QFont mClefFont; /**< Font used for the clef */
	QFont mTimeFont; /**< Font used for the time signature */
	TrackPageList* mTrackPageList; /**< List of all pages */
	
	Cm mBarHeight;
};

#endif
