/*
 * Copyright (c) 2021 Stefan Strobel <stefan.strobel@shimatta.net>
 *
 * This Source Code Form is subject to the terms of the Mozilla Public
 * License, v. 2.0. If a copy of the MPL was not distributed with this
 * file, You can obtain one at https://mozilla.org/MPL/2.0/.
 */

/**
 * @file    test_integration_transport.cpp
 * @brief   integration test implementation for the transport layer
 * @author  Stefan Strobel <stefan.strobel@shimatta.net>
 */

#include "test/framework/catch.hpp"
extern "C" {
#include "shellmatta.h"
}
#include <string.h>

static uint32_t write_callCnt = 0u;
static char write_data[1024];
static uint32_t write_length;
static const char *doSomethingArguments;
static uint32_t doSomethingLength;
static char *doSomethingStdin;
static uint32_t doSomethingStdinLength;

static shellmatta_retCode_t writeFct(const char* data, uint32_t length)
{
    write_callCnt ++;
    while((length > 0) && (write_length < sizeof(write_data)))
    {
        write_data[write_length] = *data;
        data ++;
        length --;
        write_length ++;
    }

    return SHELLMATTA_OK;
}

static shellmatta_retCode_t doSomething(shellmatta_handle_t handle, const char *arguments, uint32_t length)
{
    doSomethingArguments = arguments;
    doSomethingLength = length;

    shellmatta_read(handle, &doSomethingStdin, &doSomethingStdinLength);

    shellmatta_printf(handle, "%s - length: %u", arguments, length);
    return SHELLMATTA_OK;
}
shellmatta_cmd_t doSomethingCmd = {(char*)"doSomething", (char*)"do", (char*)"Function does something", (char*)"use me, please", doSomething, NULL};

SCENARIO("Integration test of Transport layer", "[integration, transport]")
{
    GIVEN("Shellmatta up and running with one command")
    {
        shellmatta_instance_t inst;
        shellmatta_handle_t handle;
        char buffer[1024];
        char historyBuffer[1024];

        shellmatta_doInit(  &inst,
                            &handle,
                            buffer,
                            sizeof(buffer),
                            historyBuffer,
                            sizeof(historyBuffer),
                            "shellmatta->",
                            NULL,
                            writeFct);
        shellmatta_addCmd(handle, &doSomethingCmd);

        write_callCnt = 0u;
        memset(write_data, 0, sizeof(write_data));
        write_length = 0u;

        WHEN("Invalid CRC is passed")
        {
            /* check with invalid payload */
            shellmatta_processData(handle, (char*)"\x01\x01\x00\x16\x00\x00\x00\x00"
                                                  "doSomething argument\r\n"
                                                  "\x00\x00\x00\x00", 34u);

            THEN("Shellmatta responds with CRC error")
            {
                char *dummyData =   (char*)"crc error\r\n\r\nshellmatta->";

                CHECK( write_length == strlen(dummyData));
                REQUIRE( strcmp(dummyData, write_data) == 0);
            }
        }

        WHEN("Valid CRC is passed")
        {
            /* check with valid payload - disable echo to reduce cluttering */
            shellmatta_configure(handle, SHELLMATTA_MODE_INSERT, false, '\r');
            shellmatta_processData(handle, (char*)"\x01\x01\x00\x16\x00\x00\x00\x00"
                                                "doSomething argument\r\n"
                                                "\x7b\x49\xfa\x72", 34u);
            THEN("The shellmatta responds to the command")
            {
                char *dummyData =   (char*)"\x01\x01\x00\x21\x00\x00\x01\x01"
                                           "doSomething argument - length: 20"
                                            "\xac\xf5\xe9\x4f"
                                            "\x01\x01\x00\x02\x00\x00\x01\x02"
                                            "\r\n"
                                            "\x62\xef\x22\x7a"
                                            "\x01\x01\x00\x0C\x00\x00\x01\x03"
                                            "shellmatta->"
                                            "\xd2\x0b\x8f\x3e";

                CHECK( write_length == 83);
                REQUIRE( memcmp(write_data, dummyData, 83) == 0);

            }
        }
    }
}