////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
//                                                                                                                     /
// This library is free software; you can redistribute it and/or modify it under the terms of the provided License.    /
//                                                                                                                     /
// This library 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 Lesser General Public License for more/
// details.                                                                                                            /
// You should have received a copy of the the License along with this library.                                         /
//                                                                                                                     /
// 2012-2024 (c) Baical                                                                                                /
//                                                                                                                     /
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
#include "common.h"


////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
//////////////////////////////////////////uP7 callbacks/////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
uint64_t t7getTimerFrequency(void *i_pCtx)      { UNUSED_ARG(i_pCtx); return GetPerformanceFrequency(); }
uint64_t t7getTimerValue(void *i_pCtx)          { UNUSED_ARG(i_pCtx); return GetPerformanceCounter();   }
uint32_t t7getCurrentThreadId(void *i_pCtx)     { UNUSED_ARG(i_pCtx); return CProc::Get_Thread_Id();    }
bool     t7sendPacket(void *i_pCtx, enum euP7packetRank i_eRank, const struct stP7packetChunk *i_pChunks,
                      size_t  i_szChunks, size_t i_szData)
{
    UNUSED_ARG(i_eRank);
    IuP7Fifo  *l_pFifo = static_cast<IuP7Fifo  *>(i_pCtx);
    return l_pFifo->Write((IuP7Fifo::stChunk*)i_pChunks, i_szChunks, i_szData);
}


////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
bool t7Pattern(const tXCHAR *i_pSessionFolder)
{
    UNUSED_ARG(i_pSessionFolder);

    struct stuP7config l_stConfig; 

    l_stConfig.bSessionIdCrc7        = g_bCrc7;               /**< Session ID crc */ 
    l_stConfig.uSessionId            = g_uSessionId;          /**< Session ID*/  
    l_stConfig.pCtxTimer             = NULL;                  /**< Context for timer functions */
    l_stConfig.cbTimerFrequency      = t7getTimerFrequency;   /**< callback to get system high-resolution timer frequency */
    l_stConfig.cbTimerValue          = t7getTimerValue;       /**< callback to get system high-resolution timer value */
    l_stConfig.pCtxLock              = NULL;                  /**< Context for lock functions, set it to NULL if there is no RTOS*/
    l_stConfig.cbLock                = NULL;                  /**< callback to call OS lock function, set it to NULL if there is no RTOS */
    l_stConfig.cbUnLock              = NULL;                  /**< callback to call OS unlock function, set it to NULL if there is no RTOS */
    l_stConfig.pCtxPacket            = nullptr;               /**< Context for data sending */
    l_stConfig.cbSendPacket          = t7sendPacket;          /**< callback to send data packet to host */  
    l_stConfig.pCtxThread            = 0;                     /**< Context for cbGetCurrentThreadId function */
    l_stConfig.cbGetCurrentThreadId  = t7getCurrentThreadId;  /**< callback get current thread ID, set it to NULL if there is no RTOS*/  
    l_stConfig.eDefaultVerbosity     = euP7Level_Trace;       /**< Default verbosity*/  

    //Generated descriptors, located in uP7preprocessed.h
    l_stConfig.pModules              = g_pModules;            /**< Trace modules descriptors, generated by uP7 preprocessor*/
    l_stConfig.szModules             = g_szModules;           /**< Trace modules descriptors count*/  
    l_stConfig.pTraces               = g_pTraces;             /**< Trace descriptors, generated by uP7 preprocessor*/  
    l_stConfig.szTraces              = g_szTraces;            /**< Trace descriptors count*/  
    l_stConfig.pTelemetry            = g_pTelemetry;          /**< Telemetry descriptors, generated by uP7 preprocessor*/  
    l_stConfig.szTelemetry           = g_szTelemetry;         /**< Telemetry descriptors count*/  
    l_stConfig.eAlignment            = euP7alignment4;

    if (!uP7initialize(&l_stConfig))
    {
        return false; //we don't care about memory leak! test failed application will be closed
    }

    uP7TrcRegisterModules("TestA%[0..1]/TestB%[0..1]/TestC%02[0..3]<", euP7Level_Trace );
    uP7TelCreateCounters("Tel%02[1..10]<", 0, 0, 1, 1, true);

    huP7Module l_hModule = uP7_MODULE_INVALID_ID;
    huP7TelId  l_hCounter = uP7_TELEMETRY_INVALID_ID;

    if (!uP7TrcFindModule("TestA0/TestB0/TestC00<", &l_hModule))
    {
        printf("%d\n", __LINE__);
        return false;
    }

    if (!uP7TrcFindModule("TestA0/TestB0/TestC01<", &l_hModule))
    {
        printf("%d\n", __LINE__);
        return false;
    }

    if (!uP7TrcFindModule("TestA0/TestB0/TestC02<", &l_hModule))
    {
        printf("%d\n", __LINE__);
        return false;
    }

    if (!uP7TrcFindModule("TestA0/TestB0/TestC03<", &l_hModule))
    {
        printf("%d\n", __LINE__);
        return false;
    }

    if (!uP7TrcFindModule("TestA0/TestB1/TestC00<", &l_hModule))
    {
        printf("%d\n", __LINE__);
        return false;
    }

    if (!uP7TrcFindModule("TestA0/TestB1/TestC01<", &l_hModule))
    {
        printf("%d\n", __LINE__);
        return false;
    }

    if (!uP7TrcFindModule("TestA0/TestB1/TestC02<", &l_hModule))
    {
        printf("%d\n", __LINE__);
        return false;
    }

    if (!uP7TrcFindModule("TestA0/TestB1/TestC03<", &l_hModule))
    {
        printf("%d\n", __LINE__);
        return false;
    }

    if (!uP7TrcFindModule("TestA1/TestB0/TestC00<", &l_hModule))
    {
        printf("%d\n", __LINE__);
        return false;
    }

    if (!uP7TrcFindModule("TestA1/TestB0/TestC01<", &l_hModule))
    {
        printf("%d\n", __LINE__);
        return false;
    }

    if (!uP7TrcFindModule("TestA1/TestB0/TestC02<", &l_hModule))
    {
        printf("%d\n", __LINE__);
        return false;
    }

    if (!uP7TrcFindModule("TestA1/TestB0/TestC03<", &l_hModule))
    {
        printf("%d\n", __LINE__);
        return false;
    }

    if (!uP7TrcFindModule("TestA1/TestB1/TestC00<", &l_hModule))
    {
        printf("%d\n", __LINE__);
        return false;
    }

    if (!uP7TrcFindModule("TestA1/TestB1/TestC01<", &l_hModule))
    {
        printf("%d\n", __LINE__);
        return false;
    }

    if (!uP7TrcFindModule("TestA1/TestB1/TestC02<", &l_hModule))
    {
        printf("%d\n", __LINE__);
        return false;
    }

    if (!uP7TrcFindModule("TestA1/TestB1/TestC03<", &l_hModule))
    {
        printf("%d\n", __LINE__);
        return false;
    }




    if (!uP7TelFindCounter("Tel01<", &l_hCounter))
    {
        printf("%d\n", __LINE__);
        return false;
    }


    if (!uP7TelFindCounter("Tel02<", &l_hCounter))
    {
        printf("%d\n", __LINE__);
        return false;
    }

    if (!uP7TelFindCounter("Tel03<", &l_hCounter))
    {
        printf("%d\n", __LINE__);
        return false;
    }

    if (!uP7TelFindCounter("Tel04<", &l_hCounter))
    {
        printf("%d\n", __LINE__);
        return false;
    }

    if (!uP7TelFindCounter("Tel05<", &l_hCounter))
    {
        printf("%d\n", __LINE__);
        return false;
    }

    if (!uP7TelFindCounter("Tel06<", &l_hCounter))
    {
        printf("%d\n", __LINE__);
        return false;
    }

    if (!uP7TelFindCounter("Tel07<", &l_hCounter))
    {
        printf("%d\n", __LINE__);
        return false;
    }

    if (!uP7TelFindCounter("Tel08<", &l_hCounter))
    {
        printf("%d\n", __LINE__);
        return false;
    }

    if (!uP7TelFindCounter("Tel09<", &l_hCounter))
    {
        printf("%d\n", __LINE__);
        return false;
    }

    if (!uP7TelFindCounter("Tel10<", &l_hCounter))
    {
        printf("%d\n", __LINE__);
        return false;
    }

    uP7unInitialize();

    return true;
}
