#include <stdio.h>
#include <assert.h>
#include "DebugCore.h"
#include "DebugService.h"
#include "TcpLogger.h"
#include "ConfigurationDatabase.h"
#include "ObjectRegistryDatabase.h"
#include "StandardParser.h"

using namespace MARTe;

void TestRingBuffer() {
    printf("Testing TraceRingBuffer...\n");
    TraceRingBuffer rb;
    // Each entry is 4(ID) + 4(Size) + 4(Val) = 12 bytes.
    // 100 entries = 1200 bytes.
    assert(rb.Init(2048));
    
    // Fill buffer to test wrap-around
    uint32 id = 1;
    uint32 val = 0xAAAAAAAA;
    uint32 size = 4;
    
    for (int i=0; i<100; i++) {
        id = i;
        val = 0xBBBB0000 | i;
        if (!rb.Push(id, &val, size)) {
            printf("Failed at iteration %d\n", i);
            assert(false);
        }
    }
    
    assert(rb.Count() == 100 * (4 + 4 + 4));
    
    uint32 pId, pVal, pSize;
    for (int i=0; i<100; i++) {
        assert(rb.Pop(pId, &pVal, pSize, 4));
        assert(pId == (uint32)i);
        assert(pVal == (0xBBBB0000 | (uint32)i));
    }
    
    assert(rb.Count() == 0);
    printf("TraceRingBuffer test passed.\n");
}

void TestSuffixMatch() {
    printf("Testing SuffixMatch...\n");
    
    DebugService service;
    uint32 mock = 0;
    service.RegisterSignal(&mock, UnsignedInteger32Bit, "App.Data.Timer.Counter");
    
    // Should match
    assert(service.TraceSignal("App.Data.Timer.Counter", true) == 1);
    assert(service.TraceSignal("Timer.Counter", true) == 1);
    assert(service.TraceSignal("Counter", true) == 1);
    
    // Should NOT match
    assert(service.TraceSignal("App.Timer", true) == 0);
    assert(service.TraceSignal("unt", true) == 0);
    
    printf("SuffixMatch test passed.\n");
}

void TestTcpLogger() {
    printf("Testing TcpLogger...\n");
    TcpLogger logger;
    ConfigurationDatabase config;
    config.Write("Port", (uint16)9999);
    assert(logger.Initialise(config));
    
    REPORT_ERROR_STATIC(ErrorManagement::Information, "Unit Test Log Message");
    
    printf("TcpLogger basic test passed.\n");
}

void TestDebugServiceRegistration() {
    printf("Testing DebugService Signal Registration...\n");
    DebugService service;
    uint32 val1 = 10;
    float32 val2 = 20.0;
    
    DebugSignalInfo* s1 = service.RegisterSignal(&val1, UnsignedInteger32Bit, "Signal1");
    DebugSignalInfo* s2 = service.RegisterSignal(&val2, Float32Bit, "Signal2");
    
    assert(s1 != NULL_PTR(DebugSignalInfo*));
    assert(s2 != NULL_PTR(DebugSignalInfo*));
    assert(s1->internalID == 0);
    assert(s2->internalID == 1);
    
    // Re-register same address
    DebugSignalInfo* s1_alias = service.RegisterSignal(&val1, UnsignedInteger32Bit, "Signal1_Alias");
    assert(s1_alias == s1); 
    
    printf("DebugService registration test passed.\n");
}

int main(int argc, char **argv) {
    printf("Running MARTe2 Debug Suite Unit Tests...\n");
    
    TestRingBuffer();
    TestDebugServiceRegistration();
    TestSuffixMatch();
    TestTcpLogger();
    
    printf("\nALL UNIT TESTS PASSED!\n");
    return 0;
}
