#ifndef _graphview_h__
#define _graphview_h__

#include <QDoubleSpinBox>
#include <QHash>
#include <QLabel>
#include <QList>
#include <QMap>
#include <QPushButton>
#include <QSpinBox>
#include <QVBoxLayout>
#include <QVector>
#include <QWidget>

#include "BigLabel.h"
#include "ConfigCheckBox.h"
#include "GraphLegendPreference.h"
#include "GraphQualityPreference.h"
#include "TDevice.h"
#include "WatchdogListener.h"
#include "qcustomplot.h"

class GraphView : public QWidget, public WatchdogListener {
    Q_OBJECT

  public:
    // Singleton instance
    static GraphView &instance() {
        static GraphView instance;
        return instance;
    }

    // Disable copy constructor and assignment operator
    // Required to enforce singleton pattern
    GraphView(GraphView const &) = delete;
    void operator=(GraphView const &) = delete;

    virtual ~GraphView();

    virtual void onThrash(int level);

  public slots:
    void addChannel(const QString &id);
    void removeChannel(const QString &id);
    void resetGraph();
    void saveGraph();
    void replot();
    void editTitle();
    void editLegend(QCPLegend *legend, QCPAbstractLegendItem *item, QMouseEvent *event);
    void editAxis(QCPAxis *axis, QCPAxis::SelectablePart part, QMouseEvent *event);

  private slots:

    void setIntervalMultiple(int m);
    void setGlobalInterval(int ms);
    void pauseUnpause();
    void update(const TDevice *device);
    void addData(QCPGraph *graph, double x, double y);

    void onChannelAliasUpdated(const QString id, const QString alias);
    void onAutoScaleChanged(bool ignored = true);
    void onYLogScaleChanged(bool ignored = true);
    void onGraphQualityChanged();
    void onGraphLegendChanged();
    void onBufferSizeSelected(int value);
    void applyBufferSize();

    void onGraphIntervalSelected(double value);
    void applyGraphInterval();
    void hideIntervalWarning();

  private:
    GraphView();

    QCPGraph *addGraph(const QString &channelId);
    void refreshBounds(int days);
    void refreshMemoryEstimate();

    QMap<QString, QCPGraph *> graphByChannelId;
    QHash<QCPGraph *, QString> channelIdByGraph;
    QHash<QString, int> deviceTicker;

    QCustomPlot *plot;
    QCPTextElement *title;

    QPushButton *PauseResumeButton;
    ConfigCheckBox *xAutoScaleCheckBox;
    ConfigCheckBox *yAutoScaleCheckBox;
    ConfigCheckBox *yLogScaleCheckBox;
    GraphQualityPreference *graphQualityPref;
    GraphLegendPreference *graphLegendPref;
    QSpinBox *bufferSpinBox;
    QTimer *bufferSpinBoxTimer;
    QLabel *memoryEstimateLabel;
    QLabel *graphIntervalWarningLabel;
    QPushButton *graphIntervalWarningButton;
    QDoubleSpinBox *graphIntervalSpinBox;
    QTimer *graphIntervalSpinBoxTimer;

    const int64_t origin;
    int globalInterval;
    int graphInterval;
    int graphIntervalMultiple;

    bool isPaused = false;
    double xMin;
    double xMax;
    double xBoundMin;
    double xBoundMax;

    class __WatchdogListener;
    friend class __WatchdogListener;
};

#endif
