/*
    Virtual Piano Widget for Qt5
    Copyright (C) 2008-2022, Pedro Lopez-Cabanillas <plcl@users.sf.net>

    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 3 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, see <http://www.gnu.org/licenses/>.
*/

#ifndef PIANOSCENE_H_
#define PIANOSCENE_H_

#include <QGraphicsScene>
#include <QScopedPointer>
#include <QHash>
#include <drumstick/pianokeybd.h>
#include <drumstick/pianopalette.h>
#include "pianokey.h"
#include "keylabel.h"

/**
 * @file pianoscene.h
 * PianoScene class declaration
 */

namespace drumstick { namespace widgets {

    /**
     * @addtogroup Widgets
     * @{
     *
     * @class PianoScene
     * The PianoScene class is a QGraphicsScene composed by a number of graphics items:
     * the piano keys.
     */
    class DRUMSTICK_EXPORT PianoScene : public QGraphicsScene
    {
        Q_OBJECT
    public:
        PianoScene ( const int baseOctave,
                     const int numKeys,
                     const int startKey,
                     const QColor& keyPressedColor = QColor(),
                     QObject * parent = nullptr );
        ~PianoScene();

        QSize sizeHint() const;
        void setKeyboardMap( KeyboardMap *map );
        KeyboardMap *getKeyboardMap() const;
        PianoHandler *getPianoHandler() const;
        void setPianoHandler(PianoHandler *handler);

        PianoPalette getHighlightPalette();
        void setHighlightPalette( const PianoPalette& p );
        PianoPalette getBackgroundPalette();
        void setBackgroundPalette( const PianoPalette& p );
        PianoPalette getForegroundPalette();
        void setForegroundPalette( const PianoPalette& p );

        bool showColorScale() const;
        void setShowColorScale(const bool show);

        QColor getKeyPressedColor() const;
        void setKeyPressedColor(const QColor& color);
        void resetKeyPressedColor();

        int getMinNote() const;
        void setMinNote(const int note);
        int getMaxNote() const;
        void setMaxNote(const int note);
        int getTranspose() const;
        void setTranspose(const int transpose);

        LabelVisibility showLabels() const;
        void setShowLabels(const LabelVisibility show);
        LabelAlteration alterations() const;
        void setAlterations(const LabelAlteration use);
        LabelCentralOctave getOctave() const;
        void setOctave(const LabelCentralOctave octave);
        LabelOrientation getOrientation() const;
        void setOrientation(const LabelOrientation orientation);

        bool isKeyboardEnabled() const;
        void setKeyboardEnabled( const bool enable );
        bool isMouseEnabled() const;
        void setMouseEnabled( const bool enable );
        bool isTouchEnabled() const;
        void setTouchEnabled( const bool enable );
        bool velocityTint() const;
        void setVelocityTint( const bool enable );
        bool isOctaveStart( const int note );

        void showNoteOn( const int note, QColor color, int vel = -1 );
        void showNoteOn( const int note, int vel = -1 );
        void showNoteOff( const int note, int vel = -1 );
        int baseOctave() const;
        void setBaseOctave( const int base );
        int numKeys() const;
        int startKey() const;
        void allKeysOff();
        void keyOn( const int note );
        void keyOff( const int note );
        bool getRawKeyboardMode() const;
        void setRawKeyboardMode(const bool b);
        void useCustomNoteNames(const QStringList& names);
        void useStandardNoteNames();
        QStringList customNoteNames() const;
        QStringList standardNoteNames() const;
        int getVelocity();
        void setVelocity(const int velocity);
        int getChannel() const;
        void setChannel(const int channel);
        void retranslate();
        void refreshLabels();
        void hideOrShowKeys();
        void refreshKeys();

        void setKeyPicture(const bool natural, const QPixmap& pix);
        QPixmap getKeyPicture(const bool natural);

        void setUseKeyPictures(const bool enable);
        bool getUseKeyPictures() const;

        void saveData(QByteArray& ba);
        void loadData(QByteArray& ba);

    signals:
        /**
         * This signal is emitted for each Note On MIDI event created using
         * the computer keyboard, mouse or touch screen. It is not emitted if
         * a PianoHandler has been assigned using setPianoHandler().
         * @param n the MIDI note number
         * @param v the MIDI velocity
         */
        void noteOn(int n, int v);
        /**
         * This signal is emitted for each Note Off MIDI event created using
         * the computer keyboard, mouse or touch screen. It is not emitted if
         * a PianoHandler has been assigned using setPianoHandler().
         * @param n the MIDI note number
         * @param v the MIDI velocity
         */
        void noteOff(int n, int v);
        /**
         * signalName is emitted for each note created, and contains a string
         * with the MIDI note number and the note name for each note on event.
         * @param name the MIDI note number and name
         */
        void signalName(const QString& name);

    protected:
        void showKeyOn( PianoKey *key, QColor color, int vel );
        void showKeyOn( PianoKey *key, int vel );
        void showKeyOff( PianoKey *key, int vel );
        void displayKeyOn(PianoKey *key);
        void keyOn( PianoKey *key );
        void keyOff( PianoKey *key );
        void keyOn( PianoKey *key, qreal pressure );
        void keyOff( PianoKey *key, qreal pressure );
        PianoKey *getKeyForPos( const QPointF &p ) const;
        PianoKey *getPianoKey( const int key ) const;
        QString noteName( PianoKey *key );
        void mouseMoveEvent ( QGraphicsSceneMouseEvent *mouseEvent ) override;
        void mousePressEvent ( QGraphicsSceneMouseEvent *mouseEvent ) override;
        void mouseReleaseEvent ( QGraphicsSceneMouseEvent *mouseEvent ) override;
        void keyPressEvent ( QKeyEvent *keyEvent ) override;
        void keyReleaseEvent ( QKeyEvent *keyEvent ) override;
        bool event(QEvent *event) override;

        void triggerNoteOn( const int note, const int vel );
        void triggerNoteOff( const int note, const int vel );
        int getNoteFromKey( const int key ) const;
        void setHighlightColorFromPolicy(PianoKey *key, const int vel);

    private:
        class PianoScenePrivate;
        QScopedPointer<PianoScenePrivate> d;
    };

/** @} */

}} // namespace drumstick::widgets

#endif /*PIANOSCENE_H_*/
