/*
 *
 *    Copyright (c) 2020 Project CHIP Authors
 *    Copyright (c) 2013-2018 Nest Labs, Inc.
 *
 *    Licensed under the Apache License, Version 2.0 (the "License");
 *    you may not use this file except in compliance with the License.
 *    You may obtain a copy of the License at
 *
 *        http://www.apache.org/licenses/LICENSE-2.0
 *
 *    Unless required by applicable law or agreed to in writing, software
 *    distributed under the License is distributed on an "AS IS" BASIS,
 *    WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 *    See the License for the specific language governing permissions and
 *    limitations under the License.
 */

/**
 *    @file
 *      This file sets up fault injection for all POSIX CHIP Inet layer library test
 *      applications and tools.
 *
 *      NOTE: These do not comprise a public part of the CHIP API and
 *            are subject to change without notice.
 *
 */

#include "TestInetCommonOptions.h"
#include "TestSetupFaultInjection.h"
#include <inet/InetFaultInjection.h>
#include <lib/support/CHIPFaultInjection.h>
#include <lib/support/CodeUtils.h>
#include <lib/support/ScopedBuffer.h>
#include <system/SystemFaultInjection.h>

#include <stdio.h>
#include <unistd.h>

struct RestartCallbackContext
{
    int mArgc;
    char ** mArgv;
};

static void RebootCallbackFn();
static void PostInjectionCallbackFn(nl::FaultInjection::Manager * aManager, nl::FaultInjection::Identifier aId,
                                    nl::FaultInjection::Record * aFaultRecord);

static struct RestartCallbackContext sRestartCallbackCtx;
static nl::FaultInjection::Callback sFuzzECHeaderCb;
static nl::FaultInjection::Callback sAsyncEventCb;

// clang-format off
static nl::FaultInjection::GlobalContext sFaultInjectionGlobalContext = {
    {
        RebootCallbackFn,
        PostInjectionCallbackFn
    }
};
// clang-format on

bool gSigusr1Received = false;

static void RebootCallbackFn()
{
    size_t i;
    size_t j = 0;
    chip::Platform::ScopedMemoryBuffer<char *> lArgv;
    if (!lArgv.Alloc(static_cast<size_t>(sRestartCallbackCtx.mArgc + 2)))
    {
        printf("** failed to allocate memory **\n");
        return;
    }

    if (gSigusr1Received)
    {
        printf("** skipping restart case after SIGUSR1 **\n");
        return;
    }

    for (i = 0; sRestartCallbackCtx.mArgv[i] != nullptr; i++)
    {
        if (strcmp(sRestartCallbackCtx.mArgv[i], "--faults") == 0)
        {
            // Skip the --faults argument for now
            i++;
            continue;
        }
        lArgv[j++] = sRestartCallbackCtx.mArgv[i];
    }

    lArgv[j] = nullptr;

    for (size_t idx = 0; lArgv[idx] != nullptr; idx++)
    {
        printf("argv[%d]: %s\n", static_cast<int>(idx), lArgv[idx]);
    }

    // Need to close any open file descriptor above stdin/out/err.
    // There is no portable way to get the max fd number.
    // Given that CHIP's test apps don't open a large number of files,
    // FD_SETSIZE should be a reasonable upper bound (see the documentation
    // of select).
    for (int fd = 3; fd < FD_SETSIZE; fd++)
    {
        close(fd);
    }

    printf("********** Restarting *********\n");
    fflush(stdout);
    execvp(lArgv[0], lArgv.Get());
}

static void PostInjectionCallbackFn(nl::FaultInjection::Manager * aManager, nl::FaultInjection::Identifier aId,
                                    nl::FaultInjection::Record * aFaultRecord)
{
    uint16_t numargs = aFaultRecord->mNumArguments;
    uint16_t i;

    printf("***** Injecting fault %s_%s, instance number: %" PRIu32 "; reboot: %s", aManager->GetName(),
           aManager->GetFaultNames()[aId], aFaultRecord->mNumTimesChecked, aFaultRecord->mReboot ? "yes" : "no");
    if (numargs)
    {
        printf(" with %u args:", numargs);

        for (i = 0; i < numargs; i++)
        {
            printf(" %" PRIi32, aFaultRecord->mArguments[i]);
        }
    }

    printf("\n");
}

static bool PrintFaultInjectionMaxArgCbFn(nl::FaultInjection::Manager & mgr, nl::FaultInjection::Identifier aId,
                                          nl::FaultInjection::Record * aFaultRecord, void * aContext)
{
    const char * faultName = mgr.GetFaultNames()[aId];

    if (gFaultInjectionOptions.PrintFaultCounters && aFaultRecord->mNumArguments)
    {
        printf("FI_instance_params: %s_%s_s%" PRIu32 " maxArg: %" PRIi32 ";\n", mgr.GetName(), faultName,
               aFaultRecord->mNumTimesChecked, aFaultRecord->mArguments[0]);
    }

    return false;
}

static bool PrintCHIPFaultInjectionMaxArgCbFn(nl::FaultInjection::Identifier aId, nl::FaultInjection::Record * aFaultRecord,
                                              void * aContext)
{
    nl::FaultInjection::Manager & mgr = chip::FaultInjection::GetManager();

    return PrintFaultInjectionMaxArgCbFn(mgr, aId, aFaultRecord, aContext);
}

static bool PrintSystemFaultInjectionMaxArgCbFn(nl::FaultInjection::Identifier aId, nl::FaultInjection::Record * aFaultRecord,
                                                void * aContext)
{
    nl::FaultInjection::Manager & mgr = chip::System::FaultInjection::GetManager();

    return PrintFaultInjectionMaxArgCbFn(mgr, aId, aFaultRecord, aContext);
}

void SetupFaultInjectionContext(int argc, char * argv[])
{
    SetupFaultInjectionContext(argc, argv, nullptr, nullptr);
}

void SetupFaultInjectionContext(int argc, char * argv[], int32_t (*aNumEventsAvailable)(),
                                void (*aInjectAsyncEvents)(int32_t index))
{
    nl::FaultInjection::Manager & weavemgr  = chip::FaultInjection::GetManager();
    nl::FaultInjection::Manager & systemmgr = chip::System::FaultInjection::GetManager();

    sRestartCallbackCtx.mArgc = argc;
    sRestartCallbackCtx.mArgv = argv;

    nl::FaultInjection::SetGlobalContext(&sFaultInjectionGlobalContext);

    memset(&sFuzzECHeaderCb, 0, sizeof(sFuzzECHeaderCb));
    sFuzzECHeaderCb.mCallBackFn = PrintCHIPFaultInjectionMaxArgCbFn;
    weavemgr.InsertCallbackAtFault(chip::FaultInjection::kFault_FuzzExchangeHeaderTx, &sFuzzECHeaderCb);

    if (aNumEventsAvailable && aInjectAsyncEvents)
    {
        memset(&sAsyncEventCb, 0, sizeof(sAsyncEventCb));
        sAsyncEventCb.mCallBackFn = PrintSystemFaultInjectionMaxArgCbFn;
        systemmgr.InsertCallbackAtFault(chip::System::FaultInjection::kFault_AsyncEvent, &sAsyncEventCb);

        chip::System::FaultInjection::SetAsyncEventCallbacks(aNumEventsAvailable, aInjectAsyncEvents);
    }
}
