#include "dpBarsChart.h"
//#include "dataManager.h"
#include "measurementDataManager.h"

CustomBars::CustomBars(QCPAxis* keyAxis, QCPAxis* valueAxis)
    : QCPBars(keyAxis, valueAxis),
    m_textVisible(false),
    m_textAlignment(Qt::AlignCenter),
    m_spacing(5),
    m_font(QFont(QLatin1String("sans serif"), 12))
{}

void CustomBars::setTextVisible(bool visible)
{
    m_textVisible = visible;
}

void CustomBars::setTextAlignment(Qt::Alignment alignment)
{
    m_textAlignment = alignment;
}

void CustomBars::setSpacing(double spacing)
{
    m_spacing = spacing;
}

void CustomBars::setFont(QFont font)
{
    m_font = font;
}

void CustomBars::draw(QCPPainter* painter)
{
    ///源码拷贝
    if (!mKeyAxis || !mValueAxis) { qDebug() << Q_FUNC_INFO << "invalid key or value axis"; return; }
    if (mDataContainer->isEmpty()) return;

    QCPBarsDataContainer::const_iterator visibleBegin, visibleEnd;
    getVisibleDataBounds(visibleBegin, visibleEnd);

    // loop over and draw segments of unselected/selected data:
    QList<QCPDataRange> selectedSegments, unselectedSegments, allSegments;
    getDataSegments(selectedSegments, unselectedSegments);
    allSegments << unselectedSegments << selectedSegments;
    for (int i=0; i<allSegments.size(); ++i)
    {
        bool isSelectedSegment = i >= unselectedSegments.size();
        QCPBarsDataContainer::const_iterator begin = visibleBegin;
        QCPBarsDataContainer::const_iterator end = visibleEnd;
        mDataContainer->limitIteratorsToDataRange(begin, end, allSegments.at(i));
        if (begin == end)
            continue;

        for (QCPBarsDataContainer::const_iterator it=begin; it!=end; ++it)
        {
            // check data validity if flag set:
#ifdef QCUSTOMPLOT_CHECK_DATA
            if (QCP::isInvalidData(it->key, it->value))
                qDebug() << Q_FUNC_INFO << "Data point at" << it->key << "of drawn range invalid." << "Plottable name:" << name();
#endif
            // draw bar:
            if (isSelectedSegment && mSelectionDecorator)
            {
                mSelectionDecorator->applyBrush(painter);
                mSelectionDecorator->applyPen(painter);
            } else
            {
                painter->setBrush(mBrush);
                painter->setPen(mPen);
            }
            applyDefaultAntialiasingHint(painter);
            painter->drawPolygon(getBarRect(it->key, it->value));

            ///---自定义逻辑-start---
            //draw text
            if(m_textVisible)
            {
                QRectF barRect = getBarRect(it->key, it->value);
                painter->setFont(m_font);
                QString text = QString::number(it->value, 'g', 2); //获取当前value值，保留两位精度
                QRectF textRect = painter->fontMetrics().boundingRect(0, 0, 0, 0, Qt::TextDontClip | m_textAlignment, text); //计算文字占用大小
                if(mKeyAxis.data()->orientation() == Qt::Horizontal) //水平轴为keyAxis
                {
                    if(mKeyAxis.data()->axisType() == QCPAxis::atTop) //上轴，文字放到柱图下方
                        textRect.moveTopLeft(barRect.bottomLeft() + QPointF(0, m_spacing));
                    else //下轴，文字放到柱图上方
                        textRect.moveBottomLeft(barRect.topLeft() - QPointF(0, m_spacing));
                    textRect.setWidth(barRect.width());
                }
                else //垂直轴为keyAxis
                {
                    if(mKeyAxis.data()->axisType() == QCPAxis::atLeft) //左轴，文字放到柱图右侧
                        textRect.moveTopLeft(barRect.topRight() + QPointF(m_spacing, 0));
                    else //右轴，文字放到柱图左侧
                        textRect.moveTopRight(barRect.topLeft() - QPointF(m_spacing, 0));
                    textRect.setHeight(barRect.height());
                }
                painter->drawText(textRect, Qt::TextDontClip | m_textAlignment, text);
            }

            ///---自定义逻辑-end---
        }
    }

    ///源码拷贝
    // draw other selection decoration that isn't just line/scatter pens and brushes:
    if (mSelectionDecorator)
        mSelectionDecorator->drawDecoration(painter, selection());
}

dpBarsChart::dpBarsChart(QWidget* parent)
    :dpBaseChart(parent)
{
    setAttribute(Qt::WA_TranslucentBackground,true);

    m_pCustomPlot = new QCustomPlot(this);
    /* m_pBarsGroup = new QCPBarsGroup(m_pCustomPlot);
    m_pBarsGroup->setSpacingType(QCPBarsGroup::stAbsolute);
    m_pBarsGroup->setSpacing(2); */
    initQCP();

    QBoxLayout* mainLayout = new QBoxLayout(QBoxLayout::LeftToRight);
    mainLayout->setContentsMargins(0, 1, 0, 0);
    mainLayout->addWidget(m_pCustomPlot);
    setLayout(mainLayout);

    m_updateData = false;

    //connect(DataManager::instance(), &DataManager::dataUpdated, this, &dpBarsChart::onSignal_dataUpdated);
}

dpBarsChart::~dpBarsChart()
{
    if(!m_requestDataList.isEmpty())
        MeasurementDataManager::instance()->cancelRequest(m_requestDataList, this);
}

void dpBarsChart::initQCP()
{
    m_chartStyle.bgColor = Qt::transparent;
    m_chartStyle.axisColor = QColor(87, 100, 120);
    m_chartStyle.labelColor = QColor(250, 250, 250);
    m_chartStyle.labelFont = QFont("黑体", 12);
    m_chartStyle.tickColor = QColor(87, 100, 120);
    m_chartStyle.tickLabelColor = QColor(250, 250, 250);
    m_chartStyle.tickLabelFont = QFont("黑体", 12);
    m_chartStyle.gridPen = QPen(QColor(87, 100, 120), 1, Qt::DotLine);

    m_pCustomPlot->setInteractions(QCP::iNone);
    /*m_pCustomPlot->axisRect()->setRangeDrag(Qt::Horizontal); //只允许x轴方向的拖拽
    double zoomFactor = m_pCustomPlot->axisRect()->rangeZoomFactor(Qt::Horizontal);
    m_pCustomPlot->axisRect()->setRangeZoomFactor(zoomFactor, 1); //只做x轴的缩放*/
    //m_pCustomPlot->xAxis->setTicks(false);
    m_pCustomPlot->xAxis->setSubTicks(false);
    //m_pCustomPlot->yAxis->setTicks(false);
    m_pCustomPlot->yAxis->setSubTicks(false);
    //m_pCustomPlot->yAxis->setVisible(false);
    //m_pCustomPlot->yAxis2->setTicks(false);
    m_pCustomPlot->yAxis2->setSubTicks(false);
    m_pCustomPlot->yAxis2->setVisible(false);
    //背景颜色
    m_pCustomPlot->setBackground(QBrush(m_chartStyle.bgColor));
    //坐标轴颜色
    m_pCustomPlot->xAxis->setBasePen(m_chartStyle.axisColor);
    m_pCustomPlot->xAxis2->setBasePen(m_chartStyle.axisColor);
    m_pCustomPlot->yAxis->setBasePen(m_chartStyle.axisColor);
    m_pCustomPlot->yAxis2->setBasePen(m_chartStyle.axisColor);
    //坐标刻度颜色
    m_pCustomPlot->xAxis->setTickPen(QPen(m_chartStyle.tickColor));
    m_pCustomPlot->yAxis->setTickPen(QPen(m_chartStyle.tickColor));
    m_pCustomPlot->yAxis2->setTickPen(QPen(m_chartStyle.tickColor));
    //坐标刻度Label颜色
    m_pCustomPlot->xAxis->setTickLabels(false);
    m_pCustomPlot->xAxis->setTickLabelColor(m_chartStyle.tickLabelColor);
    m_pCustomPlot->xAxis->setTickLabelFont(m_chartStyle.tickLabelFont);
    m_pCustomPlot->yAxis->setTickLabels(false);
    m_pCustomPlot->yAxis->setTickLabelColor(m_chartStyle.tickLabelColor);
    m_pCustomPlot->yAxis->setTickLabelFont(m_chartStyle.tickLabelFont);
    m_pCustomPlot->yAxis2->setTickLabelColor(m_chartStyle.tickLabelColor);
    m_pCustomPlot->yAxis2->setTickLabelFont(m_chartStyle.tickLabelFont);
    //网格线颜色
    m_pCustomPlot->xAxis->grid()->setVisible(false);
    m_pCustomPlot->xAxis->grid()->setPen(m_chartStyle.gridPen);
    m_pCustomPlot->xAxis->grid()->setZeroLinePen(m_chartStyle.gridPen);
    //m_pCustomPlot->xAxis2->grid()->setPen(m_chartStyle.gridPen);
    m_pCustomPlot->yAxis->grid()->setVisible(false);
    m_pCustomPlot->yAxis->grid()->setPen(m_chartStyle.gridPen);
    m_pCustomPlot->yAxis->grid()->setZeroLinePen(m_chartStyle.gridPen);
    m_pCustomPlot->yAxis2->grid()->setPen(m_chartStyle.gridPen);

    //Legend
    m_pCustomPlot->legend->setBrush(QBrush(QColor(255,255,255,12))); //背景透明
    m_pCustomPlot->legend->setBorderPen(QPen(QColor(255,255,255,0))); //边框透明
    m_pCustomPlot->legend->setFont(m_chartStyle.labelFont);
    m_pCustomPlot->legend->setTextColor( m_chartStyle.labelColor);
}

void dpBarsChart::setTimeRange(TimeUnit unit)
{}

void dpBarsChart::setDateTime(const QDateTime& dateTime)
{
    if(m_updateData)
    {
        for(auto it = m_bars.begin(); it != m_bars.end(); ++it)
        {
            //DataManager::instance()->requestData(it.key(), this);

            MeasurementDataPoint data = MeasurementDataManager::instance()->getLastestRealtimeData(it.key());
            if(data.timestamp == 0)
                continue;

            //qDebug() << it.key() << ": " << data.value;
            static double marginFactor = 0.0;
            double dData = data.value;
            Bars bar = it.value();
            //调整所在轴的范围
            QCPRange range = bar.qBars->valueAxis()->range();
            if(dData > range.upper)
            {
                double upper = dData + marginFactor;
                bar.qBars->valueAxis()->setRangeUpper(upper);
            }
            else if(dData < range.lower)
            {
                double lower = dData - marginFactor;
                bar.qBars->valueAxis()->setRangeLower(lower);
            }
            //更新值
            QVector<double> values;
            values << dData;
            bar.qBars->setData(bar.keys, values);
        }

        m_pCustomPlot->replot();
    }
}

void dpBarsChart::viewHistoricalData(const QDateTime& dateTime)
{}

void dpBarsChart::synchronizeConfigData(const configurationResults& cfg)
{
    m_updateData = false; //停止更新数据

    //先清除现有图形(直方图不像曲线一样有连续的过程展现，所以不采用动态更新，每次都清除、重新创建)
    //m_pBarsGroup->clear();
    m_pCustomPlot->clearPlottables();
    m_bars.clear();
    m_barsGroups.clear();

    bool groupByType = cfg.groupByType;

    //设定朝向
    QCPAxis* keyAxis = nullptr;
    QCPAxis* valueAxis = nullptr;
    if(cfg.barOrientataion == Vertical)
    {
        keyAxis = m_pCustomPlot->xAxis;
        valueAxis = m_pCustomPlot->yAxis;
    }
    else
    {
        keyAxis = m_pCustomPlot->yAxis;
        valueAxis = m_pCustomPlot->xAxis;
    }
    if(!keyAxis || !valueAxis)
        return;

    QVector<double> ticks;
    int tick = 0;
    QVector<QString> tickLabels;

    QHash<RealTimeDataType, QSet<QString>> groupedBars; //按数据类型对bar进行分组，以实现可以按组放置以及设置颜色等操作
    QStringList newRequestDataList;
    QStringList cancelRequestDataList;
    for(int i = 0; i < cfg.m_pModel_dataSource->rowCount(); i++)
    {
        QString itemText = cfg.m_pModel_dataSource->item(i, 0)->text();
        // QString stationID = cfg.m_pModel_dataSource->item(i, 0)->data(Qt::UserRole + itemRole_stationID).toString();
        // QString compoentID = cfg.m_pModel_dataSource->item(i, 0)->data(Qt::UserRole + itemRole_componentID).toString();
        // QString pointID = cfg.m_pModel_dataSource->item(i, 0)->data(Qt::UserRole + itemRole_pointID).toString();
        // QString dataID = stationID + "-" + compoentID + "-" + pointID;
        QString dataID = cfg.m_pModel_dataSource->item(i, 0)->data(Qt::UserRole + itemRole_pointID).toString();
        QVariant colorData = cfg.m_pModel_dataSource->item(i, 0)->data(Qt::DecorationRole);
        RealTimeDataType dataType = (RealTimeDataType)cfg.m_pModel_dataSource->item(i, 0)->data(Qt::UserRole + itemRole_dataType).toInt();

        Bars bars;
        bars.name = itemText;
        bars.dataID = dataID;
        bars.dataType = dataType;
        bars.color = colorData.value<QColor>();
        CustomBars* qBars = new CustomBars(keyAxis, valueAxis);
        qBars->setTextVisible(true);
        qBars->setName(bars.name);
        qBars->setPen(bars.color); //边框颜色
        qBars->setBrush(bars.color); //填充颜色
        bars.qBars = qBars;

        if(groupByType)
        {
            groupedBars[dataType].insert(dataID);
            //每一个类型创建一个QCPBarsGroup对象
            QCPBarsGroup* barsGroup = nullptr;
            if(!m_barsGroups.contains(dataType))
            {
                barsGroup = new QCPBarsGroup(m_pCustomPlot);
                m_barsGroups.insert(dataType, barsGroup);
            }
        }
        else
        {
            ticks << ++tick;
            tickLabels << itemText;
            bars.keys << tick;
        }

        m_bars.insert(dataID, bars);

        //实时模拟数据
        /*DataManager::instance()->registerDataSource(dataID, [](){
            static double min = 0, max = 10.0;
            double randomFloat = min + QRandomGenerator::global()->generateDouble() * (max - min);
            return QVariant::fromValue(randomFloat);
        });*/

        newRequestDataList << dataID;
    }

    QSet dataSet(newRequestDataList.begin(), newRequestDataList.end());
    for(const QString& data : std::as_const(m_requestDataList))
    {
        if(!dataSet.contains(data))
            cancelRequestDataList << data;
    }

    //获取实时数据
    if(!cancelRequestDataList.isEmpty())
        MeasurementDataManager::instance()->cancelRequest(cancelRequestDataList, this);
    if(!newRequestDataList.isEmpty())
        MeasurementDataManager::instance()->requestData(newRequestDataList, this);

    m_requestDataList = QStringList(std::move(newRequestDataList));

    if(groupByType)
    {
        for(auto it = groupedBars.begin(); it != groupedBars.end(); ++it)
        {
            ticks.push_back(++tick);
            switch(it.key())
            {
            case power:
                tickLabels.push_back("功率");
                break;
            case voltage:
                tickLabels.push_back("电压");
                break;
            case current:
                tickLabels.push_back("电流");
                break;
            case temperature:
                tickLabels.push_back("温度");
                break;
            default:
                tickLabels.push_back("未定义");
                break;
            }

            for(auto bars_it = it.value().begin(); bars_it != it.value().end(); ++bars_it)
            {
                QString dataID = *bars_it;
                if(m_bars.contains(dataID))
                    m_bars[dataID].keys.push_back(tick);
            }
        }
    }

    //Axis
    if(groupByType)
        keyAxis->setTickLabels(true);
    else
        keyAxis->setTickLabels(false);

    QSharedPointer<QCPAxisTickerText> textTicker(new QCPAxisTickerText);
    textTicker->addTicks(ticks, tickLabels);
    keyAxis->setTicker(textTicker);
    keyAxis->setRange(0, ticks.count() + 1);

    valueAxis->setTickLabels(true);
    QSharedPointer<QCPAxisTickerFixed > fixedTicker(new QCPAxisTickerFixed);
    valueAxis->setTicker(fixedTicker);
    valueAxis->setRange(0, 11);

    for(auto it = m_bars.begin(); it != m_bars.end(); ++it)
    {
        if(it.value().qBars.isNull())
            continue;

        //随机模拟值
        QVector<double> values;
        //double randomVaule = 1 + QRandomGenerator::global()->generateDouble() * (8 - 1);
        values << 0;

        Bars bar = it.value();
        bar.qBars->setData(bar.keys, values);
        if(groupByType && m_barsGroups.value(bar.dataType))
        {
            bar.qBars->setWidthType(QCPBars::wtPlotCoords);
            //bar.qBars->setWidth(bar.qBars->width() / groupedBars.value(bar.dataType).count());
            bar.qBars->setWidth(bar.qBars->width() * ticks.count() / m_bars.count());
            bar.qBars->setBarsGroup(m_barsGroups.value(bar.dataType));
        }
    }

    //Legend
    if(cfg.showLegend && m_bars.count() > 0)
        m_pCustomPlot->legend->setVisible(true);
    else
        m_pCustomPlot->legend->setVisible(false);

    //m_pCustomPlot->replot();
    m_updateData = true;
}

void dpBarsChart::onSignal_dataUpdated(const QString& dataID, const QVariant& data, const QDateTime& timestamp)
{
    auto it = m_bars.find(dataID);
    if(it != m_bars.end())
    {
        static double marginFactor = 1.0;
        double dData = data.toDouble();
        Bars bar = it.value();
        //调整所在轴的范围
        QCPRange range = bar.qBars->valueAxis()->range();
        if(dData > range.upper)
        {
            double upper = dData + marginFactor;
            bar.qBars->valueAxis()->setRangeUpper(upper);
        }
        else if(dData < range.lower)
        {
            double lower = dData - marginFactor;
            bar.qBars->valueAxis()->setRangeLower(lower);
        }
        //更新值
        QVector<double> values;
        values << dData;
        bar.qBars->setData(bar.keys, values);
    }
}
