#include <QApplication>
#include <QColor>
#include <QMainWindow>
#include <QOffscreenSurface>
#include <QOpenGLContext>
#include <QSplitter>
#include <QQuickWidget>
#include <QQmlEngine>
#include <QQuickWindow>
#include <QtQml/qqml.h>
#include <QSGRendererInterface>
#include <QSurfaceFormat>
#include <QVBoxLayout>
#include <QWidget>
#include <qdebug.h>
#include <qforeach.h>
#include <qobject.h>
#include <qquickitem.h>
#include <QQuickStyle>
#include <qquickstyle.h>
#include "sparkline_plotitem.h"
#include "backend.h"
#include "data_frame.h"
#include "glwidget.h"
#include "translation_manager.h"
#include "src/sparkline_plotitem.h"

int main(int argc, char *argv[]) {
    QQuickWindow::setGraphicsApi(QSGRendererInterface::OpenGL);
    // 统一OpenGL格式
    QSurfaceFormat fmt;
    fmt.setRenderableType(QSurfaceFormat::OpenGL);
    fmt.setVersion(3, 3);
    fmt.setProfile(QSurfaceFormat::CoreProfile);
    fmt.setDepthBufferSize(24);
    fmt.setStencilBufferSize(8);
    fmt.setSwapInterval(1);
    QSurfaceFormat::setDefaultFormat(fmt);

    QApplication a(argc, argv);
    QQuickStyle::setStyle("Material");

    {
        QOpenGLContext probeCtx;
        probeCtx.setFormat(QSurfaceFormat::defaultFormat());
        if (!probeCtx.create()) {
            qCritical().noquote() << "Failed to create an OpenGL context "
                                     "(required: OpenGL 3.3 Core).";
            return 1;
        }

        QOffscreenSurface probeSurface;
        probeSurface.setFormat(probeCtx.format());
        probeSurface.create();

        if (!probeCtx.makeCurrent(&probeSurface)) {
            qCritical().noquote()
                << "Failed to make the OpenGL context current. This usually "
                   "means the requested format is unsupported by the current "
                   "graphics driver.";
            return 1;
        }

        const QSurfaceFormat actual = probeCtx.format();
        const bool versionOk =
            (actual.majorVersion() > 3) ||
            (actual.majorVersion() == 3 && actual.minorVersion() >= 3);
        if (!versionOk || actual.profile() != QSurfaceFormat::CoreProfile) {
            probeCtx.doneCurrent();
            qCritical().noquote()
                << "OpenGL context is not OpenGL 3.3 Core (got: "
                << actual.majorVersion() << "." << actual.minorVersion()
                << ", profile=" << actual.profile() << ").";
            return 1;
        }

        probeCtx.doneCurrent();
    }

    auto *win = new QMainWindow;

    auto *root = new QWidget;
    auto *rootLayout = new QVBoxLayout(root);
    rootLayout->setContentsMargins(0, 0, 0, 0);
    rootLayout->setSpacing(0);

    AppBackend backend;
    TranslationManager i18n;
    qmlRegisterSingletonInstance("TactileIPC", 1, 0, "Backend", &backend);
    qmlRegisterSingletonInstance("TactileIPC", 1, 0, "I18n", &i18n);
    qmlRegisterType<SparklinePlotItem>("LiveTrend", 1, 0, "SparklinePlot");
    i18n.setLanguage(backend.language());
    QObject::connect(
        &backend, &AppBackend::languageChanged, &i18n,
        [&backend, &i18n]() { i18n.setLanguage(backend.language()); });
    auto *qmlEngine = new QQmlEngine(root);

    auto createQuickWidget = [&](const QUrl &sourceUrl) -> QQuickWidget * {
        auto *view = new QQuickWidget(qmlEngine, root);
        view->setResizeMode(QQuickWidget::SizeRootObjectToView);
        view->setSource(sourceUrl);
        return view;
    };

    auto *navView = createQuickWidget(QUrl("qrc:/qml/content/NavBar.qml"));
    navView->setFixedHeight(56);

    auto *splitter = new QSplitter;
    splitter->setOrientation(Qt::Horizontal);
    splitter->setHandleWidth(1);

    auto *leftView = createQuickWidget(QUrl("qrc:/qml/content/LeftPanel.qml"));
    leftView->setFixedWidth(350);

    auto *glw = new GLWidget;
    glw->setSpec(12, 7, 0.1f, 0.03f);
    glw->setPanelThickness(0.08f);
    glw->setRange(backend.rangeMin(), backend.rangeMax());
    glw->setColorZero(backend.colorZero());
    glw->setColorLow(backend.colorLow());
    glw->setColorMid(backend.colorMid());
    glw->setColorHigh(backend.colorHigh());
    glw->setUseHeatmap(backend.useHeatmap());

    /* backend.data()->setLiveRenderCallback([glw](const DataFrame& frame) {
        if (frame.data.size() != glw->dotCount())
            return;
        glw->submitValues(frame.data);
    }); */
    backend.data()->setLiveRenderCallback([glw](const DataFrame &frame) {
        if (frame.data.size() != 0) {
            glw->submitValues(frame.data);
        }
    });
    // TODO:待实现内容(将frame数据分发给右侧曲线/指标的QML接口)

    auto *rightView =
        createQuickWidget(QUrl("qrc:/qml/content/RightPanel.qml"));

    splitter->addWidget(leftView);
    splitter->addWidget(glw);
    splitter->addWidget(rightView);
    splitter->setStretchFactor(0, 0);
    splitter->setStretchFactor(1, 1);
    splitter->setStretchFactor(2, 0);
    splitter->setSizes({320, 640, 320});
    auto applySplitterStyle = [&backend, splitter]() {
        const QString handleColor = backend.lightMode()
                                        ? QStringLiteral("#E0E0E0")
                                        : QStringLiteral("#2C2C2C");
        splitter->setStyleSheet(
            QStringLiteral("QSplitter::handle { background: %1; }")
                .arg(handleColor));
    };
    applySplitterStyle();
    QObject::connect(&backend, &AppBackend::lightModeChanged, splitter,
                     [applySplitterStyle]() { applySplitterStyle(); });

    auto applyQuickTheme = [&backend, navView, leftView, rightView]() {
        const QColor navColor = backend.lightMode()
                                    ? QColor(QStringLiteral("#F5F7F5"))
                                    : QColor(QStringLiteral("#2B2F2B"));
        const QColor panelColor = backend.lightMode()
                                      ? QColor(QStringLiteral("#F5F5F5"))
                                      : QColor(QStringLiteral("#2C2C2C"));
        navView->setClearColor(navColor);
        leftView->setClearColor(panelColor);
        rightView->setClearColor(panelColor);
    };
    applyQuickTheme();
    QObject::connect(&backend, &AppBackend::lightModeChanged, navView,
                     [applyQuickTheme]() { applyQuickTheme(); });

    QObject::connect(&backend, &AppBackend::lightModeChanged, glw,
                     [&backend, glw]() {
                         bool m = backend.lightMode() ? true : false;
                         glw->setLightMode(m);
                     });

    QObject::connect(&backend, &AppBackend::showGridChanged, glw,
                     &GLWidget::setShowGrid);
    QObject::connect(&backend, &AppBackend::useHeatmapChanged, glw,
                     &GLWidget::setUseHeatmap);
    QObject::connect(&backend, &AppBackend::sensorRowChanged, glw,
                     &GLWidget::setRow);
    QObject::connect(&backend, &AppBackend::sensorColChanged, glw,
                     &GLWidget::setCol);
    QObject::connect(&backend, &AppBackend::rangeChanged, glw,
                     &GLWidget::setRange);
    QObject::connect(&backend, &AppBackend::colorZeroChanged, glw,
                     &GLWidget::setColorZero);
    QObject::connect(&backend, &AppBackend::colorLowChanged, glw,
                     &GLWidget::setColorLow);
    QObject::connect(&backend, &AppBackend::colorMidChanged, glw,
                     &GLWidget::setColorMid);
    QObject::connect(&backend, &AppBackend::colorHighChanged, glw,
                     &GLWidget::setColorHigh);

    rootLayout->addWidget(navView);
    rootLayout->addWidget(splitter);

    win->setCentralWidget(root);
    win->resize(1280, 720);
    win->show();
    return QApplication::exec();
}
