/*
 *
 *    Copyright (c) 2020 Project CHIP Authors
 *    Copyright (c) 2018 Nest Labs, Inc.
 *    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.
 */

/**
 *    @file
 *          Contains non-inline method definitions for the
 *          GenericThreadStackManagerImpl_OpenThread_LwIP<> template.
 */

#include <lib/core/CHIPEncoding.h>
#include <platform/OpenThread/GenericThreadStackManagerImpl_OpenThread_LwIP.h>
#include <platform/OpenThread/OpenThreadUtils.h>
#include <platform/internal/CHIPDeviceLayerInternal.h>

#include <openthread/error.h>
#include <openthread/icmp6.h>
#include <openthread/ip6.h>
#include <openthread/netdata.h>
#include <openthread/thread.h>

#include <credentials/GroupDataProvider.h>

#include <platform/OpenThread/GenericThreadStackManagerImpl_OpenThread.cpp>

#include <transport/raw/PeerAddress.h>

#if CHIP_SYSTEM_CONFIG_USE_OPEN_THREAD_ENDPOINT
#error "When using OpenThread Endpoints, one should also use GenericThreadStackManagerImpl_OpenThread"
#endif // CHIP_SYSTEM_CONFIG_USE_OPEN_THREAD_ENDPOINT

namespace chip {
namespace DeviceLayer {
namespace Internal {

template <class ImplClass>
void GenericThreadStackManagerImpl_OpenThread_LwIP<ImplClass>::_OnPlatformEvent(const ChipDeviceEvent * event)
{
    // Pass the event to the base class first.
    GenericThreadStackManagerImpl_OpenThread<ImplClass>::_OnPlatformEvent(event);

    if (event->Type == DeviceEventType::kThreadStateChange)
    {
        // If the Thread device role has changed, or if an IPv6 address has been added or
        // removed in the Thread stack, update the state and configuration of the LwIP Thread interface.
        if (event->ThreadStateChange.RoleChanged || event->ThreadStateChange.AddressChanged)
        {
            UpdateThreadInterface(event->ThreadStateChange.AddressChanged);
        }
    }
}

template <class ImplClass>
CHIP_ERROR GenericThreadStackManagerImpl_OpenThread_LwIP<ImplClass>::DoInit(otInstance * otInst)
{
    CHIP_ERROR err = CHIP_NO_ERROR;

    static struct netif sThreadNetIf;

    // Initialize member data.
    memset(mAddrAssigned, 0, sizeof(mAddrAssigned));

    sThreadNetIf.name[0] = 'o';
    sThreadNetIf.name[1] = 't';

    // Initialize the base class.
    err = GenericThreadStackManagerImpl_OpenThread<ImplClass>::DoInit(otInst);
    SuccessOrExit(err);

    // Lock LwIP stack
    LOCK_TCPIP_CORE();

    // Initialize a LwIP netif structure for the OpenThread interface and
    // add it to the list of interfaces known to LwIP.
    mNetIf = netif_add(&sThreadNetIf,
#if LWIP_IPV4
                       NULL, NULL, NULL,
#endif // LWIP_IPV4
                       NULL, DoInitThreadNetIf, tcpip_input);

    // Start with the interface in the down state.
    netif_set_link_down(mNetIf);

    // Unkock LwIP stack
    UNLOCK_TCPIP_CORE();

    VerifyOrExit(mNetIf != NULL, err = INET_ERROR_INTERFACE_INIT_FAILURE);

    // Lock OpenThread
    Impl()->LockThreadStack();

    // Arrange for OpenThread to call our ReceivePacket() method whenever an
    // IPv6 packet is received.
    otIp6SetReceiveCallback(Impl()->OTInstance(), ReceivePacket, NULL);

    // Disable automatic echo mode in OpenThread.
    otIcmp6SetEchoMode(Impl()->OTInstance(), OT_ICMP6_ECHO_HANDLER_DISABLED);

    // Enable the receive filter for Thread control traffic.
    otIp6SetReceiveFilterEnabled(Impl()->OTInstance(), true);

    // Unlock OpenThread
    Impl()->UnlockThreadStack();

exit:
    return err;
}

template <class ImplClass>
void GenericThreadStackManagerImpl_OpenThread_LwIP<ImplClass>::UpdateThreadInterface(bool addrChange)
{
    err_t lwipErr = ERR_OK;
    bool isInterfaceUp;
    bool addrAssigned[LWIP_IPV6_NUM_ADDRESSES];

    memset(addrAssigned, 0, sizeof(addrAssigned));

    // Lock LwIP stack first, then OpenThread.
    LOCK_TCPIP_CORE();
    Impl()->LockThreadStack();

    // Determine whether the device Thread interface is up..
    isInterfaceUp = GenericThreadStackManagerImpl_OpenThread<ImplClass>::IsThreadInterfaceUpNoLock();

    // If needed, adjust the link state of the LwIP netif to reflect the state of the OpenThread stack.
    // Set ifConnectivity to indicate the change in the link state.
    if (isInterfaceUp != (bool) netif_is_link_up(mNetIf))
    {
        ChipLogDetail(DeviceLayer, "LwIP Thread interface %s", isInterfaceUp ? "UP" : "DOWN");

        if (isInterfaceUp)
        {
            netif_set_link_up(mNetIf);
        }
        else
        {
            netif_set_link_down(mNetIf);
        }

        // Presume the interface addresses are also changing.
        addrChange = true;
    }

    // If needed, adjust the set of addresses associated with the LwIP netif to reflect those
    // known to the Thread stack.
    if (addrChange)
    {
        // If attached to a Thread network, add addresses to the LwIP netif to match those
        // configured in the Thread stack...
        if (isInterfaceUp)
        {
            // Enumerate the list of unicast IPv6 addresses known to OpenThread...
            const otNetifAddress * otAddrs = otIp6GetUnicastAddresses(Impl()->OTInstance());
            for (const otNetifAddress * otAddr = otAddrs; otAddr != NULL; otAddr = otAddr->mNext)
            {
                Inet::IPAddress addr = ToIPAddress(otAddr->mAddress);

                // Assign the following OpenThread addresses to LwIP's address table:
                //   - link-local addresses.
                //   - mesh-local addresses that are NOT RLOC addresses.
                //   - global unicast addresses.
                if (otAddr->mValid && !otAddr->mRloc)
                {
                    ip_addr_t lwipAddr = addr.ToLwIPAddr();
                    s8_t addrIdx;

                    // Add the address to the LwIP netif.  If the address is a link-local, and the primary
                    // link-local address* for the LwIP netif has not been set already, then use netif_ip6_addr_set()
                    // to set the primary address.  Otherwise use netif_add_ip6_address(). This special case is
                    // required because LwIP's netif_add_ip6_address() will never set the primary link-local address.
                    //
                    // * -- The primary link-local address always appears in the first slot in the netif address table.
                    //
                    if (addr.IsIPv6LinkLocal() && !addrAssigned[0])
                    {
                        netif_ip6_addr_set(mNetIf, 0, ip_2_ip6(&lwipAddr));
                        addrIdx = 0;
                    }
                    else
                    {
                        // Add the address to the LwIP netif.  If the address table fills (ERR_VAL), simply stop
                        // adding addresses.  If something else fails, log it and soldier on.
                        lwipErr = netif_add_ip6_address(mNetIf, ip_2_ip6(&lwipAddr), &addrIdx);
                        if (lwipErr == ERR_VAL)
                        {
                            break;
                        }
                        else if (lwipErr != ERR_OK)
                        {
                            ChipLogProgress(DeviceLayer, "netif_add_ip6_address) failed: %s",
                                            ErrorStr(chip::System::MapErrorLwIP(lwipErr)));
                        }
                    }

                    // Set non-mesh-local address state to PREFERRED or ACTIVE depending on the state in OpenThread.
                    netif_ip6_addr_set_state(mNetIf, addrIdx,
                                             (otAddr->mPreferred && !IsOpenThreadMeshLocalAddress(Impl()->OTInstance(), addr))
                                                 ? IP6_ADDR_PREFERRED
                                                 : IP6_ADDR_VALID);

                    // Record that the netif address slot was assigned during this loop.
                    addrAssigned[addrIdx] = true;
                }
            }
        }

        ChipLogDetail(DeviceLayer, "LwIP Thread interface addresses %s", isInterfaceUp ? "updated" : "cleared");

        // For each address associated with the netif that was *not* assigned above, remove the address
        // from the netif if the address is one that was previously assigned by this method.
        // In the case where the device is no longer attached to a Thread network, remove all addresses
        // from the netif.
        for (u8_t addrIdx = 0; addrIdx < LWIP_IPV6_NUM_ADDRESSES; addrIdx++)
        {
            if (!isInterfaceUp || (mAddrAssigned[addrIdx] && !addrAssigned[addrIdx]))
            {
                // Remove the address from the netif by setting its state to INVALID
                netif_ip6_addr_set_state(mNetIf, addrIdx, IP6_ADDR_INVALID);
            }

#if CHIP_DETAIL_LOGGING
            else
            {
                uint8_t state = netif_ip6_addr_state(mNetIf, addrIdx);
                if (state != IP6_ADDR_INVALID)
                {
                    Inet::IPAddress addr = Inet::IPAddress(*netif_ip6_addr(mNetIf, addrIdx));
                    char addrStr[50];
                    addr.ToString(addrStr, sizeof(addrStr));
                    const char * typeStr;
                    if (IsOpenThreadMeshLocalAddress(Impl()->OTInstance(), addr))
                        typeStr = "Thread mesh-local address";
                    else
                        typeStr = CharacterizeIPv6Address(addr);
                    ChipLogDetail(DeviceLayer, "   %s %s%s)", addrStr, typeStr, (state == IP6_ADDR_PREFERRED) ? ", preferred" : "");
                }
            }
#endif // CHIP_DETAIL_LOGGING
        }

        // Remember the set of assigned addresses.
        memcpy(mAddrAssigned, addrAssigned, sizeof(mAddrAssigned));
    }

    Impl()->UnlockThreadStack();
    UNLOCK_TCPIP_CORE();
}

template <class ImplClass>
err_t GenericThreadStackManagerImpl_OpenThread_LwIP<ImplClass>::DoInitThreadNetIf(struct netif * netif)
{
    netif->name[0]    = CHIP_DEVICE_CONFIG_LWIP_THREAD_IF_NAME[0];
    netif->name[1]    = CHIP_DEVICE_CONFIG_LWIP_THREAD_IF_NAME[1];
    netif->output_ip6 = SendPacket;
#if LWIP_IPV4
    netif->output = NULL;
#endif // LWIP_IPV4
    netif->linkoutput = NULL;
    netif->flags      = NETIF_FLAG_UP | NETIF_FLAG_LINK_UP | NETIF_FLAG_BROADCAST;
    netif->mtu        = CHIP_DEVICE_CONFIG_THREAD_IF_MTU;
    return ERR_OK;
}

/**
 * Send an outbound packet via the LwIP Thread interface.
 *
 * This method is called by LwIP, via a pointer in the netif structure, whenever
 * an IPv6 packet is to be sent out the Thread interface.
 *
 * NB: This method is called in the LwIP TCPIP thread with the LwIP core lock held.
 */
template <class ImplClass>
err_t GenericThreadStackManagerImpl_OpenThread_LwIP<ImplClass>::SendPacket(struct netif * netif, struct pbuf * pktPBuf,
                                                                           const struct ip6_addr * ipaddr)
{
    err_t lwipErr = ERR_OK;
    otError otErr;
    otMessage * pktMsg                  = NULL;
    const otMessageSettings msgSettings = { true, OT_MESSAGE_PRIORITY_NORMAL };
    uint16_t remainingLen;

    // Lock the OpenThread stack.
    // Note that at this point the LwIP core lock is also held.
    ThreadStackMgrImpl().LockThreadStack();

    // Allocate an OpenThread message
    pktMsg = otIp6NewMessage(ThreadStackMgrImpl().OTInstance(), &msgSettings);
    VerifyOrExit(pktMsg != NULL, lwipErr = ERR_MEM);

    // Copy data from LwIP's packet buffer chain into the OpenThread message.
    remainingLen = pktPBuf->tot_len;
    for (struct pbuf * partialPkt = pktPBuf; partialPkt != NULL; partialPkt = partialPkt->next)
    {
        VerifyOrExit(partialPkt->len <= remainingLen, lwipErr = ERR_VAL);

        otErr = otMessageAppend(pktMsg, partialPkt->payload, partialPkt->len);
        VerifyOrExit(otErr == OT_ERROR_NONE, lwipErr = ERR_MEM);

        remainingLen = static_cast<uint16_t>(remainingLen - partialPkt->len);
    }
    VerifyOrExit(remainingLen == 0, lwipErr = ERR_VAL);

#if CHIP_DETAIL_LOGGING
    LogOpenThreadPacket("Thread packet SENT", pktMsg);
#endif // CHIP_DETAIL_LOGGING

    // Pass the packet to OpenThread to be sent.  Note that OpenThread takes care of releasing
    // the otMessage object regardless of whether otIp6Send() succeeds or fails.
    // Propagate the error back up the stack UNLESS it is a transient error.
    otErr  = otIp6Send(ThreadStackMgrImpl().OTInstance(), pktMsg);
    pktMsg = NULL;
#if CHIP_DETAIL_LOGGING
    if (otErr != OT_ERROR_NONE)
    {
        ChipLogDetail(DeviceLayer, "ThreadStackManagerImpl: otIp6Send() error: %s", otThreadErrorToString(otErr));
    }
#endif // CHIP_DETAIL_LOGGING
    VerifyOrExit(otErr == OT_ERROR_NONE || otErr == OT_ERROR_DROP || otErr == OT_ERROR_NO_BUFS || otErr == OT_ERROR_NO_ROUTE,
                 lwipErr = ERR_IF);

exit:

    if (pktMsg != NULL)
    {
        otMessageFree(pktMsg);
    }

    if (lwipErr == ERR_MEM)
    {
        ThreadStackMgrImpl().OverrunErrorTally();
    }

    // Unlock the OpenThread stack.
    ThreadStackMgrImpl().UnlockThreadStack();

    return lwipErr;
}

/**
 * Receive an inbound packet from the LwIP Thread interface.
 *
 * This method is called by OpenThread whenever an IPv6 packet has been received destined
 * to the local node has been received from the Thread interface.
 *
 * NB: This method is called with the OpenThread stack lock held.  To ensure proper
 * lock ordering, it must *not* attempt to acquire the LwIP TCPIP core lock, or the
 * CHIP stack lock.
 */
template <class ImplClass>
void GenericThreadStackManagerImpl_OpenThread_LwIP<ImplClass>::ReceivePacket(otMessage * pkt, void *)
{
    struct pbuf * pbuf         = NULL;
    err_t lwipErr              = ERR_OK;
    uint16_t pktLen            = otMessageGetLength(pkt);
    struct netif * threadNetIf = ThreadStackMgrImpl().ThreadNetIf();

    // Allocate an LwIP pbuf to hold the inbound packet.
    pbuf = pbuf_alloc(PBUF_LINK, pktLen, PBUF_POOL);
    VerifyOrExit(pbuf != NULL, lwipErr = ERR_MEM);

    // Copy the packet data from the OpenThread message object to the pbuf.
    if (otMessageRead(pkt, 0, pbuf->payload, pktLen) != pktLen)
    {
        ExitNow(lwipErr = ERR_IF);
    }

#if CHIP_DETAIL_LOGGING
    LogOpenThreadPacket("Thread packet RCVD", pkt);
#endif // CHIP_DETAIL_LOGGING

    // Deliver the packet to the input function associated with the LwIP netif.
    // NOTE: The input function posts the inbound packet to LwIP's TCPIP thread.
    // Thus there's no need to acquire the LwIP TCPIP core lock here.
    lwipErr = threadNetIf->input(pbuf, threadNetIf);

exit:

    // Always free the OpenThread message.
    otMessageFree(pkt);

    if (lwipErr != ERR_OK)
    {
        // If an error occurred, make sure the pbuf gets freed.
        if (pbuf != NULL)
        {
            pbuf_free(pbuf);
        }

        // TODO: log packet reception error
        // TODO: deliver CHIP platform event signaling loss of inbound packet.
    }
}

// Fully instantiate the generic implementation class in whatever compilation unit includes this file.
// NB: This must come after all templated class members are defined.
template class GenericThreadStackManagerImpl_OpenThread_LwIP<ThreadStackManagerImpl>;

} // namespace Internal
} // namespace DeviceLayer
} // namespace chip
