///////////////////////////////////////////////////////////////////////////////////
// Copyright (C) 2018-2019, 2021-2023 Edouard Griffiths, F4EXB <f4exb06@gmail.com> //
// Copyright (C) 2022 Jon Beniston, M7RCE <jon@beniston.com>                     //
//                                                                               //
// This program is free software; you can redistribute it and/or modify          //
// it under the terms of the GNU General Public License as published by          //
// the Free Software Foundation as version 3 of the License, or                  //
// (at your option) any later version.                                           //
//                                                                               //
// This program is distributed in the hope that it will be useful,               //
// but WITHOUT ANY WARRANTY; without even the implied warranty of                //
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the                  //
// GNU General Public License V3 for more details.                               //
//                                                                               //
// You should have received a copy of the GNU General Public License             //
// along with this program. If not, see <http://www.gnu.org/licenses/>.          //
///////////////////////////////////////////////////////////////////////////////////

#include <QCommandLineOption>
#include <QRegularExpressionValidator>
#include <QDebug>

#include "parserbench.h"

ParserBench::ParserBench() :
    m_testOption(QStringList() << "t" << "test",
        "Test type: decimateii, decimatefi, decimateff, decimateif, decimateinfii, decimatesupii, ambe, golay2312, ft8, ft4, ft8protocols, callsign, fftrrcfilter, firrrcfilter, meshtastic.",
        "test",
        "decimateii"),
    m_nbSamplesOption(QStringList() << "n" << "nb-samples",
        "Number of sample to deal with.",
        "samples",
        "1048576"),
    m_repetitionOption(QStringList() << "r" << "repeat",
        "Number of repetitions.",
        "repetition",
        "1"),
    m_log2FactorOption(QStringList() << "l" << "log2-factor",
        "Log2 factor for rate conversion.",
        "log2",
        "2"),
    m_fileOption(QStringList() << "f" << "file",
        "File to be used for the test.",
        "file",
        ""),
    m_argsOption(QStringList() << "a" << "args",
        "Custom arguments string to be used for the test.",
        "args",
        "")
{
    m_testStr = "decimateii";
    m_nbSamples = 1048576;
    m_repetition = 1;
    m_log2Factor = 4;

    m_parser.setApplicationDescription("Software Defined Radio application benchmarks");
    m_parser.addHelpOption();
    m_parser.addVersionOption();

    m_parser.addOption(m_testOption);
    m_parser.addOption(m_nbSamplesOption);
    m_parser.addOption(m_repetitionOption);
    m_parser.addOption(m_log2FactorOption);
    m_parser.addOption(m_fileOption);
    m_parser.addOption(m_argsOption);
}

ParserBench::~ParserBench()
{ }

void ParserBench::parse(const QCoreApplication& app)
{
    m_parser.process(app);

    int pos;
    bool ok;

    // test switch

    QString test = m_parser.value(m_testOption);

    QString testStr = "([a-z0-9]+)";
    QRegularExpression ipRegex ("^" + testStr + "$");
    QRegularExpressionValidator ipValidator(ipRegex);

    if (ipValidator.validate(test, pos) == QValidator::Acceptable) {
        m_testStr = test;
    } else {
        qWarning() << "ParserBench::parse: test string invalid. Defaulting to " << m_testStr;
    }

    // number of samples

    QString nbSamplesStr = m_parser.value(m_nbSamplesOption);
    int nbSamples = nbSamplesStr.toInt(&ok);

    if (ok && (nbSamples > 1024) && (nbSamples < 1073741824)) {
        m_nbSamples = nbSamples;
    } else {
        qWarning() << "ParserBench::parse: number of samples invalid. Defaulting to " << m_nbSamples;
    }

    // repetition

    QString repetitionStr = m_parser.value(m_repetitionOption);
    int repetition = repetitionStr.toInt(&ok);

    if (ok && (repetition >= 0)) {
        m_repetition = repetition;
    } else {
        qWarning() << "ParserBench::parse: repetition invalid. Defaulting to " << m_repetition;
    }

    // log2 factor

    QString log2FactorStr = m_parser.value(m_log2FactorOption);
    int log2Factor = log2FactorStr.toInt(&ok);

    if (ok && (log2Factor >= 0) && (log2Factor <= 6)) {
        m_log2Factor = log2Factor;
    } else {
        qWarning() << "ParserBench::parse: repetilog2 factortion invalid. Defaulting to " << m_log2Factor;
    }

    // file

    m_fileName = m_parser.value(m_fileOption);

    // custom args

    m_argsStr = m_parser.value(m_argsOption);
}

ParserBench::TestType ParserBench::getTestType() const
{
    if (m_testStr == "decimatefi") {
        return TestDecimatorsFI;
    } else if (m_testStr == "decimateff") {
        return TestDecimatorsFF;
    } else if (m_testStr == "decimateif") {
        return TestDecimatorsIF;
    } else if (m_testStr == "decimateinfii") {
        return TestDecimatorsInfII;
    } else if (m_testStr == "decimatesupii") {
        return TestDecimatorsSupII;
    } else if (m_testStr == "golay2312") {
        return TestGolay2312;
    } else if (m_testStr == "ft8") {
        return TestFT8;
    } else if (m_testStr == "ft4") {
        return TestFT4;
    } else if (m_testStr == "callsign") {
        return TestCallsign;
    } else if (m_testStr == "ft8protocols") {
        return TestFT8Protocols;
    } else if (m_testStr == "fftrrcfilter") {
        return TestFFTRRCFilter;
    } else if (m_testStr == "firrrcfilter") {
        return TestFIRRRCFilter;
    } else if (m_testStr == "meshtastic") {
        return TestMeshtastic;
    } else {
        return TestDecimatorsII;
    }
}
