#include "odbmatrixparser.h"
#include <QFile>
#include <QTextStream>


class PcbCamOdbMatrixParserPrivate
{
    Q_DECLARE_PUBLIC(PcbCamOdbMatrixParser)
public:
    PcbCamOdbMatrixParserPrivate(PcbCamOdbMatrixParser *qptr):q_ptr(qptr){}
    ~PcbCamOdbMatrixParserPrivate(){}

    QByteArray data;
    QMap<QString, int> steps;
    QList<PcbCamMatrixLayer> layers;
    QStringList errors;

protected:
    PcbCamOdbMatrixParser * const q_ptr;
};

PcbCamOdbMatrixParser::PcbCamOdbMatrixParser(QObject *parent) : QObject(parent),
    d_ptr(new PcbCamOdbMatrixParserPrivate(this))
{

}

PcbCamOdbMatrixParser::PcbCamOdbMatrixParser(const QByteArray &iData, QObject *parent) : QObject(parent),
    d_ptr(new PcbCamOdbMatrixParserPrivate(this))
{
    Q_D(PcbCamOdbMatrixParser);
    d->data = iData;
}

PcbCamOdbMatrixParser::~PcbCamOdbMatrixParser()
{

}

void PcbCamOdbMatrixParser::setData(const QByteArray &iData)
{
    Q_D(PcbCamOdbMatrixParser);
    d->data = iData;
}

void PcbCamOdbMatrixParser::parse()
{
    Q_D(PcbCamOdbMatrixParser);
    d->errors.clear();
    d->layers.clear();
    d->steps.clear();

    int block = 0; //1:step, 2:layer, 0:other
    int tmpStepCol {0};
    QString tmpStepName;
    PcbCamMatrixLayer tmpLayer;
    QTextStream stream(d->data);
    QString line;
    while (stream.readLineInto(&line)) {
        line = line.trimmed();
        if (line.length() == 0) continue;
        if (line.startsWith("STEP") && line.endsWith(" {")) {
            block = 1;
        }
        else if (line.startsWith("LAYER") && line.endsWith(" {")) {
            block = 2;
        }
        else if (line.startsWith("}")) {
            if (block == 1) {
                d->steps.insert(tmpStepName, tmpStepCol);
            }
            else if (block == 2) {
                d->layers.append(tmpLayer);
            }
            block = 0;
        }
        else {
            if (block == 1) {
                int loc = line.indexOf('=');
                QString k = line.left(loc).trimmed();
                QString v = line.mid(loc+1).trimmed();
                if (k == "COL") {
                    tmpStepCol = v.toInt();
                }
                else if (k == "NAME") {
                    tmpStepName = v.toLower();
                }
            }
            else if (block == 2 ) {
                int loc = line.indexOf('=');
                QString k = line.left(loc).trimmed();
                QString v = line.mid(loc+1).trimmed();
                if (k == "ROW") {
                    tmpLayer.setRow(v.toInt());
                }
                else if (k == "CONTEXT") {
                    if (v == "BOARD") {
                        tmpLayer.setContext(PcbCam::BoardContext);
                    }
                    else {
                        tmpLayer.setContext(PcbCam::MiscContext);
                    }
                }
                else if (k == "TYPE") {
                    tmpLayer.setType(v.toLower());
                }
                else if (k == "NAME") {
                    tmpLayer.setName(v.toLower());
                }
                else if (k == "POLARITY") {
                    if (v == "NEGATIVE") {
                        tmpLayer.setPolarity(PcbCam::Negative);
                    }
                    else {
                        tmpLayer.setPolarity(PcbCam::Positive);
                    }
                }
                else if (k == "OLD_NAME") {
                    tmpLayer.setOldName(v);
                }
                else if (k == "START_NAME") {
                    tmpLayer.setStartName(v);
                }
                else if (k == "END_NAME") {
                    tmpLayer.setEndName(v);
                }
            }
        }
    }
}

QMap<QString, int> PcbCamOdbMatrixParser::steps() const
{
    Q_D(const PcbCamOdbMatrixParser);
    return d->steps;
}

QList<PcbCamMatrixLayer> PcbCamOdbMatrixParser::layers() const
{
    Q_D(const PcbCamOdbMatrixParser);
    return d->layers;
}

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

