#include "WedgeCommands.h"
#include <QDate>
#include <QJSEngine>
#include <QJSValue>
#include <QMap>
#include <QRegularExpression>
#include <QTextBlock>
#include <QTextCursor>
#include <QTextEdit>
#include <QtGlobal>
namespace WedgeCommands {
QString otcDateResult(int day, QString mon) {
static QMap<QString, int> months = {
{"jan", 1}, {"feb", 2}, {"mar", 3}, {"apr", 4}, {"may", 5}, {"jun", 6},
{"jul", 7}, {"aug", 8}, {"sep", 9}, {"oct", 10}, {"nov", 11}, {"dec", 12}
};
int m = months.value(mon.toLower(), 0);
if (m == 0) return "";
QDate now = QDate::currentDate();
QDate target(now.year(), m, day);
if (target < now) target = target.addYears(1);
QDate otcStart(target.year(), 3, 20);
if (target < otcStart) otcStart = otcStart.addYears(-1);
return QString("(%1)=%2").arg(otcStart.daysTo(target) + 1).arg(now.daysTo(target));
}
Result apply(QTextEdit *editor, QJSEngine &engine, int key) {
Result r;
if (!editor) return r;
QTextCursor cursor = editor->textCursor();
QString lineText = cursor.block().text().left(cursor.positionInBlock());
static QRegularExpression mathRegex("(?<=\\s|^|=)((\\d+(\\.\\d+)?%?[\\+\\-\\*\\/])+\\d+(\\.\\d+)?%?)=$");
static QRegularExpression dateRegex("(?<=\\s|^)(\\d{1,2})([a-zA-Z]{3})\\(\\)=$");
static QRegularExpression listRegex("^(\\s*)(\\d+)\\.\\s");
static QRegularExpression hrRegex("(?<=\\s|^)hr\\((\\d+)\\)$");
static QRegularExpression dashRegex("(?<=\\s|^)dash\\((\\d+)\\)$");
auto mMatch = mathRegex.match(lineText);
if (mMatch.hasMatch()) {
QString expression = mMatch.captured(1);
static QRegularExpression percentRegex("([\\d\\.]+)\\s*([\\+\\-\\*\\/])\\s*([\\d\\.]+)%");
while (expression.contains('%')) {
QRegularExpressionMatch pMatch = percentRegex.match(expression);
if (!pMatch.hasMatch()) break;
QString base = pMatch.captured(1);
QString op = pMatch.captured(2);
QString percentVal = pMatch.captured(3);
QString replacement = QString("%1 %2 (%1 * (%3 / 100))").arg(base, op, percentVal);
expression.replace(pMatch.capturedStart(), pMatch.capturedLength(), replacement);
}
QJSValue result = engine.evaluate(expression);
if (!result.isError()) {
QString resStr = QString::number(result.toNumber(), 'f', 2);
if (resStr.contains('.')) {
while (resStr.endsWith('0')) resStr.chop(1);
if (resStr.endsWith('.')) resStr.chop(1);
}
editor->blockSignals(true);
cursor.insertText(resStr);
editor->blockSignals(false);
r.changed = true;
}
r.consumed = (key == Qt::Key_Space);
return r;
}
auto dMatch = dateRegex.match(lineText);
if (dMatch.hasMatch()) {
QString res = otcDateResult(dMatch.captured(1).toInt(), dMatch.captured(2));
if (!res.isEmpty()) {
editor->blockSignals(true);
cursor.movePosition(QTextCursor::Left, QTextCursor::KeepAnchor, 3);
cursor.insertText(res);
editor->blockSignals(false);
r.changed = true;
}
r.consumed = (key == Qt::Key_Space);
return r;
}
auto hMatch = hrRegex.match(lineText);
if (hMatch.hasMatch()) {
int count = hMatch.captured(1).toInt();
if (count > 0) {
QString hrline = QString("\u2014").repeated(qMin(count, 100));
editor->blockSignals(true);
cursor.movePosition(QTextCursor::Left, QTextCursor::KeepAnchor, hMatch.capturedLength());
cursor.insertText(hrline);
editor->blockSignals(false);
r.changed = true;
}
r.consumed = (key == Qt::Key_Space);
return r;
}
auto emMatch = dashRegex.match(lineText);
if (emMatch.hasMatch()) {
int counts = emMatch.captured(1).toInt();
if (counts > 0) {
QString dashes = QString("\u2014 ").repeated(qMin(counts, 100));
editor->blockSignals(true);
cursor.movePosition(QTextCursor::Left, QTextCursor::KeepAnchor, emMatch.capturedLength());
cursor.insertText(dashes);
editor->blockSignals(false);
r.changed = true;
}
r.consumed = (key == Qt::Key_Space);
return r;
}
if (key != Qt::Key_Space) {
auto lMatch = listRegex.match(lineText);
if (lMatch.hasMatch()) {
QString ws = lMatch.captured(1);
int num = lMatch.captured(2).toInt();
QString prefix = "\n" + ws + QString::number(num + 1) + ". ";
editor->blockSignals(true);
cursor.beginEditBlock();
cursor.insertText(prefix);
QTextBlock nextBlock = cursor.block().next();
int nextExpected = num + 1;
int i = 0;
while (nextBlock.isValid()) {
auto m = listRegex.match(nextBlock.text());
if (m.hasMatch() && m.captured(1) == ws && m.captured(2).toInt() == nextExpected) {
int foundNum = m.captured(2).toInt();
QTextCursor nextCursor(nextBlock);
nextCursor.movePosition(QTextCursor::NextCharacter, QTextCursor::KeepAnchor, m.capturedLength());
nextCursor.insertText(m.captured(1) + QString::number(foundNum + 1) + ". ");
nextExpected++;
} else if (i > 0) break;
nextBlock = nextBlock.next(); i++;
}
cursor.endEditBlock();
editor->blockSignals(false);
r.changed = true;
r.consumed = true;
return r;
}
static QRegularExpression indentRegex("^(\\s+)");
auto iMatch = indentRegex.match(lineText);
if (iMatch.hasMatch()) {
QString indent = "\n" + iMatch.captured(1);
editor->blockSignals(true);
cursor.insertText(indent);
editor->blockSignals(false);
r.changed = true;
r.consumed = true;
return r;
}
}
return r;
}
}