// Chatter — Qt Quick app with a direct-framebuffer ink pipeline.
// Pen strokes are drawn straight into the e-paper framebuffer (captured by
// FbCapture) and refreshed with an explicit solid swap (InkEngine). Qt Quick is
// used only for the static UI (Back / Clear). This is what gives stock-quality
// solid, low-latency ink — the Qt scene graph can't.

#include <QGuiApplication>
#include <QQmlApplicationEngine>
#include <QQmlContext>
#include <QScreen>
#include <QSettings>
#include <QVariantMap>
#include <QColor>
#include <QRegion>
#include <QRect>

#include "PenDevice.h"
#include "AppControl.h"
#include "InkEngine.h"
#include "FbCapture.h" // links the setBuffers interposer into the executable

struct PenStyle {
    int type = 2;
    qreal size = 2.0;
    QColor color = Qt::black;
};

// Read the pen the user last selected in the standard GUI (xochitl.conf,
// [General]/LastWritingTool — flushed when xochitl stops, i.e. on Back).
static PenStyle readPenStyle()
{
    PenStyle ps;
    QSettings xs(QStringLiteral("/home/root/.config/remarkable/xochitl.conf"),
                 QSettings::IniFormat);
    const QVariantMap t = xs.value(QStringLiteral("LastWritingTool")).toMap();
    if (t.isEmpty()) {
        qWarning("readPenStyle: LastWritingTool unreadable; using defaults");
        return ps;
    }
    ps.type = t.value("LastPen").toInt();
    ps.size = t.value("LastPenSize").toDouble();
    const uint code = t.value("LastPenColorCode").toUInt();
    if (code != 0)
        ps.color = QColor::fromRgba(QRgb(code));
    qInfo("readPenStyle: pen=%d size=%.2f color=%s", ps.type, ps.size,
          qPrintable(ps.color.name(QColor::HexArgb)));
    return ps;
}

int main(int argc, char *argv[])
{
    QGuiApplication app(argc, argv);
    const PenStyle penStyle = readPenStyle();

    const QSize screen = app.primaryScreen()->geometry().size();
    PenDevice pen(screen.width(), screen.height());
    AppControl appControl;

    InkEngine ink;
    ink.setInkColor(penStyle.color);
    // reMarkable exposes only the size CATEGORY (LastPenSize 1/2/3 =
    // thin/thicker/thickest). Calibrate to measured widths on this 264-PPI panel:
    // thicker ~1mm, thickest ~2mm, thinnest ~2px. px/mm = 264/25.4 ~= 10.4.
    constexpr double pxPerMm = 264.0 / 25.4;
    const double maxMm = qMax(0.2, (penStyle.size - 1.0) * 1.0); // sz3->2mm, sz2->1mm
    ink.setWidthRange(2.0, maxMm * pxPerMm);
    ink.setPenType(penStyle.type);

    // Back button (finger or stylus) → return to the standard GUI.
    QObject::connect(&ink, &InkEngine::backRequested, &appControl, &AppControl::returnToStandard);

    // Pen drives the ink engine directly (no QML in the ink loop).
    QObject::connect(&pen, &PenDevice::strokeStart, &ink, &InkEngine::strokeStart);
    QObject::connect(&pen, &PenDevice::strokeMove, &ink, &InkEngine::strokeMove);
    QObject::connect(&pen, &PenDevice::strokeEnd, &ink, &InkEngine::strokeEnd);

    QQmlApplicationEngine engine;
    engine.rootContext()->setContextProperty("appControl", &appControl);
    engine.rootContext()->setContextProperty("ink", &ink);

    QObject::connect(
        &engine, &QQmlApplicationEngine::objectCreationFailed,
        &app, []() { QCoreApplication::exit(-1); },
        Qt::QueuedConnection);

    engine.loadFromModule("Chatter", "Main");

    return app.exec();
}
