/* This file is part of the KDE project

   SPDX-FileCopyrightText: 2007-2008 Johannes Simon <johannes.simon@gmail.com>
   SPDX-FileCopyrightText: 2010 Carlos Licea <carlos@kdab.com>
   SPDX-FileCopyrightText: 2010 Nokia Corporation and /or its subsidiary(-ies).
     Contact: Suresh Chande suresh.chande@nokia.com

   SPDX-License-Identifier: LGPL-2.0-or-later
 */

#ifndef KCHART_DATASET_H
#define KCHART_DATASET_H

// Qt
#include <QDebug>
#include <QPen>

// KoChart
#include "CellRegion.h"
#include "ChartShape.h"

namespace KChart
{
class DataValueAttributes;
class PieAttributes;
class MarkerAttributes;
}

class KoShapeLoadingContext;

namespace KoChart
{

class KChartModel;

/**
 * @brief The DataSet class stores properties of a single data series.
 *
 * A global chart type can be overridden by setting a specific type
 * on a data series.
 *
 * To change properties of a single data point inside a data series,
 * use section's like for example \a brush(int section) where the
 * section refers to the data-point number.
 */

class DataSet
{
public:
    explicit DataSet(int dataSetNr);
    ~DataSet();

    // Getter methods
    QString title() const;
    ChartType chartType() const;
    ChartSubtype chartSubType() const;
    Axis *attachedAxis() const;

    /**
     * Describes ODF attribute chart:data-label-number from §15.32.3
     */
    class ValueLabelType
    {
    public:
        /// Show value as number.
        bool number;
        bool numberIsLoaded;
        /// Show value as percentage.
        bool percentage;
        bool percentageIsLoaded;
        /// Show category.
        bool category;
        bool categoryIsLoaded;
        /// Show legend key.
        /// TODO: not supported by KChart
        bool symbol;
        bool symbolIsLoaded;
        /// Constructor.
        explicit ValueLabelType(bool number = false,
                                bool percentage = false,
                                bool category = false,
                                bool symbol = true) // to keep old behaviour where symbols were displayed by default
            : number(number)
            , numberIsLoaded(false)
            , percentage(percentage)
            , percentageIsLoaded(false)
            , category(category)
            , categoryIsLoaded(false)
            , symbol(symbol)
            , symbolIsLoaded(false)
        {
        }

        /// Returns true if no label will be displayed.
        bool noLabel() const
        {
            return !number && !percentage && !category && !symbol;
        }
    };

    /**
     * Sets the value label type. \see ValueLabelType
     *
     * \param section The data point to set this type for. -1 will set
     * a series-wide value
     */
    void setValueLabelType(const ValueLabelType &type, int section = -1);

    /**
     * \return the value label type.
     * \see ValueLabelType
     *
     * \param section The data point to return the type for. -1 will return
     * the series-wide value
     */
    ValueLabelType valueLabelType(int section = -1) const;

    /**
     * Sets the marker attributes of the series
     *
     * \param section The data point to set this type for. -1 will set
     * a series-wide value
     */
    void setMarkerAttributes(const KChart::MarkerAttributes &attribs, int section = -1);

    /**
     * \return the MarkerAttributes.
     * \see ValueLabelType
     *
     * \param section The data point to return the MarkerAttributes for. -1 will return
     * the series-wide value
     */
    KChart::MarkerAttributes getMarkerAttributes(int section = -1) const;

    // Graphics properties for the visualization of this dataset.
    QPen pen() const;
    QBrush brush() const;
    QIcon markerIcon(OdfMarkerStyle markerStyle);
    KChart::PieAttributes pieAttributes() const;
    QPen pen(int section) const;
    QBrush brush(int section) const;
    KChart::PieAttributes pieAttributes(int section) const;
    KChart::DataValueAttributes dataValueAttributes(int section = -1) const;
    int number() const;

    bool showMeanValue() const;
    QPen meanValuePen() const;

    bool showLowerErrorIndicator() const;
    bool showUpperErrorIndicator() const;
    QPen errorIndicatorPen() const;
    ErrorCategory errorCategory() const;
    qreal errorPercentage() const;
    qreal errorMargin() const;
    qreal lowerErrorLimit() const;
    qreal upperErrorLimit() const;
    /// returns the marker symbol type to use
    OdfSymbolType odfSymbolType() const;
    /// Set symbol type to @p type and marker style to @p style
    void setOdfSymbolType(OdfSymbolType type);
    OdfMarkerStyle markerStyle() const;
    void setMarkerStyle(OdfMarkerStyle style);

    // Setter methods
    void setChartType(ChartType type);
    void setChartSubType(ChartSubtype type);
    void setAttachedAxis(Axis *axis);

    void setPen(const QPen &pen);
    void setBrush(const QBrush &brush);
    void setPen(int section, const QPen &pen);
    void setBrush(int section, const QBrush &brush);

    void setPieExplodeFactor(int factor);
    void setPieExplodeFactor(int section, int factor);

    void setShowMeanValue(bool b);
    void setMeanValuePen(const QPen &pen);

    void setShowLowerErrorIndicator(bool b);
    void setShowUpperErrorIndicator(bool b);
    void setShowErrorIndicators(bool lower, bool upper);
    void setErrorIndicatorPen(const QPen &pen);
    void setErrorCategory(ErrorCategory category);
    void setErrorPercentage(qreal percentage);
    void setErrorMargin(qreal margin);
    void setLowerErrorLimit(qreal limit);
    void setUpperErrorLimit(qreal limit);

    /**
     * Returns the x-data.
     *
     * \param index the unique index that identifies the cell.
     * \param role either Qt::DisplayRole if the content displayed
     * in the cell (aka the displayText()) should be returned or
     * Qt::EditRole if the actual data of the cell (which can be
     * different from what is displayed) should be returned.
     * \return the x-data value.
     */
    QVariant xData(int index, int role = Qt::EditRole) const;

    /**
     * Returns the y-data aka value-data.
     *
     * \param index the unique index that identifies the cell.
     * \param role either Qt::DisplayRole if the content displayed
     * in the cell (aka the displayText()) should be returned or
     * Qt::EditRole if the actual data of the cell (which can be
     * different from what is displayed) should be returned.
     * \return the y-data value.
     */
    QVariant yData(int index, int role = Qt::EditRole) const;

    /**
     * Used for bubble width in bubble charts. May also be referred to as
     * 'z data' in some cases.
     */
    QVariant customData(int index, int role = Qt::EditRole) const;

    QVariant categoryData(int index, int role = Qt::EditRole) const;

    QVariant labelData() const;
    QString defaultLabelData() const;

    CellRegion xDataRegion() const;
    CellRegion yDataRegion() const;
    CellRegion customDataRegion() const;
    CellRegion categoryDataRegion() const;
    CellRegion labelDataRegion() const;
    // TODO: Region for custom colors

    void setXDataRegion(const CellRegion &region);
    void setYDataRegion(const CellRegion &region);
    void setCustomDataRegion(const CellRegion &region);
    void setCategoryDataRegion(const CellRegion &region);
    void setLabelDataRegion(const CellRegion &region);

    int size() const;
    int dimension() const;

    // Called by the proxy model
    void yDataChanged(const QRect &region) const;
    void xDataChanged(const QRect &region) const;
    void customDataChanged(const QRect &region) const;
    void labelDataChanged(const QRect &region) const;
    void categoryDataChanged(const QRect &region) const;

    void setKdChartModel(KChartModel *model);
    KChartModel *kdChartModel() const;

    bool loadOdf(const KoXmlElement &n, KoShapeLoadingContext &context);
    bool loadSeriesIntoDataset(const KoXmlElement &n, KoShapeLoadingContext &context);
    /**
     * Saves a series to ODF. Creates a new chart:series element.
     */
    void saveOdf(KoShapeSavingContext &context) const;

    QString axisName() const;

private:
    class Private;
    Private *const d;
};

} // Namespace KoChart

QDebug operator<<(QDebug dbg, const KoChart::DataSet *ds);
QDebug operator<<(QDebug dbg, const KoChart::DataSet::ValueLabelType &v);

#endif // KCHART_DATASET_H
