#include "parserhelper.h"
#include <QFile>
#include <QTextStream>
#include <QVariantMap>
#include <QtMath>
#include <QDebug>
#include "../core/font.h"


QVariantMap PcbCamParserHelper::parseOdbStructuredText(const QByteArray &iData)
{
    QByteArray data = iData;
    QVariantMap res;

    QTextStream stream(&data);
    QString line;

    QMap<QString, QVariantList> subMaps;
    bool inSubBlock = false;
    QString subKey;
    QVariantMap subValue;
    while (stream.readLineInto(&line)) {
        if (line.length() == 0 || line.startsWith("#")) continue;
        if (line.endsWith(" {")) {
            line.chop(2);
            subKey = line;
            if (!subMaps.contains(subKey)) {
                subMaps.insert(subKey, QVariantList());
            }
            inSubBlock = true;
        }
        else if (line.startsWith("}")) {
            subMaps[subKey].append(subValue);
            inSubBlock = false;
            subKey = "";
            subValue.clear();
        }
        else {
            int loc = line.indexOf('=');
            QString k = line.left(loc).trimmed();
            QString v = line.mid(loc+1).trimmed();
            if (inSubBlock) {
                subValue.insert(k, v);
            }
            else {
                res.insert(k, v);
            }
        }
    }

    QMapIterator<QString, QVariantList> it(subMaps);
    while (it.hasNext()) {
        it.next();
        res.insert(it.key(), it.value());
    }

    return res;
}

QPainterPath PcbCamParserHelper::parseOdbProfile(const QByteArray &iData)
{
    QByteArray data = iData;
    QTextStream stream(&data);
    QString line;
    QPainterPath res;
    qreal lastx {0.0};
    qreal lasty {0.0};
    while (stream.readLineInto(&line)) {
        if (line.startsWith("#") || line.length() == 0) { // comment
          continue;
        }
        QStringList param = line.split(" ", Qt::SkipEmptyParts);
        if (param.value(0) == "OB") {
            lastx = param.value(1).toDouble();
            lasty = param.value(2).toDouble();
            res.moveTo(lastx, lasty);
        }
        else if (param.value(0) == "OS") {
            lastx = param.value(1).toDouble();
            lasty = param.value(2).toDouble();
            res.lineTo(lastx, lasty);
        }
        else if (param.value(0) == "OC") {
            qreal sx = lastx, sy = lasty;
            qreal ex = param.value(1).toDouble(), ey = param.value(2).toDouble();
            qreal cx = param.value(3).toDouble(), cy = param.value(4).toDouble();
            bool cw = param.value(5) == "Y" ? true : false;

            qreal sax = sx - cx, say = sy - cy;
            qreal eax = ex - cx, eay = ey - cy;

            qreal r = qSqrt(sax * sax + say * say);

            qreal sa = qAtan2(-say, sax);
            qreal ea = qAtan2(-eay, eax);

            if (cw) {
                if (ea <= sa) {
                    ea += 2.0 * M_PI;
                }
            }
            else {
                if (sa <= ea) {
                    sa += 2.0 * M_PI;
                }
            }
            res.arcTo(QRectF(cx -r, cy -r, r *2, r *2), sa * (180.0 / M_PI), (ea - sa) * (180.0 / M_PI));
            //res.lineTo(ex, ey);

            lastx = ex;
            lasty = ey;
        }
        else if (param.value(0) == "OE") {
            res.closeSubpath();
        }

    }
    return res;
}

bool PcbCamParserHelper::parseOdbFont(const QByteArray &iData, PcbCamFont *oFont)
{
    if (oFont == nullptr) return false;

    QList<PcbCamFontCharLine> currentCharLines;
    QChar currentChar;

    bool inblock = false;
    QTextStream stream(iData);
    QString line;
    while (stream.readLineInto(&line)) {
        line = line.trimmed();
        if (line.startsWith("#") || line.length() == 0) { //comment
            continue;
        }

        QStringList param = line.split(" ", Qt::SkipEmptyParts);

        if (inblock) {
            if (line.startsWith("ECHAR")) {
                oFont->setCharLines(currentChar, currentCharLines);
                currentCharLines.clear();
                inblock = false;
            }
            else if (line.startsWith("LINE")) {
                PcbCamFontCharLine charline;
                double xs = param.value(1, "0.0").toDouble();
                double ys = param.value(2, "0.0").toDouble();
                double xe = param.value(3, "0.0").toDouble();
                double ye = param.value(4, "0.0").toDouble();
                charline.setLine(QLineF(xs, ys, xe, ye));
                charline.setPolarity(param.value(5) == "N" ? PcbCam::Negative : PcbCam::Positive);
                charline.setShape(param.value(6) == "S" ? PcbCamFontCharLine::LineShape_S : PcbCamFontCharLine::LineShape_R);
                charline.setWidth(param.value(7, "0.0").toDouble());
                currentCharLines.append(charline);
            }
            continue;
        }

        if (line.startsWith("XSIZE")) {
            oFont->setSizeX(param.value(1).toDouble());
        }
        else if (line.startsWith("YSIZE")) {
            oFont->setSizeY(param.value(1).toDouble());
        }
        else if (line.startsWith("OFFSET")) {
            oFont->setOffset(param.value(1).toDouble());
        }
        else if (line.startsWith("CHAR")) {
            currentChar = param.value(1, " ").at(0);
            inblock = true;
        }

    }
    return true;
}



PcbCamParserHelper::PcbCamParserHelper()
{

}