#include "bwidget.h"

#include <QGridLayout>
#include <QComboBox>

#include <QtCharts/QChartView>
#include <QtCharts/QPieSeries>
#include <QtCharts/QPieSlice>
#include <QtCharts/QAbstractBarSeries>
#include <QtCharts/QPercentBarSeries>
#include <QtCharts/QStackedBarSeries>
#include <QtCharts/QBarSeries>
#include <QtCharts/QBarSet>
#include <QtCharts/QLineSeries>
#include <QtCharts/QSplineSeries>
#include <QtCharts/QScatterSeries>
#include <QtCharts/QAreaSeries>
#include <QtCharts/QLegend>
#include <QtWidgets/QGridLayout>
#include <QtWidgets/QFormLayout>
#include <QtWidgets/QComboBox>
#include <QtWidgets/QSpinBox>
#include <QtWidgets/QCheckBox>
#include <QtWidgets/QGroupBox>
#include <QtWidgets/QLabel>
#include <QtCore/QRandomGenerator>
#include <QtCharts/QBarCategoryAxis>
#include <QtWidgets/QApplication>
#include <QtCharts/QValueAxis>

#include <QtCore/QVariant>
#include <QtWidgets/QApplication>
#include <QtWidgets/QCheckBox>
#include <QtWidgets/QComboBox>
#include <QtWidgets/QGridLayout>
#include <QtWidgets/QHBoxLayout>
#include <QtWidgets/QLabel>
#include <QtWidgets/QSpacerItem>
#include <QSplitter>

#include "ctextedit.h"

BWidget::BWidget(QWidget *parent) : QWidget(parent),
                                    m_listCount(3),
                                    m_valueMax(10),
                                    m_valueCount(7),
                                    m_dataTable(generateRandomData(m_listCount, m_valueMax, m_valueCount))
{
    initUI();
    updateUI();
}

BWidget::~BWidget()
{
}

DataTable BWidget::generateRandomData(int listCount, int valueMax, int valueCount) const
{
    DataTable dataTable;

    // generate random data
    for (int i(0); i < listCount; i++)
    {
        DataList dataList;
        qreal yValue(0);
        for (int j(0); j < valueCount; j++)
        {
            yValue = yValue + QRandomGenerator::global()->bounded(valueMax / (qreal)valueCount);
            QPointF value((j + QRandomGenerator::global()->generateDouble()) * ((qreal)m_valueMax / (qreal)valueCount),
                          yValue);
            QString label = "Slice " + QString::number(i) + ":" + QString::number(j);
            dataList << Data(value, label);
        }
        dataTable << dataList;
    }

    return dataTable;
}

void BWidget::populateThemeBox()
{
    // add items to theme combobox
    this->themeComboBox->addItem("Light", QChart::ChartThemeLight);
    this->themeComboBox->addItem("Blue Cerulean", QChart::ChartThemeBlueCerulean);
    this->themeComboBox->addItem("Dark", QChart::ChartThemeDark);
    this->themeComboBox->addItem("Brown Sand", QChart::ChartThemeBrownSand);
    this->themeComboBox->addItem("Blue NCS", QChart::ChartThemeBlueNcs);
    this->themeComboBox->addItem("High Contrast", QChart::ChartThemeHighContrast);
    this->themeComboBox->addItem("Blue Icy", QChart::ChartThemeBlueIcy);
    this->themeComboBox->addItem("Qt", QChart::ChartThemeQt);
}

void BWidget::populateLegendBox()
{
    // add items to legend combobox
    this->legendComboBox->addItem(tr("No Legend "), 0);
    this->legendComboBox->addItem("Legend Top", Qt::AlignTop);
    this->legendComboBox->addItem("Legend Bottom", Qt::AlignBottom);
    this->legendComboBox->addItem("Legend Left", Qt::AlignLeft);
    this->legendComboBox->addItem("Legend Right", Qt::AlignRight);
}

void BWidget::createPieChart()
{
    mPieChart = new QChart();
    mPieChart->setTitle("Pie chart");

    QPieSeries *series = new QPieSeries(mPieChart);
    for (const Data &data : m_dataTable[0])
    {
        QPieSlice *slice = series->append(data.second, data.first.y());

        // 饼图偏移
        // slice->setExploded();
        // slice->setExplodeDistanceFactor(0.5);

        // 标签可见
        slice->setLabelVisible();

    }
    series->setPieSize(0.4);
    mPieChart->addSeries(series);
}

void BWidget::createSplineChart()
{
    mSplineChart = new QChart();
    mSplineChart->setTitle("Spline chart");
    QString name("Series ");
    int nameIndex = 0;
    for (const DataList &list : m_dataTable)
    {
        QSplineSeries *series = new QSplineSeries(mSplineChart);
        for (const Data &data : list)
            series->append(data.first);
        series->setName(name + QString::number(nameIndex));
        nameIndex++;
        mSplineChart->addSeries(series);
    }

    mSplineChart->createDefaultAxes();
    mSplineChart->axes(Qt::Horizontal).first()->setRange(0, m_valueMax);
    mSplineChart->axes(Qt::Vertical).first()->setRange(0, m_valueCount);

    // Add space to label to add space between labels and axis
    QValueAxis *axisY = qobject_cast<QValueAxis *>(mSplineChart->axes(Qt::Vertical).first());
    Q_ASSERT(axisY);
    axisY->setLabelFormat("%.1f  ");
}

void BWidget::updateUI()
{
    QChart::ChartTheme theme = static_cast<QChart::ChartTheme>(
        this->themeComboBox->itemData(this->themeComboBox->currentIndex()).toInt());

    const auto charts = m_charts;
    if (!m_charts.isEmpty() && m_charts.at(0)->chart()->theme() != theme)
    {
        for (QChartView *chartView : charts)
        {
            chartView->chart()->setTheme(theme);
        }

        // Set palette colors based on selected theme
        QPalette pal = window()->palette();
        if (theme == QChart::ChartThemeLight)
        {
            pal.setColor(QPalette::Window, QRgb(0xf0f0f0));
            pal.setColor(QPalette::WindowText, QRgb(0x404044));
        }
        else if (theme == QChart::ChartThemeDark)
        {
            pal.setColor(QPalette::Window, QRgb(0x121218));
            pal.setColor(QPalette::WindowText, QRgb(0xd6d6d6));
        }
        else if (theme == QChart::ChartThemeBlueCerulean)
        {
            pal.setColor(QPalette::Window, QRgb(0x40434a));
            pal.setColor(QPalette::WindowText, QRgb(0xd6d6d6));
        }
        else if (theme == QChart::ChartThemeBrownSand)
        {
            pal.setColor(QPalette::Window, QRgb(0x9e8965));
            pal.setColor(QPalette::WindowText, QRgb(0x404044));
        }
        else if (theme == QChart::ChartThemeBlueNcs)
        {
            pal.setColor(QPalette::Window, QRgb(0x018bba));
            pal.setColor(QPalette::WindowText, QRgb(0x404044));
        }
        else if (theme == QChart::ChartThemeHighContrast)
        {
            pal.setColor(QPalette::Window, QRgb(0xffab03));
            pal.setColor(QPalette::WindowText, QRgb(0x181818));
        }
        else if (theme == QChart::ChartThemeBlueIcy)
        {
            pal.setColor(QPalette::Window, QRgb(0xcee7f0));
            pal.setColor(QPalette::WindowText, QRgb(0x404044));
        }
        else
        {
            pal.setColor(QPalette::Window, QRgb(0xf0f0f0));
            pal.setColor(QPalette::WindowText, QRgb(0x404044));
        }
        window()->setPalette(pal);
    }

    // 抗锯齿
    for (QChartView *chart : charts)
        chart->setRenderHint(QPainter::Antialiasing, true);

    //图例
    Qt::Alignment alignment(
        this->legendComboBox->itemData(this->legendComboBox->currentIndex()).toInt());

    if (!alignment)
    {
        for (QChartView *chartView : charts)
            chartView->chart()->legend()->hide();
    }
    else
    {
        for (QChartView *chartView : charts)
        {
            chartView->chart()->legend()->setAlignment(alignment);
            chartView->chart()->legend()->show();
        }
    }
}

void BWidget::initUI()
{
    mMainVLayout = new QVBoxLayout;
    this->setLayout(mMainVLayout);

    if (this->objectName().isEmpty())
        this->setObjectName(QString::fromUtf8("BWidgetForm"));
    this->resize(900, 600);
    mChartHLayout = new QHBoxLayout();
    mChartHLayout->setObjectName(QString::fromUtf8("hboxLayout"));
    horizontalLayout = new QHBoxLayout();
    horizontalLayout->setObjectName(QString::fromUtf8("horizontalLayout"));
    themeLabel = new QLabel(this);
    themeLabel->setObjectName(QString::fromUtf8("themeLabel"));

    horizontalLayout->addWidget(themeLabel);

    themeComboBox = new QComboBox(this);
    themeComboBox->setObjectName(QString::fromUtf8("themeComboBox"));

    horizontalLayout->addWidget(themeComboBox);

    animatedLabel = new QLabel(this);
    animatedLabel->setObjectName(QString::fromUtf8("animatedLabel"));

    horizontalLayout->addWidget(animatedLabel);

    legendLabel = new QLabel(this);
    legendLabel->setObjectName(QString::fromUtf8("legendLabel"));

    horizontalLayout->addWidget(legendLabel);

    legendComboBox = new QComboBox(this);
    legendComboBox->setObjectName(QString::fromUtf8("legendComboBox"));

    horizontalLayout->addWidget(legendComboBox);

    horizontalSpacer = new QSpacerItem(40, 20, QSizePolicy::Expanding, QSizePolicy::Minimum);

    horizontalLayout->addItem(horizontalSpacer);

    mMainVLayout->addLayout(horizontalLayout);
    mMainVLayout->addLayout(mChartHLayout);

    QObject::connect(themeComboBox, SIGNAL(currentIndexChanged(int)), this, SLOT(updateUI()));
    QObject::connect(legendComboBox, SIGNAL(currentIndexChanged(int)), this, SLOT(updateUI()));

    populateThemeBox();
    populateLegendBox();
    createPieChart();
    createSplineChart();

    QChartView *pieChartView = new QChartView(mPieChart);
    // Funny things happen if the pie slice labels do not fit the screen, so we ignore size policy
    pieChartView->setSizePolicy(QSizePolicy::Ignored, QSizePolicy::Ignored);
    this->mChartHLayout->addWidget(pieChartView, 1);
    m_charts << pieChartView;

    QChartView *splineChartView = new QChartView(mSplineChart);
    this->mChartHLayout->addWidget(splineChartView, 1);
    m_charts << splineChartView;

    // Set the colors from the light theme as default ones
    QPalette pal = qApp->palette();
    pal.setColor(QPalette::Window, QRgb(0xf0f0f0));
    pal.setColor(QPalette::WindowText, QRgb(0x404044));
    qApp->setPalette(pal);

    themeComboBox->setCurrentIndex(2);
    legendComboBox->setCurrentIndex(3);


    mSplitter = new QSplitter;
    mSplitter->setOrientation(Qt::Vertical);

    mChartWidget = new QWidget;
    mChartWidget->setLayout(mMainVLayout);

    mLogTextEdit = new CTextEdit;

    mSplitter->addWidget(mChartWidget);
    mSplitter->addWidget(mLogTextEdit);
    mSplitter->setStretchFactor(0, 4);
    mSplitter->setStretchFactor(1, 1);

    QHBoxLayout* layout = new QHBoxLayout;
    layout->addWidget(mSplitter);
    this->setLayout(layout);
}
