/*
 *  Copyright (c) 2023, The OpenThread Authors.
 *  All rights reserved.
 *
 *  Redistribution and use in source and binary forms, with or without
 *  modification, are permitted provided that the following conditions are met:
 *  1. Redistributions of source code must retain the above copyright
 *     notice, this list of conditions and the following disclaimer.
 *  2. Redistributions in binary form must reproduce the above copyright
 *     notice, this list of conditions and the following disclaimer in the
 *     documentation and/or other materials provided with the distribution.
 *  3. Neither the name of the copyright holder nor the
 *     names of its contributors may be used to endorse or promote products
 *     derived from this software without specific prior written permission.
 *
 *  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
 *  AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
 *  IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
 *  ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
 *  LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
 *  CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
 *  SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
 *  INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
 *  CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
 *  ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
 *  POSSIBILITY OF SUCH DAMAGE.
 */

/**
 * @file
 *   This file implements CLI for Border Router.
 */

#include "cli_br.hpp"

#if OPENTHREAD_CONFIG_BORDER_ROUTING_ENABLE

#include <string.h>

#include <openthread/border_routing.h>

#include "cli/cli.hpp"

namespace ot {
namespace Cli {

/**
 * @cli br init
 * @code
 * br init 2 1
 * Done
 * @endcode
 * @cparam br init @ca{infrastructure-network-index} @ca{is-running}
 * @par
 * Initializes the Border Routing Manager.
 * @sa otBorderRoutingInit
 */
template <> otError Br::Process<Cmd("init")>(Arg aArgs[])
{
    otError  error = OT_ERROR_NONE;
    uint32_t ifIndex;
    bool     isRunning;

    SuccessOrExit(error = aArgs[0].ParseAsUint32(ifIndex));
    SuccessOrExit(error = aArgs[1].ParseAsBool(isRunning));
    VerifyOrExit(aArgs[2].IsEmpty(), error = OT_ERROR_INVALID_ARGS);
    error = otBorderRoutingInit(GetInstancePtr(), ifIndex, isRunning);

exit:
    return error;
}

/**
 * @cli br enable
 * @code
 * br enable
 * Done
 * @endcode
 * @par
 * Enables the Border Routing Manager.
 * @sa otBorderRoutingSetEnabled
 */
template <> otError Br::Process<Cmd("enable")>(Arg aArgs[])
{
    otError error = OT_ERROR_NONE;

    VerifyOrExit(aArgs[0].IsEmpty(), error = OT_ERROR_INVALID_ARGS);
    error = otBorderRoutingSetEnabled(GetInstancePtr(), true);

exit:
    return error;
}

/**
 * @cli br disable
 * @code
 * br disable
 * Done
 * @endcode
 * @par
 * Disables the Border Routing Manager.
 * @sa otBorderRoutingSetEnabled
 */
template <> otError Br::Process<Cmd("disable")>(Arg aArgs[])
{
    otError error = OT_ERROR_NONE;

    VerifyOrExit(aArgs[0].IsEmpty(), error = OT_ERROR_INVALID_ARGS);
    error = otBorderRoutingSetEnabled(GetInstancePtr(), false);

exit:
    return error;
}

/**
 * @cli br state
 * @code
 * br state
 * running
 * @endcode
 * @par api_copy
 * #otBorderRoutingGetState
 */
template <> otError Br::Process<Cmd("state")>(Arg aArgs[])
{
    static const char *const kStateStrings[] = {

        "uninitialized", // (0) OT_BORDER_ROUTING_STATE_UNINITIALIZED
        "disabled",      // (1) OT_BORDER_ROUTING_STATE_DISABLED
        "stopped",       // (2) OT_BORDER_ROUTING_STATE_STOPPED
        "running",       // (3) OT_BORDER_ROUTING_STATE_RUNNING
    };

    otError error = OT_ERROR_NONE;

    static_assert(0 == OT_BORDER_ROUTING_STATE_UNINITIALIZED, "STATE_UNINITIALIZED value is incorrect");
    static_assert(1 == OT_BORDER_ROUTING_STATE_DISABLED, "STATE_DISABLED value is incorrect");
    static_assert(2 == OT_BORDER_ROUTING_STATE_STOPPED, "STATE_STOPPED value is incorrect");
    static_assert(3 == OT_BORDER_ROUTING_STATE_RUNNING, "STATE_RUNNING value is incorrect");

    VerifyOrExit(aArgs[0].IsEmpty(), error = OT_ERROR_INVALID_ARGS);
    OutputLine("%s", Stringify(otBorderRoutingGetState(GetInstancePtr()), kStateStrings));

exit:
    return error;
}

otError Br::ParsePrefixTypeArgs(Arg aArgs[], PrefixType &aFlags)
{
    otError error = OT_ERROR_NONE;

    aFlags = 0;

    if (aArgs[0].IsEmpty())
    {
        aFlags = kPrefixTypeFavored | kPrefixTypeLocal;
        ExitNow();
    }

    if (aArgs[0] == "local")
    {
        aFlags = kPrefixTypeLocal;
    }
    else if (aArgs[0] == "favored")
    {
        aFlags = kPrefixTypeFavored;
    }
    else
    {
        ExitNow(error = OT_ERROR_INVALID_ARGS);
    }

    VerifyOrExit(aArgs[1].IsEmpty(), error = OT_ERROR_INVALID_ARGS);

exit:
    return error;
}

/**
 * @cli br omrprefix
 * @code
 * br omrprefix
 * Local: fdfc:1ff5:1512:5622::/64
 * Favored: fdfc:1ff5:1512:5622::/64 prf:low
 * Done
 * @endcode
 * @par
 * Outputs both local and favored OMR prefix.
 * @sa otBorderRoutingGetOmrPrefix
 * @sa otBorderRoutingGetFavoredOmrPrefix
 */
template <> otError Br::Process<Cmd("omrprefix")>(Arg aArgs[])
{
    otError    error = OT_ERROR_NONE;
    PrefixType outputPrefixTypes;

    SuccessOrExit(error = ParsePrefixTypeArgs(aArgs, outputPrefixTypes));

    /**
     * @cli br omrprefix local
     * @code
     * br omrprefix local
     * fdfc:1ff5:1512:5622::/64
     * Done
     * @endcode
     * @par api_copy
     * #otBorderRoutingGetOmrPrefix
     */
    if (outputPrefixTypes & kPrefixTypeLocal)
    {
        otIp6Prefix local;

        SuccessOrExit(error = otBorderRoutingGetOmrPrefix(GetInstancePtr(), &local));

        OutputFormat("%s", outputPrefixTypes == kPrefixTypeLocal ? "" : "Local: ");
        OutputIp6PrefixLine(local);
    }

    /**
     * @cli br omrprefix favored
     * @code
     * br omrprefix favored
     * fdfc:1ff5:1512:5622::/64 prf:low
     * Done
     * @endcode
     * @par api_copy
     * #otBorderRoutingGetFavoredOmrPrefix
     */
    if (outputPrefixTypes & kPrefixTypeFavored)
    {
        otIp6Prefix       favored;
        otRoutePreference preference;

        SuccessOrExit(error = otBorderRoutingGetFavoredOmrPrefix(GetInstancePtr(), &favored, &preference));

        OutputFormat("%s", outputPrefixTypes == kPrefixTypeFavored ? "" : "Favored: ");
        OutputIp6Prefix(favored);
        OutputLine(" prf:%s", Interpreter::PreferenceToString(preference));
    }

exit:
    return error;
}

/**
 * @cli br onlinkprefix
 * @code
 * br onlinkprefix
 * Local: fd41:2650:a6f5:0::/64
 * Favored: 2600::0:1234:da12::/64
 * Done
 * @endcode
 * @par
 * Outputs both local and favored on-link prefixes.
 * @sa otBorderRoutingGetOnLinkPrefix
 * @sa otBorderRoutingGetFavoredOnLinkPrefix
 */
template <> otError Br::Process<Cmd("onlinkprefix")>(Arg aArgs[])
{
    otError    error = OT_ERROR_NONE;
    PrefixType outputPrefixTypes;

    SuccessOrExit(error = ParsePrefixTypeArgs(aArgs, outputPrefixTypes));

    /**
     * @cli br onlinkprefix local
     * @code
     * br onlinkprefix local
     * fd41:2650:a6f5:0::/64
     * Done
     * @endcode
     * @par api_copy
     * #otBorderRoutingGetOnLinkPrefix
     */
    if (outputPrefixTypes & kPrefixTypeLocal)
    {
        otIp6Prefix local;

        SuccessOrExit(error = otBorderRoutingGetOnLinkPrefix(GetInstancePtr(), &local));

        OutputFormat("%s", outputPrefixTypes == kPrefixTypeLocal ? "" : "Local: ");
        OutputIp6PrefixLine(local);
    }

    /**
     * @cli br onlinkprefix favored
     * @code
     * br onlinkprefix favored
     * 2600::0:1234:da12::/64
     * Done
     * @endcode
     * @par api_copy
     * #otBorderRoutingGetFavoredOnLinkPrefix
     */
    if (outputPrefixTypes & kPrefixTypeFavored)
    {
        otIp6Prefix favored;

        SuccessOrExit(error = otBorderRoutingGetFavoredOnLinkPrefix(GetInstancePtr(), &favored));

        OutputFormat("%s", outputPrefixTypes == kPrefixTypeFavored ? "" : "Favored: ");
        OutputIp6PrefixLine(favored);
    }

exit:
    return error;
}

#if OPENTHREAD_CONFIG_NAT64_BORDER_ROUTING_ENABLE

/**
 * @cli br nat64prefix
 * @code
 * br nat64prefix
 * Local: fd14:1078:b3d5:b0b0:0:0::/96
 * Favored: fd14:1078:b3d5:b0b0:0:0::/96 prf:low
 * Done
 * @endcode
 * @par
 * Outputs both local and favored NAT64 prefixes.
 * @sa otBorderRoutingGetNat64Prefix
 * @sa otBorderRoutingGetFavoredNat64Prefix
 */
template <> otError Br::Process<Cmd("nat64prefix")>(Arg aArgs[])
{
    otError    error = OT_ERROR_NONE;
    PrefixType outputPrefixTypes;

    SuccessOrExit(error = ParsePrefixTypeArgs(aArgs, outputPrefixTypes));

    /**
     * @cli br nat64prefix local
     * @code
     * br nat64prefix local
     * fd14:1078:b3d5:b0b0:0:0::/96
     * Done
     * @endcode
     * @par api_copy
     * #otBorderRoutingGetNat64Prefix
     */
    if (outputPrefixTypes & kPrefixTypeLocal)
    {
        otIp6Prefix local;

        SuccessOrExit(error = otBorderRoutingGetNat64Prefix(GetInstancePtr(), &local));

        OutputFormat("%s", outputPrefixTypes == kPrefixTypeLocal ? "" : "Local: ");
        OutputIp6PrefixLine(local);
    }

    /**
     * @cli br nat64prefix favored
     * @code
     * br nat64prefix favored
     * fd14:1078:b3d5:b0b0:0:0::/96 prf:low
     * Done
     * @endcode
     * @par api_copy
     * #otBorderRoutingGetFavoredNat64Prefix
     */
    if (outputPrefixTypes & kPrefixTypeFavored)
    {
        otIp6Prefix       favored;
        otRoutePreference preference;

        SuccessOrExit(error = otBorderRoutingGetFavoredNat64Prefix(GetInstancePtr(), &favored, &preference));

        OutputFormat("%s", outputPrefixTypes == kPrefixTypeFavored ? "" : "Favored: ");
        OutputIp6Prefix(favored);
        OutputLine(" prf:%s", Interpreter::PreferenceToString(preference));
    }

exit:
    return error;
}

#endif // OPENTHREAD_CONFIG_NAT64_BORDER_ROUTING_ENABLE

/**
 * @cli br prefixtable
 * @code
 * br prefixtable
 * prefix:fd00:1234:5678:0::/64, on-link:no, ms-since-rx:29526, lifetime:1800, route-prf:med,
 * router:ff02:0:0:0:0:0:0:1
 * prefix:1200:abba:baba:0::/64, on-link:yes, ms-since-rx:29527, lifetime:1800, preferred:1800,
 * router:ff02:0:0:0:0:0:0:1
 * Done
 * @endcode
 * @par api_copy
 * #otBorderRoutingGetNextPrefixTableEntry
 */
template <> otError Br::Process<Cmd("prefixtable")>(Arg aArgs[])
{
    otError                            error = OT_ERROR_NONE;
    otBorderRoutingPrefixTableIterator iterator;
    otBorderRoutingPrefixTableEntry    entry;

    VerifyOrExit(aArgs[0].IsEmpty(), error = OT_ERROR_INVALID_ARGS);

    otBorderRoutingPrefixTableInitIterator(GetInstancePtr(), &iterator);

    while (otBorderRoutingGetNextPrefixTableEntry(GetInstancePtr(), &iterator, &entry) == OT_ERROR_NONE)
    {
        char string[OT_IP6_PREFIX_STRING_SIZE];

        otIp6PrefixToString(&entry.mPrefix, string, sizeof(string));
        OutputFormat("prefix:%s, on-link:%s, ms-since-rx:%lu, lifetime:%lu, ", string, entry.mIsOnLink ? "yes" : "no",
                     ToUlong(entry.mMsecSinceLastUpdate), ToUlong(entry.mValidLifetime));

        if (entry.mIsOnLink)
        {
            OutputFormat("preferred:%lu, ", ToUlong(entry.mPreferredLifetime));
        }
        else
        {
            OutputFormat("route-prf:%s, ", Interpreter::PreferenceToString(entry.mRoutePreference));
        }

        otIp6AddressToString(&entry.mRouterAddress, string, sizeof(string));
        OutputLine("router:%s", string);
    }

exit:
    return error;
}

template <> otError Br::Process<Cmd("rioprf")>(Arg aArgs[])
{
    otError error = OT_ERROR_NONE;

    /**
     * @cli br rioprf
     * @code
     * br rioprf
     * med
     * Done
     * @endcode
     * @par api_copy
     * #otBorderRoutingGetRouteInfoOptionPreference
     */
    if (aArgs[0].IsEmpty())
    {
        OutputLine("%s",
                   Interpreter::PreferenceToString(otBorderRoutingGetRouteInfoOptionPreference(GetInstancePtr())));
    }
    /**
     * @cli br rioprf clear
     * @code
     * br rioprf clear
     * Done
     * @endcode
     * @par api_copy
     * #otBorderRoutingClearRouteInfoOptionPreference
     */
    else if (aArgs[0] == "clear")
    {
        otBorderRoutingClearRouteInfoOptionPreference(GetInstancePtr());
    }
    /**
     * @cli br rioprf (high,med,low)
     * @code
     * br rioprf low
     * Done
     * @endcode
     * @cparam br rioprf [@ca{high}|@ca{med}|@ca{low}]
     * @par api_copy
     * #otBorderRoutingSetRouteInfoOptionPreference
     */
    else
    {
        otRoutePreference preference;

        SuccessOrExit(error = Interpreter::ParsePreference(aArgs[0], preference));
        otBorderRoutingSetRouteInfoOptionPreference(GetInstancePtr(), preference);
    }

exit:
    return error;
}

template <> otError Br::Process<Cmd("routeprf")>(Arg aArgs[])
{
    otError error = OT_ERROR_NONE;

    /**
     * @cli br routeprf
     * @code
     * br routeprf
     * med
     * Done
     * @endcode
     * @par api_copy
     * #otBorderRoutingGetRoutePreference
     */
    if (aArgs[0].IsEmpty())
    {
        OutputLine("%s", Interpreter::PreferenceToString(otBorderRoutingGetRoutePreference(GetInstancePtr())));
    }
    /**
     * @cli br routeprf clear
     * @code
     * br routeprf clear
     * Done
     * @endcode
     * @par api_copy
     * #otBorderRoutingClearRoutePreference
     */
    else if (aArgs[0] == "clear")
    {
        otBorderRoutingClearRoutePreference(GetInstancePtr());
    }
    /**
     * @cli br routeprf (high,med,low)
     * @code
     * br routeprf low
     * Done
     * @endcode
     * @cparam br routeprf [@ca{high}|@ca{med}|@ca{low}]
     * @par api_copy
     * #otBorderRoutingSetRoutePreference
     */
    else
    {
        otRoutePreference preference;

        SuccessOrExit(error = Interpreter::ParsePreference(aArgs[0], preference));
        otBorderRoutingSetRoutePreference(GetInstancePtr(), preference);
    }

exit:
    return error;
}

#if OPENTHREAD_CONFIG_IP6_BR_COUNTERS_ENABLE

/**
 * @cli br counters
 * @code
 * br counters
 * Inbound Unicast: Packets 4 Bytes 320
 * Inbound Multicast: Packets 0 Bytes 0
 * Outbound Unicast: Packets 2 Bytes 160
 * Outbound Multicast: Packets 0 Bytes 0
 * RA Rx: 4
 * RA TxSuccess: 2
 * RA TxFailed: 0
 * RS Rx: 0
 * RS TxSuccess: 2
 * RS TxFailed: 0
 * Done
 * @endcode
 * @par api_copy
 * #otIp6GetBorderRoutingCounters
 */
template <> otError Br::Process<Cmd("counters")>(Arg aArgs[])
{
    otError error = OT_ERROR_NONE;

    VerifyOrExit(aArgs[0].IsEmpty(), error = OT_ERROR_INVALID_ARGS);
    Interpreter::GetInterpreter().OutputBorderRouterCounters();

exit:
    return error;
}

#endif // OPENTHREAD_CONFIG_IP6_BR_COUNTERS_ENABLE

otError Br::Process(Arg aArgs[])
{
#define CmdEntry(aCommandString)                          \
    {                                                     \
        aCommandString, &Br::Process<Cmd(aCommandString)> \
    }

    static constexpr Command kCommands[] = {
#if OPENTHREAD_CONFIG_IP6_BR_COUNTERS_ENABLE
        CmdEntry("counters"),
#endif
        CmdEntry("disable"),
        CmdEntry("enable"),
        CmdEntry("init"),
#if OPENTHREAD_CONFIG_NAT64_BORDER_ROUTING_ENABLE
        CmdEntry("nat64prefix"),
#endif
        CmdEntry("omrprefix"),
        CmdEntry("onlinkprefix"),
        CmdEntry("prefixtable"),
        CmdEntry("rioprf"),
        CmdEntry("routeprf"),
        CmdEntry("state"),
    };

#undef CmdEntry

    static_assert(BinarySearch::IsSorted(kCommands), "kCommands is not sorted");

    otError        error = OT_ERROR_INVALID_COMMAND;
    const Command *command;

    if (aArgs[0].IsEmpty() || (aArgs[0] == "help"))
    {
        OutputCommandTable(kCommands);
        ExitNow(error = aArgs[0].IsEmpty() ? error : OT_ERROR_NONE);
    }

    command = BinarySearch::Find(aArgs[0].GetCString(), kCommands);
    VerifyOrExit(command != nullptr);

    error = (this->*command->mHandler)(aArgs + 1);

exit:
    return error;
}

} // namespace Cli
} // namespace ot

#endif // OPENTHREAD_CONFIG_BORDER_ROUTING_ENABLE
