/*
 *   Copyright (c) 2020 Project CHIP Authors
 *   All rights reserved.
 *
 *   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.
 *
 */

#include "Command.h"
#include "CustomStringPrefix.h"
#include "platform/PlatformManager.h"

#include <functional>
#include <netdb.h>
#include <sstream>
#include <sys/socket.h>
#include <sys/types.h>

#include <math.h> // For INFINITY

#include <lib/core/CHIPSafeCasts.h>
#include <lib/support/BytesToHex.h>
#include <lib/support/CHIPMem.h>
#include <lib/support/CodeUtils.h>
#include <lib/support/SafeInt.h>
#include <lib/support/ScopedBuffer.h>
#include <lib/support/logging/CHIPLogging.h>

constexpr const char * kOptionalArgumentPrefix = "--";
constexpr size_t kOptionalArgumentPrefixLength = 2;

bool Command::InitArguments(int argc, char ** argv)
{
    bool isValidCommand = false;

    size_t argvExtraArgsCount = (size_t) argc;
    size_t mandatoryArgsCount = 0;
    size_t optionalArgsCount  = 0;
    for (auto & arg : mArgs)
    {
        if (arg.isOptional())
        {
            optionalArgsCount++;
        }
        else
        {
            mandatoryArgsCount++;
            argvExtraArgsCount--;
        }
    }

    VerifyOrExit((size_t)(argc) >= mandatoryArgsCount && (argvExtraArgsCount == 0 || (argvExtraArgsCount && optionalArgsCount)),
                 ChipLogError(chipTool, "InitArgs: Wrong arguments number: %d instead of %u", argc,
                              static_cast<unsigned int>(mandatoryArgsCount)));

    // Initialize mandatory arguments
    for (size_t i = 0; i < mandatoryArgsCount; i++)
    {
        char * arg = argv[i];
        if (!InitArgument(i, arg))
        {
            ExitNow();
        }
    }

    // Initialize optional arguments
    // Optional arguments expect a name and a value, so i is increased by 2 on every step.
    for (size_t i = mandatoryArgsCount; i < (size_t) argc; i += 2)
    {
        bool found = false;
        for (size_t j = mandatoryArgsCount; j < mandatoryArgsCount + optionalArgsCount; j++)
        {
            // optional arguments starts with kOptionalArgumentPrefix
            if (strlen(argv[i]) <= kOptionalArgumentPrefixLength &&
                strncmp(argv[i], kOptionalArgumentPrefix, kOptionalArgumentPrefixLength) != 0)
            {
                continue;
            }

            if (strcmp(argv[i] + strlen(kOptionalArgumentPrefix), mArgs[j].name) == 0)
            {
                found = true;

                VerifyOrExit((size_t) argc > (i + 1),
                             ChipLogError(chipTool, "InitArgs: Optional argument %s missing value.", argv[i]));
                if (!InitArgument(j, argv[i + 1]))
                {
                    ExitNow();
                }
            }
        }
        VerifyOrExit(found, ChipLogError(chipTool, "InitArgs: Optional argument %s does not exist.", argv[i]));
    }

    isValidCommand = true;

exit:
    return isValidCommand;
}

static bool ParseAddressWithInterface(const char * addressString, Command::AddressWithInterface * address)
{
    struct addrinfo hints;
    struct addrinfo * result;
    int ret;

    memset(&hints, 0, sizeof(hints));
    hints.ai_family   = AF_UNSPEC;
    hints.ai_socktype = SOCK_DGRAM;
    ret               = getaddrinfo(addressString, nullptr, &hints, &result);
    if (ret < 0)
    {
        ChipLogError(chipTool, "Invalid address: %s", addressString);
        return false;
    }

    if (result->ai_family == AF_INET6)
    {
        struct sockaddr_in6 * addr = reinterpret_cast<struct sockaddr_in6 *>(result->ai_addr);
        address->address           = ::chip::Inet::IPAddress::FromSockAddr(*addr);
        address->interfaceId       = ::chip::Inet::InterfaceId(addr->sin6_scope_id);
    }
#if INET_CONFIG_ENABLE_IPV4
    else if (result->ai_family == AF_INET)
    {
        address->address     = ::chip::Inet::IPAddress::FromSockAddr(*reinterpret_cast<struct sockaddr_in *>(result->ai_addr));
        address->interfaceId = chip::Inet::InterfaceId::Null();
    }
#endif // INET_CONFIG_ENABLE_IPV4
    else
    {
        ChipLogError(chipTool, "Unsupported address: %s", addressString);
        return false;
    }

    return true;
}

// The callback should return whether the argument is valid, for the non-null
// case.  It can't directly write to isValidArgument (by closing over it)
// because in the nullable-and-null case we need to do that from this function,
// via the return value.
template <typename T>
bool HandleNullableOptional(Argument & arg, char * argValue, std::function<bool(T * value)> callback)
{
    if (arg.isOptional())
    {
        if (arg.isNullable())
        {
            arg.value = &(reinterpret_cast<chip::Optional<chip::app::DataModel::Nullable<T>> *>(arg.value)->Emplace());
        }
        else
        {
            arg.value = &(reinterpret_cast<chip::Optional<T> *>(arg.value)->Emplace());
        }
    }

    if (arg.isNullable())
    {
        auto * nullable = reinterpret_cast<chip::app::DataModel::Nullable<T> *>(arg.value);
        if (strcmp(argValue, "null") == 0)
        {
            nullable->SetNull();
            return true;
        }

        arg.value = &(nullable->SetNonNull());
    }

    return callback(reinterpret_cast<T *>(arg.value));
}

bool Command::InitArgument(size_t argIndex, char * argValue)
{
    bool isValidArgument = false;
    bool isHexNotation   = strncmp(argValue, "0x", 2) == 0 || strncmp(argValue, "0X", 2) == 0;

    Argument arg = mArgs.at(argIndex);

    // We have two places where we handle uint8_t-typed args (actual int8u and
    // bool args), so declare the handler function here so it can be reused.
    auto uint8Handler = [&](uint8_t * value) {
        // stringstream treats uint8_t as char, which is not what we want here.
        uint16_t tmpValue;
        std::stringstream ss;
        isHexNotation ? (ss << std::hex << argValue) : (ss << argValue);
        ss >> tmpValue;
        if (chip::CanCastTo<uint8_t>(tmpValue))
        {
            *value = static_cast<uint8_t>(tmpValue);

            uint64_t min = chip::CanCastTo<uint64_t>(arg.min) ? static_cast<uint64_t>(arg.min) : 0;
            uint64_t max = arg.max;
            return (!ss.fail() && ss.eof() && *value >= min && *value <= max);
        }

        return false;
    };

    switch (arg.type)
    {
    case ArgumentType::Complex: {
        auto complexArgument = static_cast<ComplexArgument *>(arg.value);
        return CHIP_NO_ERROR == complexArgument->Parse(arg.name, argValue);
    }

    case ArgumentType::Custom: {
        auto customArgument = static_cast<CustomArgument *>(arg.value);
        return CHIP_NO_ERROR == customArgument->Parse(arg.name, argValue);
    }

    case ArgumentType::VectorBool: {
        // Currently only chip::Optional<std::vector<bool>> is supported.
        if (arg.flags != Argument::kOptional)
        {
            return false;
        }

        std::vector<bool> vectorArgument;
        std::stringstream ss(argValue);
        while (ss.good())
        {
            std::string valueAsString;
            getline(ss, valueAsString, ',');

            if (strcasecmp(valueAsString.c_str(), "true") == 0)
            {
                vectorArgument.push_back(true);
            }
            else if (strcasecmp(valueAsString.c_str(), "false") == 0)
            {
                vectorArgument.push_back(false);
            }
            else
            {
                return false;
            }
        }

        auto optionalArgument = static_cast<chip::Optional<std::vector<bool>> *>(arg.value);
        optionalArgument->SetValue(vectorArgument);
        return true;
    }

    case ArgumentType::Vector16:
    case ArgumentType::Vector32: {
        std::vector<uint64_t> values;
        uint64_t min = chip::CanCastTo<uint64_t>(arg.min) ? static_cast<uint64_t>(arg.min) : 0;
        uint64_t max = arg.max;

        std::stringstream ss(argValue);
        while (ss.good())
        {
            std::string valueAsString;
            getline(ss, valueAsString, ',');
            isHexNotation = strncmp(valueAsString.c_str(), "0x", 2) == 0 || strncmp(valueAsString.c_str(), "0X", 2) == 0;

            std::stringstream subss;
            isHexNotation ? subss << std::hex << valueAsString : subss << valueAsString;

            uint64_t value;
            subss >> value;
            VerifyOrReturnError(!subss.fail() && subss.eof() && value >= min && value <= max, false);
            values.push_back(value);
        }

        if (arg.type == ArgumentType::Vector16)
        {
            auto vectorArgument = static_cast<std::vector<uint16_t> *>(arg.value);
            for (uint64_t v : values)
            {
                vectorArgument->push_back(static_cast<uint16_t>(v));
            }
        }
        else if (arg.type == ArgumentType::Vector32 && arg.flags != Argument::kOptional)
        {
            auto vectorArgument = static_cast<std::vector<uint32_t> *>(arg.value);
            for (uint64_t v : values)
            {
                vectorArgument->push_back(static_cast<uint32_t>(v));
            }
        }
        else if (arg.type == ArgumentType::Vector32 && arg.flags == Argument::kOptional)
        {
            std::vector<uint32_t> vectorArgument;
            for (uint64_t v : values)
            {
                vectorArgument.push_back(static_cast<uint32_t>(v));
            }

            auto optionalArgument = static_cast<chip::Optional<std::vector<uint32_t>> *>(arg.value);
            optionalArgument->SetValue(vectorArgument);
        }
        else
        {
            return false;
        }

        return true;
    }

    case ArgumentType::VectorCustom: {
        auto vectorArgument = static_cast<std::vector<CustomArgument *> *>(arg.value);

        std::stringstream ss(argValue);
        while (ss.good())
        {
            std::string valueAsString;
            // By default the parameter separator is ";" in order to not collapse with the argument itself if it contains commas
            // (e.g a struct argument with multiple fields). In case one needs to use ";" it can be overriden with the following
            // environment variable.
            constexpr const char * kSeparatorVariable = "CHIPTOOL_CUSTOM_ARGUMENTS_SEPARATOR";
            getline(ss, valueAsString, getenv(kSeparatorVariable) ? getenv(kSeparatorVariable)[0] : ';');

            CustomArgument * customArgument = new CustomArgument();
            vectorArgument->push_back(customArgument);
            VerifyOrReturnError(CHIP_NO_ERROR == vectorArgument->back()->Parse(arg.name, valueAsString.c_str()), false);
        }

        return true;
    }

    case ArgumentType::Attribute: {
        if (arg.isOptional() || arg.isNullable())
        {
            isValidArgument = false;
        }
        else
        {
            char * value    = reinterpret_cast<char *>(arg.value);
            isValidArgument = (strcmp(argValue, value) == 0);
        }
        break;
    }

    case ArgumentType::String: {
        isValidArgument = HandleNullableOptional<char *>(arg, argValue, [&](auto * value) {
            *value = argValue;
            return true;
        });
        break;
    }

    case ArgumentType::CharString: {
        isValidArgument = HandleNullableOptional<chip::CharSpan>(arg, argValue, [&](auto * value) {
            *value = chip::Span<const char>(argValue, strlen(argValue));
            return true;
        });
        break;
    }

    case ArgumentType::OctetString: {
        isValidArgument = HandleNullableOptional<chip::ByteSpan>(arg, argValue, [&](auto * value) {
            // We support two ways to pass an octet string argument.  If it happens
            // to be all-ASCII, you can just pass it in.  Otherwise you can pass in
            // "hex:" followed by the hex-encoded bytes.
            size_t argLen = strlen(argValue);

            if (IsHexString(argValue))
            {
                // Hex-encoded.  Decode it into a temporary buffer first, so if we
                // run into errors we can do correct "argument is not valid" logging
                // that actually shows the value that was passed in.  After we
                // determine it's valid, modify the passed-in value to hold the
                // right bytes, so we don't need to worry about allocating storage
                // for this somewhere else.  This works because the hex
                // representation is always longer than the octet string it encodes,
                // so we have enough space in argValue for the decoded version.
                chip::Platform::ScopedMemoryBuffer<uint8_t> buffer;
                if (!buffer.Calloc(argLen)) // Bigger than needed, but it's fine.
                {
                    return false;
                }

                size_t octetCount =
                    chip::Encoding::HexToBytes(argValue + kHexStringPrefixLen, argLen - kHexStringPrefixLen, buffer.Get(), argLen);
                if (octetCount == 0)
                {
                    return false;
                }

                memcpy(argValue, buffer.Get(), octetCount);
                *value = chip::ByteSpan(chip::Uint8::from_char(argValue), octetCount);
                return true;
            }

            // Just ASCII.  Check for the "str:" prefix.
            if (IsStrString(argValue))
            {
                // Skip the prefix
                argValue += kStrStringPrefixLen;
                argLen -= kStrStringPrefixLen;
            }
            *value = chip::ByteSpan(chip::Uint8::from_char(argValue), argLen);
            return true;
        });
        break;
    }

    case ArgumentType::Bool: {
        isValidArgument = HandleNullableOptional<bool>(arg, argValue, [&](auto * value) {
            // Start with checking for actual boolean values.
            if (strcasecmp(argValue, "true") == 0)
            {
                *value = true;
                return true;
            }

            if (strcasecmp(argValue, "false") == 0)
            {
                *value = false;
                return true;
            }

            // For backwards compat, keep accepting 0 and 1 for now as synonyms
            // for false and true.  Since we set our min to 0 and max to 1 for
            // booleans, calling uint8Handler does the right thing in terms of
            // only allowing those two values.
            uint8_t temp = 0;
            if (!uint8Handler(&temp))
            {
                return false;
            }
            *value = (temp == 1);
            return true;
        });
        break;
    }

    case ArgumentType::Number_uint8: {
        isValidArgument = HandleNullableOptional<uint8_t>(arg, argValue, uint8Handler);
        break;
    }

    case ArgumentType::Number_uint16: {
        isValidArgument = HandleNullableOptional<uint16_t>(arg, argValue, [&](auto * value) {
            std::stringstream ss;
            isHexNotation ? ss << std::hex << argValue : ss << argValue;
            ss >> *value;

            uint64_t min = chip::CanCastTo<uint64_t>(arg.min) ? static_cast<uint64_t>(arg.min) : 0;
            uint64_t max = arg.max;
            return (!ss.fail() && ss.eof() && *value >= min && *value <= max);
        });
        break;
    }

    case ArgumentType::Number_uint32: {
        isValidArgument = HandleNullableOptional<uint32_t>(arg, argValue, [&](auto * value) {
            std::stringstream ss;
            isHexNotation ? ss << std::hex << argValue : ss << argValue;
            ss >> *value;

            uint64_t min = chip::CanCastTo<uint64_t>(arg.min) ? static_cast<uint64_t>(arg.min) : 0;
            uint64_t max = arg.max;
            return (!ss.fail() && ss.eof() && *value >= min && *value <= max);
        });
        break;
    }

    case ArgumentType::Number_uint64: {
        isValidArgument = HandleNullableOptional<uint64_t>(arg, argValue, [&](auto * value) {
            std::stringstream ss;
            isHexNotation ? ss << std::hex << argValue : ss << argValue;
            ss >> *value;

            uint64_t min = chip::CanCastTo<uint64_t>(arg.min) ? static_cast<uint64_t>(arg.min) : 0;
            uint64_t max = arg.max;
            return (!ss.fail() && ss.eof() && *value >= min && *value <= max);
        });
        break;
    }

    case ArgumentType::Number_int8: {
        isValidArgument = HandleNullableOptional<int8_t>(arg, argValue, [&](auto * value) {
            // stringstream treats int8_t as char, which is not what we want here.
            int16_t tmpValue;
            std::stringstream ss;
            isHexNotation ? ss << std::hex << argValue : ss << argValue;
            ss >> tmpValue;
            if (chip::CanCastTo<int8_t>(tmpValue))
            {
                *value = static_cast<int8_t>(tmpValue);

                int64_t min = arg.min;
                int64_t max = chip::CanCastTo<int64_t>(arg.max) ? static_cast<int64_t>(arg.max) : INT64_MAX;
                return (!ss.fail() && ss.eof() && *value >= min && *value <= max);
            }

            return false;
        });
        break;
    }

    case ArgumentType::Number_int16: {
        isValidArgument = HandleNullableOptional<int16_t>(arg, argValue, [&](auto * value) {
            std::stringstream ss;
            isHexNotation ? ss << std::hex << argValue : ss << argValue;
            ss >> *value;

            int64_t min = arg.min;
            int64_t max = chip::CanCastTo<int64_t>(arg.max) ? static_cast<int64_t>(arg.max) : INT64_MAX;
            return (!ss.fail() && ss.eof() && *value >= min && *value <= max);
        });
        break;
    }

    case ArgumentType::Number_int32: {
        isValidArgument = HandleNullableOptional<int32_t>(arg, argValue, [&](auto * value) {
            std::stringstream ss;
            isHexNotation ? ss << std::hex << argValue : ss << argValue;
            ss >> *value;

            int64_t min = arg.min;
            int64_t max = chip::CanCastTo<int64_t>(arg.max) ? static_cast<int64_t>(arg.max) : INT64_MAX;
            return (!ss.fail() && ss.eof() && *value >= min && *value <= max);
        });
        break;
    }

    case ArgumentType::Number_int64: {
        isValidArgument = HandleNullableOptional<int64_t>(arg, argValue, [&](auto * value) {
            std::stringstream ss;
            isHexNotation ? ss << std::hex << argValue : ss << argValue;
            ss >> *value;

            int64_t min = arg.min;
            int64_t max = chip::CanCastTo<int64_t>(arg.max) ? static_cast<int64_t>(arg.max) : INT64_MAX;
            return (!ss.fail() && ss.eof() && *value >= min && *value <= max);
        });
        break;
    }

    case ArgumentType::Float: {
        isValidArgument = HandleNullableOptional<float>(arg, argValue, [&](auto * value) {
            if (strcmp(argValue, "Infinity") == 0)
            {
                *value = INFINITY;
                return true;
            }

            if (strcmp(argValue, "-Infinity") == 0)
            {
                *value = -INFINITY;
                return true;
            }

            std::stringstream ss;
            ss << argValue;
            ss >> *value;
            return (!ss.fail() && ss.eof());
        });
        break;
    }

    case ArgumentType::Double: {
        isValidArgument = HandleNullableOptional<double>(arg, argValue, [&](auto * value) {
            if (strcmp(argValue, "Infinity") == 0)
            {
                *value = INFINITY;
                return true;
            }

            if (strcmp(argValue, "-Infinity") == 0)
            {
                *value = -INFINITY;
                return true;
            }

            std::stringstream ss;
            ss << argValue;
            ss >> *value;
            return (!ss.fail() && ss.eof());
        });
        break;
    }

    case ArgumentType::Address: {
        isValidArgument = HandleNullableOptional<AddressWithInterface>(
            arg, argValue, [&](auto * value) { return ParseAddressWithInterface(argValue, value); });
        break;
    }
    }

    if (!isValidArgument)
    {
        ChipLogError(chipTool, "InitArgs: Invalid argument %s: %s", arg.name, argValue);
    }

    return isValidArgument;
}

size_t Command::AddArgument(const char * name, const char * value, const char * desc, uint8_t flags)
{
    Argument arg;
    arg.type  = ArgumentType::Attribute;
    arg.name  = name;
    arg.value = const_cast<void *>(reinterpret_cast<const void *>(value));
    arg.flags = flags;
    arg.desc  = desc;

    return AddArgumentToList(std::move(arg));
}

size_t Command::AddArgument(const char * name, char ** value, const char * desc, uint8_t flags)
{
    Argument arg;
    arg.type  = ArgumentType::String;
    arg.name  = name;
    arg.value = reinterpret_cast<void *>(value);
    arg.flags = flags;
    arg.desc  = desc;

    return AddArgumentToList(std::move(arg));
}

size_t Command::AddArgument(const char * name, chip::CharSpan * value, const char * desc, uint8_t flags)
{
    Argument arg;
    arg.type  = ArgumentType::CharString;
    arg.name  = name;
    arg.value = reinterpret_cast<void *>(value);
    arg.flags = flags;
    arg.desc  = desc;

    return AddArgumentToList(std::move(arg));
}

size_t Command::AddArgument(const char * name, chip::ByteSpan * value, const char * desc, uint8_t flags)
{
    Argument arg;
    arg.type  = ArgumentType::OctetString;
    arg.name  = name;
    arg.value = reinterpret_cast<void *>(value);
    arg.flags = flags;
    arg.desc  = desc;

    return AddArgumentToList(std::move(arg));
}

size_t Command::AddArgument(const char * name, AddressWithInterface * out, const char * desc, uint8_t flags)
{
    Argument arg;
    arg.type  = ArgumentType::Address;
    arg.name  = name;
    arg.value = reinterpret_cast<void *>(out);
    arg.flags = flags;
    arg.desc  = desc;

    return AddArgumentToList(std::move(arg));
}

size_t Command::AddArgument(const char * name, int64_t min, uint64_t max, std::vector<uint16_t> * value, const char * desc)
{
    Argument arg;
    arg.type  = ArgumentType::Vector16;
    arg.name  = name;
    arg.value = static_cast<void *>(value);
    arg.min   = min;
    arg.max   = max;
    arg.flags = 0;
    arg.desc  = desc;

    return AddArgumentToList(std::move(arg));
}

size_t Command::AddArgument(const char * name, int64_t min, uint64_t max, std::vector<uint32_t> * value, const char * desc)
{
    Argument arg;
    arg.type  = ArgumentType::Vector32;
    arg.name  = name;
    arg.value = static_cast<void *>(value);
    arg.min   = min;
    arg.max   = max;
    arg.flags = 0;
    arg.desc  = desc;

    return AddArgumentToList(std::move(arg));
}

size_t Command::AddArgument(const char * name, int64_t min, uint64_t max, chip::Optional<std::vector<uint32_t>> * value,
                            const char * desc)
{
    Argument arg;
    arg.type  = ArgumentType::Vector32;
    arg.name  = name;
    arg.value = static_cast<void *>(value);
    arg.min   = min;
    arg.max   = max;
    arg.flags = Argument::kOptional;
    arg.desc  = desc;

    return AddArgumentToList(std::move(arg));
}

size_t Command::AddArgument(const char * name, int64_t min, uint64_t max, chip::Optional<std::vector<bool>> * value,
                            const char * desc)
{
    Argument arg;
    arg.type  = ArgumentType::VectorBool;
    arg.name  = name;
    arg.value = static_cast<void *>(value);
    arg.min   = min;
    arg.max   = max;
    arg.flags = Argument::kOptional;
    arg.desc  = desc;

    return AddArgumentToList(std::move(arg));
}

size_t Command::AddArgument(const char * name, ComplexArgument * value, const char * desc)
{
    Argument arg;
    arg.type  = ArgumentType::Complex;
    arg.name  = name;
    arg.value = static_cast<void *>(value);
    arg.flags = 0;
    arg.desc  = desc;

    return AddArgumentToList(std::move(arg));
}

size_t Command::AddArgument(const char * name, CustomArgument * value, const char * desc)
{
    Argument arg;
    arg.type  = ArgumentType::Custom;
    arg.name  = name;
    arg.value = const_cast<void *>(reinterpret_cast<const void *>(value));
    arg.flags = 0;
    arg.desc  = desc;

    return AddArgumentToList(std::move(arg));
}

size_t Command::AddArgument(const char * name, std::vector<CustomArgument *> * value, const char * desc)
{
    Argument arg;
    arg.type  = ArgumentType::VectorCustom;
    arg.name  = name;
    arg.value = static_cast<void *>(value);
    arg.flags = 0;
    arg.desc  = desc;

    return AddArgumentToList(std::move(arg));
}

size_t Command::AddArgument(const char * name, float min, float max, float * out, const char * desc, uint8_t flags)
{
    Argument arg;
    arg.type  = ArgumentType::Float;
    arg.name  = name;
    arg.value = reinterpret_cast<void *>(out);
    arg.flags = flags;
    arg.desc  = desc;
    // Ignore min/max for now; they're always +-Infinity anyway.

    return AddArgumentToList(std::move(arg));
}

size_t Command::AddArgument(const char * name, double min, double max, double * out, const char * desc, uint8_t flags)
{
    Argument arg;
    arg.type  = ArgumentType::Double;
    arg.name  = name;
    arg.value = reinterpret_cast<void *>(out);
    arg.flags = flags;
    arg.desc  = desc;
    // Ignore min/max for now; they're always +-Infinity anyway.

    return AddArgumentToList(std::move(arg));
}

size_t Command::AddArgument(const char * name, int64_t min, uint64_t max, void * out, ArgumentType type, const char * desc,
                            uint8_t flags)
{
    Argument arg;
    arg.type  = type;
    arg.name  = name;
    arg.value = out;
    arg.min   = min;
    arg.max   = max;
    arg.flags = flags;
    arg.desc  = desc;

    return AddArgumentToList(std::move(arg));
}

size_t Command::AddArgument(const char * name, int64_t min, uint64_t max, void * out, const char * desc, uint8_t flags)
{
    Argument arg;
    arg.type  = ArgumentType::Number_uint8;
    arg.name  = name;
    arg.value = out;
    arg.min   = min;
    arg.max   = max;
    arg.flags = flags;
    arg.desc  = desc;

    return AddArgumentToList(std::move(arg));
}

const char * Command::GetArgumentName(size_t index) const
{
    if (index < mArgs.size())
    {
        return mArgs.at(index).name;
    }

    return nullptr;
}

const char * Command::GetArgumentDescription(size_t index) const
{
    if (index < mArgs.size())
    {
        return mArgs.at(index).desc;
    }

    return nullptr;
}

const char * Command::GetAttribute() const
{
    size_t argsCount = mArgs.size();
    for (size_t i = 0; i < argsCount; i++)
    {
        Argument arg = mArgs.at(i);
        if (arg.type == ArgumentType::Attribute)
        {
            return reinterpret_cast<const char *>(arg.value);
        }
    }

    return nullptr;
}

const char * Command::GetEvent() const
{
    size_t argsCount = mArgs.size();
    for (size_t i = 0; i < argsCount; i++)
    {
        Argument arg = mArgs.at(i);
        if (arg.type == ArgumentType::Attribute)
        {
            return reinterpret_cast<const char *>(arg.value);
        }
    }

    return nullptr;
}

size_t Command::AddArgumentToList(Argument && argument)
{
    if (argument.isOptional() || mArgs.empty() || !mArgs.back().isOptional())
    {
        // Safe to just append.
        mArgs.emplace_back(std::move(argument));
        return mArgs.size();
    }

    // We're inserting a non-optional arg but we already have something optional
    // in the list.  Insert before the first optional arg.
    for (auto cur = mArgs.cbegin(), end = mArgs.cend(); cur != end; ++cur)
    {
        if ((*cur).isOptional())
        {
            mArgs.emplace(cur, std::move(argument));
            return mArgs.size();
        }
    }

    // Never reached.
    VerifyOrDie(false);
    return 0;
}

namespace {
template <typename T>
void ResetOptionalArg(const Argument & arg)
{
    VerifyOrDie(arg.isOptional());

    if (arg.isNullable())
    {
        reinterpret_cast<chip::Optional<chip::app::DataModel::Nullable<T>> *>(arg.value)->ClearValue();
    }
    else
    {
        reinterpret_cast<chip::Optional<T> *>(arg.value)->ClearValue();
    }
}
} // anonymous namespace

void Command::ResetArguments()
{
    for (const auto & arg : mArgs)
    {
        const ArgumentType type = arg.type;
        if (arg.isOptional())
        {
            // Must always clean these up so they don't carry over to the next
            // command invocation in interactive mode.
            switch (type)
            {
            case ArgumentType::Complex: {
                // No optional complex arguments so far.
                VerifyOrDie(false);
                break;
            }
            case ArgumentType::Custom: {
                // No optional custom arguments so far.
                VerifyOrDie(false);
                break;
            }
            case ArgumentType::VectorBool: {
                ResetOptionalArg<std::vector<bool>>(arg);
                break;
            }
            case ArgumentType::Vector16: {
                // No optional Vector16 arguments so far.
                VerifyOrDie(false);
                break;
            }
            case ArgumentType::Vector32: {
                ResetOptionalArg<std::vector<uint32_t>>(arg);
                break;
            }
            case ArgumentType::VectorCustom: {
                // No optional VectorCustom arguments so far.
                VerifyOrDie(false);
                break;
            }
            case ArgumentType::Attribute: {
                // No optional Attribute arguments so far.
                VerifyOrDie(false);
                break;
            }
            case ArgumentType::String: {
                ResetOptionalArg<char *>(arg);
                break;
            }
            case ArgumentType::CharString: {
                ResetOptionalArg<chip::CharSpan>(arg);
                break;
            }
            case ArgumentType::OctetString: {
                ResetOptionalArg<chip::ByteSpan>(arg);
                break;
            }
            case ArgumentType::Bool: {
                ResetOptionalArg<bool>(arg);
                break;
            }
            case ArgumentType::Number_uint8: {
                ResetOptionalArg<uint8_t>(arg);
                break;
            }
            case ArgumentType::Number_uint16: {
                ResetOptionalArg<uint16_t>(arg);
                break;
            }
            case ArgumentType::Number_uint32: {
                ResetOptionalArg<uint32_t>(arg);
                break;
            }
            case ArgumentType::Number_uint64: {
                ResetOptionalArg<uint64_t>(arg);
                break;
            }
            case ArgumentType::Number_int8: {
                ResetOptionalArg<int8_t>(arg);
                break;
            }
            case ArgumentType::Number_int16: {
                ResetOptionalArg<int16_t>(arg);
                break;
            }
            case ArgumentType::Number_int32: {
                ResetOptionalArg<int32_t>(arg);
                break;
            }
            case ArgumentType::Number_int64: {
                ResetOptionalArg<int64_t>(arg);
                break;
            }
            case ArgumentType::Float: {
                ResetOptionalArg<float>(arg);
                break;
            }
            case ArgumentType::Double: {
                ResetOptionalArg<double>(arg);
                break;
            }
            case ArgumentType::Address: {
                ResetOptionalArg<AddressWithInterface>(arg);
                break;
            }
            }
        }
        else
        {
            // Some non-optional arguments have state that needs to be cleaned
            // up too.
            if (type == ArgumentType::Vector16)
            {
                auto vectorArgument = static_cast<std::vector<uint16_t> *>(arg.value);
                vectorArgument->clear();
            }
            else if (type == ArgumentType::Vector32)
            {
                auto vectorArgument = static_cast<std::vector<uint32_t> *>(arg.value);
                vectorArgument->clear();
            }
            else if (type == ArgumentType::VectorCustom)
            {
                auto vectorArgument = static_cast<std::vector<CustomArgument *> *>(arg.value);
                for (auto & customArgument : *vectorArgument)
                {
                    delete customArgument;
                }
                vectorArgument->clear();
            }
        }
    }
}
