#include "symbolfactory.h"
#include <QDebug>
#include "./symbol.h"


static QString formatNumber(double iNumber, int iPercision = 6)
{
    QString res = QString::number(iNumber, 'f', iPercision);
    if (res.contains(".")) {
        while (true) {
            if (res.at(res.length() - 1) == '0') {
                res.chop(1);
            }
            else {
                if (res.at(res.length() - 1) == '.') {
                    res.chop(1);
                }
                break;
            }
        }
    }
    return res;
}



PcbCamSymbol *PcbCamSymbolFactory::create(const QString &iName)
{
    QRegularExpression rx("^(r|s|rect|oval|di|oct|donut_r|donut_s|tri|hex_l|hex_s|bfr|bfs|ths|thr|oval_h|s_ths|s_tho|sr_ths|rc_ths|rc_tho|el|moire|hole)[0-9.]+");
    QRegularExpressionMatch match = rx.match(iName);
    if (!match.hasMatch()) {
        return new PcbCamSymbolUser(iName);
    }

    rx.setPattern("^r([0-9.]+)$");
    if (rx.match(iName).hasMatch()) {
        return new PcbCamSymbolR(iName);
    }

    rx.setPattern("^s([0-9.]+)$");
    if (rx.match(iName).hasMatch()) {
        return new PcbCamSymbolS(iName);
    }

    rx.setPattern("^rect([0-9.]+)x([0-9.]+)$");
    if (rx.match(iName).hasMatch()) {
        return new PcbCamSymbolRect(iName);
    }

    rx.setPattern("^oval([0-9.]+)x([0-9.]+)$");
    if (rx.match(iName).hasMatch()) {
        return new PcbCamSymbolOval(iName);
    }

    rx.setPattern("^thr([0-9.]+)x([0-9.]+)x([0-9.]+)x([0-9]+)x([0-9.]+)$");
    if (rx.match(iName).hasMatch()) {
        return new PcbCamSymbolThr(iName);
    }

    rx.setPattern("^ths([0-9.]+)x([0-9.]+)x([0-9.]+)x([0-9]+)x([0-9.]+)$");
    if (rx.match(iName).hasMatch()) {
        return new PcbCamSymbolThs(iName);
    }

    rx.setPattern("^s_ths([0-9.]+)x([0-9.]+)x([0-9.]+)x([0-9]+)x([0-9.]+)$");
    if (rx.match(iName).hasMatch()) {
        return new PcbCamSymbolSThs(iName);
    }

    rx.setPattern("^s_tho([0-9.]+)x([0-9.]+)x([0-9.]+)x([0-9]+)x([0-9.]+)$");
    if (rx.match(iName).hasMatch()) {
        return new PcbCamSymbolSTho(iName);
    }

    rx.setPattern("^donut_r([0-9.]+)x([0-9.]+)$");
    if (rx.match(iName).hasMatch()) {
        return new PcbCamSymbolDonutR(iName);
    }

    rx.setPattern("^donut_s([0-9.]+)x([0-9.]+)$");
    if (rx.match(iName).hasMatch()) {
        return new PcbCamSymbolDonutS(iName);
    }

    rx.setPattern("^di([0-9.]+)x([0-9.]+)$");
    if (rx.match(iName).hasMatch()) {
        return new PcbCamSymbolDi(iName);
    }

    rx.setPattern("^oct([0-9.]+)x([0-9.]+)x([0-9.]+)$");
    if (rx.match(iName).hasMatch()) {
        return new PcbCamSymbolOct(iName);
    }

    rx.setPattern("^hex_l([0-9.]+)x([0-9.]+)x([0-9.]+)$");
    if (rx.match(iName).hasMatch()) {
        return new PcbCamSymbolHexL(iName);
    }

    rx.setPattern("^hex_s([0-9.]+)x([0-9.]+)x([0-9.]+)$");
    if (rx.match(iName).hasMatch()) {
        return new PcbCamSymbolHexS(iName);
    }

    rx.setPattern("^bfr([0-9.]+)$");
    if (rx.match(iName).hasMatch()) {
        return new PcbCamSymbolBfr(iName);
    }

    rx.setPattern("^bfs([0-9.]+)$");
    if (rx.match(iName).hasMatch()) {
        return new PcbCamSymbolBfs(iName);
    }

    rx.setPattern("^tri([0-9.]+)x([0-9.]+)$");
    if (rx.match(iName).hasMatch()) {
        return new PcbCamSymbolTri(iName);
    }

    rx.setPattern("^oval_h([0-9.]+)x([0-9.]+)$");
    if (rx.match(iName).hasMatch()) {
        return new PcbCamSymbolOvalH(iName);
    }

    rx.setPattern("^rect([0-9.]+)x([0-9.]+)xr([0-9.]+)(?:x([1-4]+))?$");
    if (rx.match(iName).hasMatch()) {
        return new PcbCamSymbolRectR(iName);
    }

    rx.setPattern("^rect([0-9.]+)x([0-9.]+)xc([0-9.]+)(?:x([1-4]+))?$");
    if (rx.match(iName).hasMatch()) {
        return new PcbCamSymbolRectC(iName);
    }

    rx.setPattern("^sr_ths([0-9.]+)x([0-9.]+)x([0-9.]+)x([0-9]+)x([0-9.]+)$");
    if (rx.match(iName).hasMatch()) {
        return new PcbCamSymbolSrThs(iName);
    }

    rx.setPattern("^rc_ths([0-9.]+)x([0-9.]+)x([0-9.]+)x([0-9]+)x([0-9.]+)x([0-9.]+)$");
    if (rx.match(iName).hasMatch()) {
        return new PcbCamSymbolRcThs(iName);
    }

    rx.setPattern("^rc_tho([0-9.]+)x([0-9.]+)x([0-9.]+)x([0-9]+)x([0-9.]+)x([0-9.]+)$");
    if (rx.match(iName).hasMatch()) {
        return new PcbCamSymbolRcTho(iName);
    }

    rx.setPattern("^moire([0-9.]+)x([0-9.]+)x([0-9.]+)x([0-9.]+)x([0-9.]+)x([0-9.]+)$");
    if (rx.match(iName).hasMatch()) {
        return new PcbCamSymbolMoire(iName);
    }

    rx.setPattern("^el([0-9.]+)x([0-9.]+)$");
    if (rx.match(iName).hasMatch()) {
        return new PcbCamSymbolEl(iName);
    }

    return new PcbCamSymbolUser(iName);
}

QString PcbCamSymbolFactory::symbolScaledName(const QString &iName, double iScale, int iPercision)
{
    QRegularExpression rx("^(r|s|rect|oval|di|oct|donut_r|donut_s|tri|hex_l|hex_s|bfr|bfs|ths|thr|oval_h|s_ths|s_tho|sr_ths|rc_ths|rc_tho|el|moire|hole)[0-9.]+");
    QRegularExpressionMatch match = rx.match(iName);
    if (!match.hasMatch()) {
        return iName;
    }

    rx.setPattern("^r([0-9.]+)$");
    match = rx.match(iName);
    if (match.hasMatch()) {
        return QString("r%1")
                .arg(formatNumber(match.captured(1).toDouble() * iScale, iPercision));
    }

    rx.setPattern("^s([0-9.]+)$");
    match = rx.match(iName);
    if (match.hasMatch()) {
        return QString("s%1")
                .arg(formatNumber(match.captured(1).toDouble() * iScale, iPercision));
    }

    rx.setPattern("^rect([0-9.]+)x([0-9.]+)$");
    match = rx.match(iName);
    if (match.hasMatch()) {
        return QString("rect%1x%2")
                .arg(formatNumber(match.captured(1).toDouble() * iScale, iPercision))
                .arg(formatNumber(match.captured(2).toDouble() * iScale, iPercision));
    }

    rx.setPattern("^oval([0-9.]+)x([0-9.]+)$");
    match = rx.match(iName);
    if (match.hasMatch()) {
        return QString("oval%1x%2")
                .arg(formatNumber(match.captured(1).toDouble() * iScale, iPercision))
                .arg(formatNumber(match.captured(2).toDouble() * iScale, iPercision));
    }

    rx.setPattern("^thr([0-9.]+)x([0-9.]+)x([0-9.]+)x([0-9]+)x([0-9.]+)$");
    match = rx.match(iName);
    if (match.hasMatch()) {
        return QString("thr%1x%2x%3x%4x%5")
                .arg(formatNumber(match.captured(1).toDouble() * iScale, iPercision))
                .arg(formatNumber(match.captured(2).toDouble() * iScale, iPercision))
                .arg(formatNumber(match.captured(3).toDouble() * iScale, iPercision))
                .arg(match.captured(4))
                .arg(formatNumber(match.captured(5).toDouble() * iScale, iPercision));
    }

    rx.setPattern("^ths([0-9.]+)x([0-9.]+)x([0-9.]+)x([0-9]+)x([0-9.]+)$");
    match = rx.match(iName);
    if (match.hasMatch()) {
        return QString("ths%1x%2x%3x%4x%5")
                .arg(formatNumber(match.captured(1).toDouble() * iScale, iPercision))
                .arg(formatNumber(match.captured(2).toDouble() * iScale, iPercision))
                .arg(formatNumber(match.captured(3).toDouble() * iScale, iPercision))
                .arg(match.captured(4))
                .arg(formatNumber(match.captured(5).toDouble() * iScale, iPercision));
    }

    rx.setPattern("^s_ths([0-9.]+)x([0-9.]+)x([0-9.]+)x([0-9]+)x([0-9.]+)$");
    match = rx.match(iName);
    if (match.hasMatch()) {
        return QString("s_ths%1x%2x%3x%4x%5")
                .arg(formatNumber(match.captured(1).toDouble() * iScale, iPercision))
                .arg(formatNumber(match.captured(2).toDouble() * iScale, iPercision))
                .arg(formatNumber(match.captured(3).toDouble() * iScale, iPercision))
                .arg(match.captured(4))
                .arg(formatNumber(match.captured(5).toDouble() * iScale, iPercision));
    }

    rx.setPattern("^s_tho([0-9.]+)x([0-9.]+)x([0-9.]+)x([0-9]+)x([0-9.]+)$");
    match = rx.match(iName);
    if (match.hasMatch()) {
        return QString("s_tho%1x%2x%3x%4x%5")
                .arg(formatNumber(match.captured(1).toDouble() * iScale, iPercision))
                .arg(formatNumber(match.captured(2).toDouble() * iScale, iPercision))
                .arg(formatNumber(match.captured(3).toDouble() * iScale, iPercision))
                .arg(match.captured(4))
                .arg(formatNumber(match.captured(5).toDouble() * iScale, iPercision));
    }

    rx.setPattern("^donut_r([0-9.]+)x([0-9.]+)$");
    match = rx.match(iName);
    if (match.hasMatch()) {
        return QString("donut_r%1x%2")
                .arg(formatNumber(match.captured(1).toDouble() * iScale, iPercision))
                .arg(formatNumber(match.captured(2).toDouble() * iScale, iPercision));
    }

    rx.setPattern("^donut_s([0-9.]+)x([0-9.]+)$");
    match = rx.match(iName);
    if (match.hasMatch()) {
        return QString("donut_s%1x%2")
                .arg(formatNumber(match.captured(1).toDouble() * iScale, iPercision))
                .arg(formatNumber(match.captured(2).toDouble() * iScale, iPercision));
    }

    rx.setPattern("^di([0-9.]+)x([0-9.]+)$");
    match = rx.match(iName);
    if (match.hasMatch()) {
        return QString("di%1x%2")
                .arg(formatNumber(match.captured(1).toDouble() * iScale, iPercision))
                .arg(formatNumber(match.captured(2).toDouble() * iScale, iPercision));
    }

    rx.setPattern("^oct([0-9.]+)x([0-9.]+)x([0-9.]+)$");
    match = rx.match(iName);
    if (match.hasMatch()) {
        return QString("oct%1x%2x%3")
                .arg(formatNumber(match.captured(1).toDouble() * iScale, iPercision))
                .arg(formatNumber(match.captured(2).toDouble() * iScale, iPercision))
                .arg(formatNumber(match.captured(3).toDouble() * iScale, iPercision));
    }

    rx.setPattern("^hex_l([0-9.]+)x([0-9.]+)x([0-9.]+)$");
    match = rx.match(iName);
    if (match.hasMatch()) {
        return QString("hex_l%1x%2x%3")
                .arg(formatNumber(match.captured(1).toDouble() * iScale, iPercision))
                .arg(formatNumber(match.captured(2).toDouble() * iScale, iPercision))
                .arg(formatNumber(match.captured(3).toDouble() * iScale, iPercision));
    }

    rx.setPattern("^hex_s([0-9.]+)x([0-9.]+)x([0-9.]+)$");
    match = rx.match(iName);
    if (match.hasMatch()) {
        return QString("hex_s%1x%2x%3")
                .arg(formatNumber(match.captured(1).toDouble() * iScale, iPercision))
                .arg(formatNumber(match.captured(2).toDouble() * iScale, iPercision))
                .arg(formatNumber(match.captured(3).toDouble() * iScale, iPercision));
    }

    rx.setPattern("^bfr([0-9.]+)$");
    match = rx.match(iName);
    if (match.hasMatch()) {
        return QString("bfr%1")
                .arg(formatNumber(match.captured(1).toDouble() * iScale, iPercision));
    }

    rx.setPattern("^bfs([0-9.]+)$");
    match = rx.match(iName);
    if (match.hasMatch()) {
        return QString("bfs%1")
                .arg(formatNumber(match.captured(1).toDouble() * iScale, iPercision));
    }

    rx.setPattern("^tri([0-9.]+)x([0-9.]+)$");
    match = rx.match(iName);
    if (match.hasMatch()) {
        return QString("tri%1x%2")
                .arg(formatNumber(match.captured(1).toDouble() * iScale, iPercision))
                .arg(formatNumber(match.captured(2).toDouble() * iScale, iPercision));
    }

    rx.setPattern("^oval_h([0-9.]+)x([0-9.]+)$");
    match = rx.match(iName);
    if (match.hasMatch()) {
        return QString("oval_h%1x%2")
                .arg(formatNumber(match.captured(1).toDouble() * iScale, iPercision))
                .arg(formatNumber(match.captured(2).toDouble() * iScale, iPercision));
    }

    rx.setPattern("^rect([0-9.]+)x([0-9.]+)xr([0-9.]+)(x([1-4]+))?$");
    match = rx.match(iName);
    if (match.hasMatch()) {
        return QString("rect%1x%2xr%3%4")
                .arg(formatNumber(match.captured(1).toDouble() * iScale, iPercision))
                .arg(formatNumber(match.captured(2).toDouble() * iScale, iPercision))
                .arg(formatNumber(match.captured(3).toDouble() * iScale, iPercision))
                .arg(match.captured(4));
    }

    rx.setPattern("^rect([0-9.]+)x([0-9.]+)xc([0-9.]+)(x([1-4]+))?$");
    match = rx.match(iName);
    if (match.hasMatch()) {
        return QString("rect%1x%2xc%3%4")
                .arg(formatNumber(match.captured(1).toDouble() * iScale, iPercision))
                .arg(formatNumber(match.captured(2).toDouble() * iScale, iPercision))
                .arg(formatNumber(match.captured(3).toDouble() * iScale, iPercision))
                .arg(match.captured(4));
    }

    rx.setPattern("^sr_ths([0-9.]+)x([0-9.]+)x([0-9.]+)x([0-9]+)x([0-9.]+)$");
    match = rx.match(iName);
    if (match.hasMatch()) {
        return QString("sr_ths%1x%2x%3x%4x%5")
                .arg(formatNumber(match.captured(1).toDouble() * iScale, iPercision))
                .arg(formatNumber(match.captured(2).toDouble() * iScale, iPercision))
                .arg(formatNumber(match.captured(3).toDouble() * iScale, iPercision))
                .arg(match.captured(4))
                .arg(formatNumber(match.captured(5).toDouble() * iScale, iPercision));
    }

    rx.setPattern("^rc_ths([0-9.]+)x([0-9.]+)x([0-9.]+)x([0-9]+)x([0-9.]+)x([0-9.]+)$");
    match = rx.match(iName);
    if (match.hasMatch()) {
        return QString("rc_ths%1x%2x%3x%4x%5x%6")
                .arg(formatNumber(match.captured(1).toDouble() * iScale, iPercision))
                .arg(formatNumber(match.captured(2).toDouble() * iScale, iPercision))
                .arg(formatNumber(match.captured(3).toDouble() * iScale, iPercision))
                .arg(match.captured(4))
                .arg(formatNumber(match.captured(5).toDouble() * iScale, iPercision))
                .arg(formatNumber(match.captured(6).toDouble() * iScale, iPercision));
    }

    rx.setPattern("^rc_tho([0-9.]+)x([0-9.]+)x([0-9.]+)x([0-9]+)x([0-9.]+)x([0-9.]+)$");
    match = rx.match(iName);
    if (match.hasMatch()) {
        return QString("rc_tho%1x%2x%3x%4x%5x%6")
                .arg(formatNumber(match.captured(1).toDouble() * iScale, iPercision))
                .arg(formatNumber(match.captured(2).toDouble() * iScale, iPercision))
                .arg(formatNumber(match.captured(3).toDouble() * iScale, iPercision))
                .arg(match.captured(4))
                .arg(formatNumber(match.captured(5).toDouble() * iScale, iPercision))
                .arg(formatNumber(match.captured(6).toDouble() * iScale, iPercision));
    }

    rx.setPattern("^moire([0-9.]+)x([0-9.]+)x([0-9.]+)x([0-9.]+)x([0-9.]+)x([0-9.]+)$");
    match = rx.match(iName);
    if (match.hasMatch()) {
        return QString("moire%1x%2x%3x%4x%5x%6")
                .arg(formatNumber(match.captured(1).toDouble() * iScale, iPercision))
                .arg(formatNumber(match.captured(2).toDouble() * iScale, iPercision))
                .arg(formatNumber(match.captured(3).toDouble() * iScale, iPercision))
                .arg(formatNumber(match.captured(4).toDouble() * iScale, iPercision))
                .arg(formatNumber(match.captured(5).toDouble() * iScale, iPercision))
                .arg(formatNumber(match.captured(6).toDouble() * iScale, iPercision));
    }

    rx.setPattern("^el([0-9.]+)x([0-9.]+)$");
    match = rx.match(iName);
    if (match.hasMatch()) {
        return QString("el%1x%2")
                .arg(formatNumber(match.captured(1).toDouble() * iScale, iPercision))
                .arg(formatNumber(match.captured(2).toDouble() * iScale, iPercision));
    }

    return iName;
}