#include "odbcomponentparser.h"
#include <QTextStream>
#include <QStringList>
#include <QtMath>


class PcbCamOdbComponentParserPrivate
{
    Q_DECLARE_PUBLIC(PcbCamOdbComponentParser)
public:
    PcbCamOdbComponentParserPrivate(PcbCamOdbComponentParser *qptr) : q_ptr(qptr){ }
    ~PcbCamOdbComponentParserPrivate() { }

    QList<PcbCamOdbFeatureInfo> featureList;
    QStringList errorList;
    QByteArray featData;

    QHash<int, QString> symbolsHash;
    QHash<int, QString> attrNameHash;
    QHash<int, QString> attrTextHash;

protected:
    PcbCamOdbComponentParser * const q_ptr;
};

PcbCamOdbComponentParser::PcbCamOdbComponentParser(const QByteArray &iData)
    : d_ptr(new PcbCamOdbComponentParserPrivate(this))
{
    Q_D(PcbCamOdbComponentParser);
    d->featData = iData;
}

PcbCamOdbComponentParser::~PcbCamOdbComponentParser()
{

}

void PcbCamOdbComponentParser::parse()
{
    Q_D(PcbCamOdbComponentParser);
    d->attrNameHash.clear();
    d->attrTextHash.clear();
    d->featureList.clear();
    d->errorList.clear();

    QTextStream stream(&d->featData);
    QString line;
    while (stream.readLineInto(&line)) {
        if (line.startsWith("#") || line.length() == 0) { // comment
            continue;
        }

        if (line.startsWith("@")) { // symbol names
            parseAttrName(line);
        }
        else if (line.startsWith("&")) { // attr text strings
            parseAttrText(line);
        }
        else if (line.startsWith("CMP")) { // component
            parseComponent(line);
        }
    }
}

QList<PcbCamOdbFeatureInfo> PcbCamOdbComponentParser::features()
{
    Q_D(const PcbCamOdbComponentParser);
    return d->featureList;
}

QStringList PcbCamOdbComponentParser::errors()
{
    Q_D(const PcbCamOdbComponentParser);
    return d->errorList;
}


void PcbCamOdbComponentParser::parseAttrName(const QString &iLine)
{
    Q_D(PcbCamOdbComponentParser);
    QStringList tmp = iLine.split(" ", Qt::SkipEmptyParts);
    if (tmp.length() == 2) {
        d->attrNameHash.insert(tmp[0].mid(1).toInt(), tmp[1]);
    }
}

void PcbCamOdbComponentParser::parseAttrText(const QString &iLine)
{
    Q_D(PcbCamOdbComponentParser);
    QStringList tmp = iLine.split(" ", Qt::SkipEmptyParts);
    if (tmp.length() == 2) {
        d->attrTextHash.insert(tmp[0].mid(1).toInt(), tmp[1]);
    }
}

void PcbCamOdbComponentParser::parseComponent(const QString &iLine)
{
    Q_D(PcbCamOdbComponentParser);
    QStringList param;
    QVariantMap attrmap;
    parseAttributes(iLine, &param, &attrmap);

    // CMP <pkg_ref> <x> <y> <rot> <mirror> <comp_name> <part_name> ; <attributes>
    PcbCamOdbFeatureInfo feat;
    feat.type = PcbCam::ComponentFeature;
    feat.ps = QPointF(param.value(2).toDouble(), param.value(3).toDouble());
    feat.symbol = param.value(1);
    feat.widthFactor = param.value(4).toDouble(); // 为了节省内层空间,角度<rot>放在widthFactor里
    feat.cw = (param.value(5) == "Y"); // 为了节省内层空间,是否镜像<mirror>放在cw里
    feat.text = param.value(6); // comp_name
    feat.font = param.value(7); // part_name
    feat.attributes = attrmap;
    d->featureList.append(feat);
}

void PcbCamOdbComponentParser::parseAttributes(const QString &iLine, QStringList *oParams, QVariantMap *oAttrMap) const
{
    Q_D(const PcbCamOdbComponentParser);
    //拆分属性
    //CMP 9 3.7385827 5.1106299 180.0 N J7002 998-6533 ;0=2,1=0.166142
    int loc = iLine.lastIndexOf(";");
    QString record = iLine.left(loc).trimmed();
    QString attr;
    if (loc != -1) {
        attr = iLine.right(iLine.length() - loc - 1).trimmed();
    }

    //拆分文字的单引号
    //CMP 9 3.7385827 5.1106299 180.0 N 'J7002 1' 998-6533 1;0
    if (record.indexOf("'") != -1) {
        int loc = record.indexOf("'");
        int loc2 = record.indexOf("'", loc + 1);
        QString left = record.left(loc);
        QString middle = record.mid(loc + 1, loc2 - loc - 1);
        QString right = record.right(record.length() - loc2 - 1);
        *oParams = left.split(" ", Qt::SkipEmptyParts);
        *oParams << middle;
        *oParams += right.split(" ", Qt::SkipEmptyParts);
    } else {
        *oParams = record.split(" ", Qt::SkipEmptyParts);
    }

    if (!attr.isEmpty()) {
        QStringList terms = attr.split(',');
        for (int i = 0; i < terms.size(); ++i) {
            QStringList v = terms[i].split('=');
            QString key = d->attrNameHash.value(v[0].toInt());
            if (v.size() == 1) {
                oAttrMap->insert(key, QVariant(true));
            } else {
                oAttrMap->insert(key, d->attrTextHash.value(v[1].toInt()));
            }
        }
    }
}