// Copyright (c) 2020 Metrolab Technology S.A., Geneva, Switzerland (www.metrolab.com)
// See the included file LICENSE.txt for the licensing conditions.

//////////////////////////////////////////////////////////////////////////
/// \file
/// \brief Test IEEE488Instrument API: Utility functions.

#include <regex>

#include "IEEE488InstrumentTest.h"
#include "Helpers.h"
#include "Exception.h"

bool FetchIEEE4888Resource (IEEE4888_TEST_RESOURCE_MANAGER_CLASS & rResourceManager, tResourceName & rInstrumentName)
{
    try
    {
        // Open a connection to the the resource manager
        if (!rResourceManager.Initialize())
            throw MTL::CException<CIEEE488Instrument>("Could not initialize resource manager", MTL__LOCATION__);

        // Find all instruments.
        CResourceList l_InstrumentList;
        if (!rResourceManager.FindResources(l_InstrumentList, IEEE4888_TEST_RESOURCE_FILTER) || l_InstrumentList.empty())
            throw MTL::CException<CIEEE488Instrument>("Could not find instrument", MTL__LOCATION__);

        // Run the tests on the first one in the list.
        rInstrumentName = l_InstrumentList.front();
    }
    catch (MTL::CException<CIEEE488Instrument> & rE)
    {
        std::cout << "l_CManagerException: " << rE.what() << std::endl;
        rInstrumentName = "";
        return false;
    }

    return true;
}

bool ConnectToIEEE488Instrument (IEEE4888_TEST_RESOURCE_MANAGER_CLASS * & rpResourceManager, IEEE4888_TEST_INSTRUMENT_CLASS * & rpInstrument)
{
    try
    {
        // Create the resource manager.
        rpResourceManager = new IEEE4888_TEST_RESOURCE_MANAGER_CLASS;

        // Fetch the instrument resource name.
        tResourceName			l_InstrumentName;
        if (!FetchIEEE4888Resource(*rpResourceManager, l_InstrumentName))
            throw MTL::CException<CIEEE488Instrument>("Could not find instrument", MTL__LOCATION__);

        // Create the instrument object.
        rpInstrument = new IEEE4888_TEST_INSTRUMENT_CLASS(*rpResourceManager, l_InstrumentName);
        if (nullptr == rpInstrument)
            throw MTL::CException<CIEEE488Instrument>("Unable to create instrument object", MTL__LOCATION__);

        // Connect to the instrument.
        if (!rpInstrument->Open())
            throw MTL::CException<CIEEE488Instrument>("Unable to connect to instrument", MTL__LOCATION__);
    }
    catch (MTL::CException<CIEEE488Instrument> & rE)
    {
        std::cout << "l_CManagerException: " << rE.what() << std::endl;
        rpInstrument = nullptr;
        return false;
    }
    return true;
}

bool CheckIDNResponse (const CSCPIBuffer & rBuffer)
{
    std::string l_ID = std::string(rBuffer.begin(), rBuffer.end());
    std::regex  l_Regex("([^,]+), *([^,]+), *([^,]+), *([^,]+)");
    std::smatch l_Match;
    if (!std::regex_match(l_ID, l_Match, l_Regex))
        return false;

    std::string l_Manufacturer	= l_Match[1].str();
    std::string l_Model			= l_Match[2].str();
    std::string l_SerialNumber	= l_Match[3].str();
    std::string l_Versions		= l_Match[4].str();

    l_Regex = "(Metrolab.*)|(NATIONAL INSTRUMENTS)";
    if (!std::regex_match(l_Manufacturer, l_Regex))
        return false;

    l_Regex = "(0x1234)|([0-9]+)";
    if (!std::regex_match(l_SerialNumber, l_Regex))
        return false;

    l_Regex = "((THM1176)|(TFM1186)|(PT2026)|(FDI2056)|(SIMPLE IEEE 488.2 DEVICE)).*";
    if (!std::regex_match(l_Model, l_Regex))
        return false;

    if (l_Model.compare(0, 7, "THM1176") == 0)
        l_Regex = "el(([A-Z])([0-9]+))-pr(([A-Z])([0-9]+))-fw(([0-9]+)\\.([0-9]+))\\n";
    else if (l_Model.compare("SIMPLE IEEE 488.2 DEVICE") == 0)
        l_Regex = "0\n";
    else
        l_Regex = ".*\n";
    if (!std::regex_match(l_Versions, l_Regex))
        return false;

    return true;
}
