/*
 *  Copyright (c) 2020, 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 OTNS utilities.
 *
 */

#include "otns.hpp"

#if (OPENTHREAD_MTD || OPENTHREAD_FTD) && OPENTHREAD_CONFIG_OTNS_ENABLE

#include "common/debug.hpp"
#include "common/locator_getters.hpp"
#include "common/log.hpp"

namespace ot {
namespace Utils {

RegisterLogModule("Otns");

const int kMaxStatusStringLength = 128;

void Otns::EmitShortAddress(uint16_t aShortAddress)
{
    EmitStatus("rloc16=%d", aShortAddress);
}

void Otns::EmitExtendedAddress(const Mac::ExtAddress &aExtAddress)
{
    Mac::ExtAddress revExtAddress;
    revExtAddress.Set(aExtAddress.m8, Mac::ExtAddress::kReverseByteOrder);
    EmitStatus("extaddr=%s", revExtAddress.ToString().AsCString());
}

void Otns::EmitPingRequest(const Ip6::Address &aPeerAddress,
                           uint16_t            aPingLength,
                           uint32_t            aTimestamp,
                           uint8_t             aHopLimit)
{
    OT_UNUSED_VARIABLE(aHopLimit);
    EmitStatus("ping_request=%s,%d,%lu", aPeerAddress.ToString().AsCString(), aPingLength, aTimestamp);
}

void Otns::EmitPingReply(const Ip6::Address &aPeerAddress, uint16_t aPingLength, uint32_t aTimestamp, uint8_t aHopLimit)
{
    EmitStatus("ping_reply=%s,%u,%lu,%d", aPeerAddress.ToString().AsCString(), aPingLength, aTimestamp, aHopLimit);
}

void Otns::EmitStatus(const char *aFmt, ...)
{
    char statusStr[kMaxStatusStringLength + 1];
    int  n;

    va_list ap;
    va_start(ap, aFmt);

    n = vsnprintf(statusStr, sizeof(statusStr), aFmt, ap);
    OT_UNUSED_VARIABLE(n);
    OT_ASSERT(n >= 0);

    va_end(ap);

    otPlatOtnsStatus(statusStr);
}

void Otns::HandleNotifierEvents(Events aEvents)
{
    if (aEvents.Contains(kEventThreadRoleChanged))
    {
        EmitStatus("role=%d", Get<Mle::Mle>().GetRole());
    }

    if (aEvents.Contains(kEventThreadPartitionIdChanged))
    {
        EmitStatus("parid=%x", Get<Mle::Mle>().GetLeaderData().GetPartitionId());
    }

#if OPENTHREAD_CONFIG_JOINER_ENABLE
    if (aEvents.Contains(kEventJoinerStateChanged))
    {
        EmitStatus("joiner_state=%d", Get<MeshCoP::Joiner>().GetState());
    }
#endif
}

void Otns::EmitNeighborChange(NeighborTable::Event aEvent, const Neighbor &aNeighbor)
{
    switch (aEvent)
    {
    case NeighborTable::kRouterAdded:
        EmitStatus("router_added=%s", aNeighbor.GetExtAddress().ToString().AsCString());
        break;
    case NeighborTable::kRouterRemoved:
        EmitStatus("router_removed=%s", aNeighbor.GetExtAddress().ToString().AsCString());
        break;
    case NeighborTable::kChildAdded:
        EmitStatus("child_added=%s", aNeighbor.GetExtAddress().ToString().AsCString());
        break;
    case NeighborTable::kChildRemoved:
        EmitStatus("child_removed=%s", aNeighbor.GetExtAddress().ToString().AsCString());
        break;
    case NeighborTable::kChildModeChanged:
        break;
    }
}

void Otns::EmitTransmit(const Mac::TxFrame &aFrame)
{
    Mac::Address dst;
    uint16_t     frameControlField = aFrame.GetFrameControlField();
    uint8_t      channel           = aFrame.GetChannel();
    uint8_t      sequence          = aFrame.GetSequence();

    IgnoreError(aFrame.GetDstAddr(dst));

    if (dst.IsShort())
    {
        EmitStatus("transmit=%d,%04x,%d,%04x", channel, frameControlField, sequence, dst.GetShort());
    }
    else if (dst.IsExtended())
    {
        EmitStatus("transmit=%d,%04x,%d,%s", channel, frameControlField, sequence, dst.ToString().AsCString());
    }
    else
    {
        EmitStatus("transmit=%d,%04x,%d", channel, frameControlField, sequence);
    }
}

void Otns::EmitDeviceMode(Mle::DeviceMode aMode)
{
    EmitStatus("mode=%s%s%s", aMode.IsRxOnWhenIdle() ? "r" : "", aMode.IsFullThreadDevice() ? "d" : "",
               (aMode.GetNetworkDataType() == NetworkData::kFullSet) ? "n" : "");
}

void Otns::EmitCoapSend(const Coap::Message &aMessage, const Ip6::MessageInfo &aMessageInfo)
{
    char  uriPath[Coap::Message::kMaxReceivedUriPath + 1];
    Error error;

    SuccessOrExit(error = aMessage.ReadUriPathOptions(uriPath));

    EmitStatus("coap=send,%d,%d,%d,%s,%s,%d", aMessage.GetMessageId(), aMessage.GetType(), aMessage.GetCode(), uriPath,
               aMessageInfo.GetPeerAddr().ToString().AsCString(), aMessageInfo.GetPeerPort());
exit:
    if (error != kErrorNone)
    {
        LogWarn("EmitCoapSend failed: %s", ErrorToString(error));
    }
}

void Otns::EmitCoapReceive(const Coap::Message &aMessage, const Ip6::MessageInfo &aMessageInfo)
{
    char  uriPath[Coap::Message::kMaxReceivedUriPath + 1];
    Error error = kErrorNone;

    SuccessOrExit(error = aMessage.ReadUriPathOptions(uriPath));

    EmitStatus("coap=recv,%d,%d,%d,%s,%s,%d", aMessage.GetMessageId(), aMessage.GetType(), aMessage.GetCode(), uriPath,
               aMessageInfo.GetPeerAddr().ToString().AsCString(), aMessageInfo.GetPeerPort());
exit:
    if (error != kErrorNone)
    {
        LogWarn("EmitCoapReceive failed: %s", ErrorToString(error));
    }
}

void Otns::EmitCoapSendFailure(Error aError, Coap::Message &aMessage, const Ip6::MessageInfo &aMessageInfo)
{
    char  uriPath[Coap::Message::kMaxReceivedUriPath + 1];
    Error error = kErrorNone;

    SuccessOrExit(error = aMessage.ReadUriPathOptions(uriPath));

    EmitStatus("coap=send_error,%d,%d,%d,%s,%s,%d,%s", aMessage.GetMessageId(), aMessage.GetType(), aMessage.GetCode(),
               uriPath, aMessageInfo.GetPeerAddr().ToString().AsCString(), aMessageInfo.GetPeerPort(),
               ErrorToString(aError));
exit:
    if (error != kErrorNone)
    {
        LogWarn("EmitCoapSendFailure failed: %s", ErrorToString(error));
    }
}

} // namespace Utils
} // namespace ot

#endif // (OPENTHREAD_MTD || OPENTHREAD_FTD) && OPENTHREAD_CONFIG_OTNS_ENABLE
