/***************************************************************************
 *   Copyright (C) 2008 by S. MANKOWSKI / G. DE BURE support@mankowski.fr  *
 *                                                                         *
 *   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, see <http://www.gnu.org/licenses/>  *
 ***************************************************************************/
#ifndef SKGTABLEWITHGRAPH_H
#define SKGTABLEWITHGRAPH_H
/** @file
 * A table with graph with more features.
 *
 * @author Stephane MANKOWSKI / Guillaume DE BURE
 */
#include <QWidget>

#include <KGlobal>

#include "skgbasegui_export.h"
#include "ui_skgtablewithgraph.h"
#include "skgcombobox.h"
#include "skgservices.h"

class SKGGraphicsScene;
class KMenu;
class QTimer;
class QWidgetAction;
class QGraphicsItem;

/**
 * This file is a table with graph with more features
 */
class SKGBASEGUI_EXPORT SKGTableWithGraph : public QWidget
{
    Q_OBJECT

public:
    /**
     * Graph type
     */
    enum GraphType {STACK,
                    HISTOGRAM,
                    PIE,
                    CONCENTRICPIE,
                    POINT,
                    LINE,
                    STACKAREA,
                    BUBBLE,
                    STACKCOLUMNS
                   };
    /**
     * Additionel information to display
     */
    enum DisplayAdditional {NONE      = 0x0,
                            SUM       = 0x1,
                            AVERAGE   = 0x2,
                            LIMITS    = 0x4,
                            ALL       = 255
                           };
    /**
     * Graph type
     */
    Q_ENUMS(GraphType)
    /**
     * Additional information to display
     */
    Q_DECLARE_FLAGS(DisplayAdditionalFlag, DisplayAdditional)
    /**
     * State of the view
     */
    Q_PROPERTY(QString state READ getState WRITE setState)
    /**
     * Graph Type widget visibility
     */
    Q_PROPERTY(bool graphTypeSelectorVisible READ isGraphTypeSelectorVisible WRITE setGraphTypeSelectorVisible)
    /**
     * Items selectable or not
     */
    Q_PROPERTY(bool selectable READ isSelectable WRITE setSelectable)
    /**
     * Items with shadow or not
     */
    Q_PROPERTY(bool shadow READ isShadowVisible WRITE setShadowVisible)
    /**
     * Graph Type
     */
    Q_PROPERTY(GraphType graphType READ getGraphType WRITE setGraphType)

    /**
     * Default Constructor
     * @param iParent the parent
     */
    explicit SKGTableWithGraph(QWidget* iParent = 0);

    /**
     * Default Destructor
     */
    virtual ~SKGTableWithGraph();

Q_SIGNALS:
    /**
     * Emitted when a cell is double clicked
     * @param row row of the cell
     * @param column column of the cell
     */
    void cellDoubleClicked(int row, int column);

public Q_SLOTS:
    /**
    * Get the current state
    * MUST BE OVERWRITTEN
    * @return a string containing all information needed to set the same state.
    * Could be an XML stream
     */
    virtual QString getState();

    /**
     * Set the current state
     * MUST BE OVERWRITTEN
     * @param iState must be interpreted to set the state of the widget
     */
    virtual void setState(const QString& iState);

    /**
     * Returns the table.
     * @return table
     */
    virtual QTableWidget* table() const;

    /**
     * Returns the graph.
     * @return graph
     */
    virtual SKGGraphicsView* graph() const;

    /**
     * Returns the text report.
     * @return text report
     */
    virtual SKGWebView* textReport() const;

    /**
     * Set Data
     * @param iData the data
     * @param iPrimaryUnit the primary unit
     * @param iSecondaryUnit the secondary unit
     * @param iAdditionalInformation show sum and average columns
     * @param iNbVirtualColumn number of virtual columns
     */
    virtual void setData(const SKGStringListList& iData,
                         SKGServices::SKGUnitInfo iPrimaryUnit,
                         SKGServices::SKGUnitInfo iSecondaryUnit,
                         DisplayAdditionalFlag iAdditionalInformation = SKGTableWithGraph::ALL,
                         int iNbVirtualColumn = 0);

    /**
     * Get the mode for the additional display
     * @return the mode
     */
    virtual SKGTableWithGraph::DisplayAdditionalFlag getAdditionalDisplayMode() const;

    /**
     * Get the table content
     * @return the table content
     */
    virtual SKGStringListList getTable();

    /**
     * Get a pointer on the contextual menu of the table
     * @return contextual menu
     */
    virtual KMenu* getTableContextualMenu() const;

    /**
     * Get a pointer on the contextual menu of the graph
     * @return contextual menu
     */
    virtual KMenu* getGraphContextualMenu() const;

    /**
     * Set the visibility of the graph type selector zone
     * @param iVisible the visibility
     */
    virtual void setGraphTypeSelectorVisible(bool iVisible);

    /**
     * Get the visibility of the graph type selector zone
     * @return the visibility
     */
    virtual bool isGraphTypeSelectorVisible() const;

    /**
     * Enable / disable the selectability of items
     * @param iSelectable the selectability
     */
    virtual void setSelectable(bool iSelectable);

    /**
     * Get the selectability of items
     * @return the selectability
     */
    virtual bool isSelectable() const;

    /**
     * Enable / disable the shadows
     * @param iShadow the shadows
     */
    virtual void setShadowVisible(bool iShadow);

    /**
     * Get the shadows visibility
     * @return the visibility
     */
    virtual bool isShadowVisible() const;

    /**
     * Set the graph type
     * @param iType the type of graph
     */
    virtual void setGraphType(SKGTableWithGraph::GraphType iType) const;

    /**
     * Get the graph type
     *  @return the type of graph
     */
    virtual SKGTableWithGraph::GraphType getGraphType() const;

    /**
     * Get the number of columns
     * @param iWithComputed with compute columns (average, sum, forecast, ...) or not
     * @return the number of columns
     */
    virtual int getNbColumns(bool iWithComputed = false) const;

    /**
     * @brief Get show widget
     *
     * @return SKGShow*
     **/
    virtual SKGShow* getShowWidget() const;

    /**
     * Set tool bar visibility
     * @param iVisibility the visibility
     */
    virtual void setFilterVisibility(bool iVisibility) const;

    /**
     * Set the axis color
     * @param iColor the color
     */
    virtual void setAxisColor(const QColor& iColor = Qt::gray);

    /**
     * Set the grid color
     * @param iColor the color
     */
    virtual void setGridColor(const QColor& iColor = Qt::lightGray);

    /**
     * Set the min color
     * @param iColor the color
     */
    virtual void setMinColor(const QColor& iColor = Qt::red);

    /**
     * Set the max color
     * @param iColor the color
     */
    virtual void setMaxColor(const QColor& iColor = Qt::green);

    /**
     * Set the pareto color
     * @param iColor the color
     */
    virtual void setParetoColor(const QColor& iColor = Qt::darkRed);

    /**
     * Set the average color
     * @param iColor the color
     */
    virtual void setAverageColor(const QColor& iColor = Qt::blue);

    /**
     * Set the tendency color
     * @param iColor the color
     */
    virtual void setTendencyColor(const QColor& iColor = Qt::darkYellow);

    /**
     * Set the outline color
     * @param iColor the color
     */
    virtual void setOutlineColor(const QColor& iColor = Qt::black);

    /**
     * Set the background color
     * @param iColor the color
     */
    virtual void setBackgroundColor(const QColor& iColor = Qt::white);

    /**
     * Set the text color
     * @param iColor the color
     */
    virtual void setTextColor(const QColor& iColor = Qt::black);

    /**
     * Set antialiasing
     * @param iAntialiasing enabled or disabled
     */
    virtual void setAntialiasing(bool iAntialiasing = true);

    /**
     * Redraw the graph after some milliseconds
     */
    virtual void redrawGraphDelayed();

    /**
     * To know if the table is visible
     * @return the visibility
     */
    virtual bool isTableVisible() const;

    /**
     * To know if the graph is visible
     * @return the visibility
     */
    virtual bool isGraphVisible() const;

    /**
     * To know if the text report is visible
     * @return the visibility
     */
    virtual bool isTextReportVisible() const;

    /**
     * Switch the limits visibility
     * @return the new visibility
     */
    virtual bool switchLimitsVisibility();

    /**
     * Switch the average visibility
     * @return the new visibility
     */
    virtual bool switchAverageVisibility();

    /**
     * Switch the linear regression visibility
     * @return the new visibility
     */
    virtual bool switchLinearRegressionVisibility();

    /**
     * Switch the pareto curve visibility
     * @return the new visibility
     */
    virtual bool switchParetoVisibility();

    /**
     * Switch the legend visibility
     * @return the new visibility
     */
    virtual bool switchLegendVisibility();

    /**
     * Switch the origin visibility
     * @return the new visibility
     */
    virtual bool swithOriginVisibility();

    /**
     * Reset the colors
     */
    virtual void resetColors();

    /**
     * Export to a file
     * @param iFileName the file name
     * @return an object managing the error
     *   @see SKGError
     */
    virtual SKGError exportInFile(const QString& iFileName);

Q_SIGNALS:
    /**
     * Selection changed
     */
    void selectionChanged();

private Q_SLOTS:
    void onExport();
    void onSelectionChanged();
    void onSelectionChangedInGraph();
    void onDoubleClick(int row, int column);
    void onDoubleClickGraph();
    void onFilterModified();
    void onDisplayModeChanged();
    void onChangeColor();
    void onHorizontalScrollBarChanged(int);
    void refresh();
    void redrawText();
    void redrawGraph();
    void showMenu(const QPoint& iPos);

private:
    Q_DISABLE_COPY(SKGTableWithGraph)

    double computeStepSize(double iRange, double iTargetSteps);
    void addArrow(const QPointF& iPeak, double iSize, double iArrowAngle = 45, double iDegree = 90);
    void addLegend(const QPointF& iPosition, double iSize, double iScaleText, double iMaxY);
    QGraphicsItem* drawPoint(qreal iX, qreal iY, qreal iRadius, int iMode, const QBrush& iBrush);
    int getAverageColumnIndex() const;
    int getMinColumnIndex() const;

    QStringList getSumItems(const QString& iString) const;
    void addSums(SKGStringListList& ioTable, int& iNblines);

    static bool listSort(const QStringList& s1, const QStringList& s2);
    static Qt::SortOrder m_sortOrder;
    static int m_sortColumn;

    Ui::skgtablewithgraph_base ui;
    SKGGraphicsScene* m_scene;

    SKGStringListList m_data;
    QList<bool> m_sumRows;
    SKGServices::SKGUnitInfo m_primaryUnit;
    SKGServices::SKGUnitInfo m_secondaryUnit;
    DisplayAdditionalFlag m_additionalInformation;
    int m_nbVirtualColumns;
    bool m_selectable;
    bool m_toolBarVisible;
    bool m_graphTypeVisible;
    bool m_limitVisible;
    bool m_averageVisible;
    bool m_linearRegressionVisible;
    bool m_paretoVisible;
    bool m_legendVisible;
    bool m_graphVisible;
    bool m_tableVisible;
    bool m_textVisible;
    bool m_zeroVisible;
    bool m_shadow;

    KMenu* m_mainMenu;
    QTimer m_timer;
    QTimer m_timerRedraw;
    QAction* m_actShowLimits;
    QAction* m_actShowAverage;
    QAction* m_actShowLinearRegression;
    QAction* m_actShowPareto;
    QAction* m_actShowLegend;
    QAction* m_actShowZero;
    QAction* m_allPositiveMenu;
    QWidgetAction* m_displayModeWidget;

    int m_indexSum;
    int m_indexAverage;
    int m_indexMin;
    int m_indexLinearRegression;
    QMap<QString, QColor> m_mapTitleColor;
    QMap<QTableWidgetItem*, QGraphicsItem*> m_mapItemGraphic;

    QColor m_axisColor;
    QColor m_backgroundColor;
    QColor m_textColor;
    QColor m_gridColor;
    QColor m_minColor;
    QColor m_maxColor;
    QColor m_paretoColor;
    QColor m_averageColor;
    QColor m_tendencyColor;
    QColor m_outlineColor;
    QBrush m_NegativeColor;
    QBrush m_WhiteColor;

    SKGComboBox* m_displayMode;
};

Q_DECLARE_OPERATORS_FOR_FLAGS(SKGTableWithGraph::DisplayAdditionalFlag)

#endif  // SKGTABLEWITHGRAPH_H
