/*
 * Copyright (c) 2019 - 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_busy.cpp
 * @brief   integration test implementation for the cmd busy function
 * @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 uint32_t busyCallCnt;
static uint32_t notBusyCallCnt;
static bool suspendBusy;

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 busyCmdFct(shellmatta_handle_t handle, const char *arguments, uint32_t length)
{
    (void)      handle;
    (void)      arguments;
    (void)      length;
    shellmatta_retCode_t ret        = SHELLMATTA_BUSY;
    static const char   *callArgs   = NULL;
    static uint32_t     callLength  = 0u;;

    if(busyCallCnt < 10u)
    {
        if(NULL == callArgs)
        {
            callArgs    = arguments;
            callLength  = length;
        }
        else
        {
            CHECK(callArgs      == arguments);
            CHECK(callLength    == length);
        }

        busyCallCnt ++;
    }
    else
    {
        ret = SHELLMATTA_OK;
    }

    if(true == suspendBusy)
    {
        ret = SHELLMATTA_CONTINUE;
    }

    return ret;
}
shellmatta_cmd_t busyCmd = {(char*)"busy", (char*)"b", NULL, NULL, busyCmdFct, NULL};


static shellmatta_retCode_t notBusyCmdFct(shellmatta_handle_t handle, const char *arguments, uint32_t length)
{
    (void)      handle;
    (void)      arguments;
    (void)      length;

    notBusyCallCnt ++;

    return SHELLMATTA_OK;
}
shellmatta_cmd_t notBusyCmd = {(char*)"notBusy", (char*)"n", NULL, NULL, notBusyCmdFct, NULL};


TEST_CASE( "shellmatta busy 1" ) {

    shellmatta_retCode_t ret;
    shellmatta_instance_t inst;
    shellmatta_handle_t handle;
    char buffer[1024];
    char historyBuffer[1024];
    char *dummyData =   (char*) "busy and some arguments\r\n"
                                "\r\nshellmatta->notBusy and some arguments\r\n"
                                "\r\nshellmatta->";

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

    busyCallCnt = 0u;
    notBusyCallCnt = 0u;
    write_callCnt = 0u;
    memset(write_data, 0, sizeof(write_data));
    write_length = 0u;
    suspendBusy = false;

    shellmatta_addCmd(handle, &busyCmd);
    shellmatta_addCmd(handle, &notBusyCmd);

    do
    {
        ret = shellmatta_processData(handle, (char*)"busy and some arguments\r"
                                                    "notBusy and some arguments\r", 51);

    } while (SHELLMATTA_BUSY == ret);
    

    CHECK( 10u  == busyCallCnt);
    CHECK( 1u   == notBusyCallCnt );
    CHECK( write_length == strlen(dummyData));
    REQUIRE( strcmp(dummyData, write_data) == 0);
}

TEST_CASE( "shellmatta busy suspend with continuous mode" ) {

    shellmatta_retCode_t ret;
    shellmatta_instance_t inst;
    shellmatta_handle_t handle;
    char buffer[1024];
    char historyBuffer[1024];
    char *dummyData =   (char*) "busy and some arguments\r\n";

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

    busyCallCnt = 0u;
    notBusyCallCnt = 0u;
    write_callCnt = 0u;
    memset(write_data, 0, sizeof(write_data));
    write_length = 0u;
    suspendBusy = false;

    shellmatta_addCmd(handle, &busyCmd);
    shellmatta_addCmd(handle, &notBusyCmd);

    do
    {
        ret = shellmatta_processData(handle, (char*)"busy and some arguments\r123", 27u);

        suspendBusy = true;

    } while (SHELLMATTA_BUSY == ret);

    ret = shellmatta_processData(handle, (char*)"", 0u);

    CHECK( SHELLMATTA_CONTINUE == ret);
    CHECK( 6u  == busyCallCnt);
    CHECK( 0u   == notBusyCallCnt );
    CHECK( write_length == strlen(dummyData));
    REQUIRE( strcmp(dummyData, write_data) == 0);
}