/*
 *
 *    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
 *          Provides implementations of platform functions for the Weave
 *          Addressing and Routing Module (WARM) for use on LwIP-based
 *          platforms.
 */

#include <Weave/DeviceLayer/internal/WeaveDeviceLayerInternal.h>
#include <Weave/DeviceLayer/ConnectivityManager.h>
#include <Weave/DeviceLayer/LwIP/WarmSupport.h>
#include <lwip/netif.h>
#include <lwip/ip6_route_table.h>
#if LWIP_IPV6_MLD
#include "lwip/mld6.h"
#endif /* LWIP_IPV6_MLD */

#if WARM_CONFIG_SUPPORT_THREAD
#include <Weave/DeviceLayer/ThreadStackManager.h>
#include <Weave/DeviceLayer/OpenThread/OpenThreadUtils.h>
#include <openthread/ip6.h>
#endif // WARM_CONFIG_SUPPORT_THREAD


using namespace ::nl::Weave::DeviceLayer;
using namespace ::nl::Weave::DeviceLayer::Internal;

using namespace ::nl;
using namespace ::nl::Weave;
using namespace ::nl::Weave::Warm;

// ==================== WARM Platform Functions ====================

namespace nl {
namespace Weave {
namespace Warm {
namespace Platform {

WEAVE_ERROR Init(WarmFabricStateDelegate * inFabricStateDelegate)
{
    // Nothing to do.
    return WEAVE_NO_ERROR;
}

void CriticalSectionEnter(void)
{
    // No-op on this platform since all interaction with WARM core happens on the Weave event thread.
}

void CriticalSectionExit(void)
{
    // No-op on this platform since all interaction with WARM core happens on the Weave event thread.
}

void RequestInvokeActions(void)
{
    ::nl::Weave::Warm::InvokeActions();
}

PlatformResult AddRemoveHostAddress(InterfaceType inInterfaceType, const Inet::IPAddress & inAddress, uint8_t inPrefixLength, bool inAdd)
{
    WEAVE_ERROR err = WEAVE_NO_ERROR;
    err_t lwipErr;
    struct netif * netif;
    ip6_addr_t ip6addr = inAddress.ToIPv6();
    bool lockHeld = false;

    // If an address is being added/removed from the tunnel interface, and the address in question
    // is a ULA referring to the Weave Primary WiFi subnet, substitute the Thread Mesh subnet id.
    // This works around a limitation in the current Nest service, which presumes that all devices
    // have a Thread radio, and therefore a Thread subnet Weave ULA to which packets can be routed.
    if (inInterfaceType == kInterfaceTypeTunnel && inAddress.IsIPv6ULA() && inAddress.Subnet() == kWeaveSubnetId_PrimaryWiFi)
    {
        Inet::IPAddress altAddr = Inet::IPAddress::MakeULA(inAddress.GlobalId(), kWeaveSubnetId_ThreadMesh, inAddress.InterfaceId());
        ip6addr = altAddr.ToIPv6();
    }

    LOCK_TCPIP_CORE();
    lockHeld = true;

    err = GetLwIPNetifForWarmInterfaceType(inInterfaceType, netif);
    SuccessOrExit(err);

    if (inAdd)
    {
        s8_t addrIdx;
        lwipErr = netif_add_ip6_address_with_route(netif, &ip6addr, inPrefixLength, &addrIdx);
        err = System::MapErrorLwIP(lwipErr);
        if (err != WEAVE_NO_ERROR)
        {
            WeaveLogError(DeviceLayer, "netif_add_ip6_address_with_route() failed for %s interface: %s",
                    WarmInterfaceTypeToStr(inInterfaceType), nl::ErrorStr(err));
            ExitNow();
        }
        netif_ip6_addr_set_state(netif, addrIdx, IP6_ADDR_PREFERRED);

#if LWIP_IPV6_MLD
        // If the interface supports IPv6 MLD, join the solicited-node multicast group associated
        // with the assigned address.
        if (LwIPNetifSupportsMLD(netif))
        {
            ip6_addr_t solNodeAddr;
            ip6_addr_set_solicitednode(&solNodeAddr, ip6addr.addr[3]);
            lwipErr = mld6_joingroup_netif(netif, &solNodeAddr);
            err = System::MapErrorLwIP(lwipErr);
            if (err != WEAVE_NO_ERROR)
            {
                WeaveLogError(DeviceLayer, "mld6_joingroup_netif() failed for %s interface: %s",
                        WarmInterfaceTypeToStr(inInterfaceType), nl::ErrorStr(err));
                ExitNow();
            }
        }
#endif /* LWIP_IPV6_MLD */
    }
    else
    {
        lwipErr = netif_remove_ip6_address_with_route(netif, &ip6addr, inPrefixLength);
        // There are two possible errors from netif_remove_ip6_address: ERR_ARG
        // if call was made with wrong arguments, or ERR_VAL if the action could
        // not be performed (e.g. the address was already removed).  We squash
        // ERR_VAL, and return SUCCESS so that WARM can set its state correctly.
        if (lwipErr == ERR_VAL)
        {
            WeaveLogProgress(DeviceLayer, "netif_remove_ip6_address_with_route: Already removed");
            lwipErr = ERR_OK;
        }
        err = System::MapErrorLwIP(lwipErr);
        if (err != WEAVE_NO_ERROR)
        {
            WeaveLogError(DeviceLayer, "netif_remove_ip6_address_with_route() failed for %s interface: %s",
                     WarmInterfaceTypeToStr(inInterfaceType), nl::ErrorStr(err));
            ExitNow();
        }

#if LWIP_IPV6_MLD
        // Leave the solicited-node multicast group associated with the removed address.
        {
            ip6_addr_t solNodeAddr;
            ip6_addr_set_solicitednode(&solNodeAddr, ip6addr.addr[3]);
            mld6_leavegroup_netif(netif, &solNodeAddr);
        }
#endif /* LWIP_IPV6_MLD */
    }

    UNLOCK_TCPIP_CORE();
    lockHeld = false;

#if WEAVE_PROGRESS_LOGGING
    {
        char interfaceName[4];
        GetInterfaceName(netif, interfaceName, sizeof(interfaceName));
        char ipAddrStr[INET6_ADDRSTRLEN];
        inAddress.ToString(ipAddrStr, sizeof(ipAddrStr));
        WeaveLogProgress(DeviceLayer, "%s %s %s LwIP %s interface (%s): %s/%" PRId8,
                 (inAdd) ? "Adding" : "Removing",
                 CharacterizeIPv6Address(inAddress),
                 (inAdd) ? "to" : "from",
                 WarmInterfaceTypeToStr(inInterfaceType),
                 interfaceName,
                 ipAddrStr, inPrefixLength);
    }
#endif // WEAVE_PROGRESS_LOGGING

exit:
    if (lockHeld)
    {
        UNLOCK_TCPIP_CORE();
    }

    if (err != WEAVE_NO_ERROR)
    {
        WeaveLogError(DeviceLayer, "AddRemoveHostAddress() failed: %s", ::nl::ErrorStr(err));
    }

    return (err == WEAVE_NO_ERROR) ? kPlatformResultSuccess : kPlatformResultFailure;
}

PlatformResult AddRemoveHostRoute(InterfaceType inInterfaceType, const Inet::IPPrefix & inPrefix, RoutePriority inPriority, bool inAdd)
{
    WEAVE_ERROR err = WEAVE_NO_ERROR;
    struct netif * netif;
    bool lockHeld = false;

    LOCK_TCPIP_CORE();
    lockHeld = true;

    err = GetLwIPNetifForWarmInterfaceType(inInterfaceType, netif);
    SuccessOrExit(err);

    // if requested, set/unset the default route...
    if (inPrefix.Length == 0)
    {
        // Only bother to set the default route.
        if (inAdd)
        {
            netif_set_default(netif);
        }
    }

    // otherwise a more specific route is being added/removed, so...
    else
    {
#if WARM_CONFIG_SUPPORT_WIFI || WARM_CONFIG_SUPPORT_CELLULAR

        // On platforms that support WiFi and/or cellular, this code supports full manipulation of the
        // local routing table.  Note that this requires a custom version of LwIP that support the
        // LWIP_IPV6_ROUTE_TABLE_SUPPORT extension.

        struct ip6_prefix lwipIP6prefix;
        lwipIP6prefix.addr = inPrefix.IPAddr.ToIPv6();
        lwipIP6prefix.prefix_len = inPrefix.Length;

        if (inAdd)
        {
            err_t lwipErr = ip6_add_route_entry(&lwipIP6prefix, netif, NULL, NULL);
            err = System::MapErrorLwIP(lwipErr);
            if (err != WEAVE_NO_ERROR)
            {
                WeaveLogError(DeviceLayer, "ip6_add_route_entry() failed for %s interface: %s",
                         WarmInterfaceTypeToStr(inInterfaceType), nl::ErrorStr(err));
                ExitNow();
            }
        }
        else
        {
            ip6_remove_route_entry(&lwipIP6prefix);
        }

#elif WARM_CONFIG_SUPPORT_THREAD

        // On platforms that only support Thread there is only one interface, and thus no need
        // for a generalized routing table or adding/removing routes. In this situation, WARM
        // will only call this function to set the default route.  Since that case was handled
        // above, we fail with an error here.

        ExitNow(err = WEAVE_ERROR_INVALID_ARGUMENT);

#endif // WARM_CONFIG_SUPPORT_THREAD
    }

    UNLOCK_TCPIP_CORE();
    lockHeld = false;

#if WEAVE_PROGRESS_LOGGING
    {
        char interfaceName[4];
        GetInterfaceName(netif, interfaceName, sizeof(interfaceName));
        if (inPrefix.Length != 0)
        {
            char prefixAddrStr[INET6_ADDRSTRLEN];
            inPrefix.IPAddr.ToString(prefixAddrStr, sizeof(prefixAddrStr));
            const char * prefixDesc = CharacterizeIPv6Prefix(inPrefix);
            WeaveLogProgress(DeviceLayer, "IPv6 route%s%s %s LwIP %s interface (%s): %s/%" PRId8,
                     (prefixDesc != NULL) ? " for " : "",
                     (prefixDesc != NULL) ? prefixDesc : "",
                     (inAdd) ? "added to" : "removed from",
                     WarmInterfaceTypeToStr(inInterfaceType),
                     interfaceName,
                     prefixAddrStr, inPrefix.Length);
        }
        else
        {
            WeaveLogProgress(DeviceLayer, "LwIP default interface set to %s interface (%s)",
                     WarmInterfaceTypeToStr(inInterfaceType),
                     interfaceName);
        }
    }
#endif // WEAVE_PROGRESS_LOGGING

exit:
    if (lockHeld)
    {
        UNLOCK_TCPIP_CORE();
    }

    if (err != WEAVE_NO_ERROR)
    {
        WeaveLogError(DeviceLayer, "AddRemoveHostRoute() failed: %s", ::nl::ErrorStr(err));
    }

    return (err == WEAVE_NO_ERROR) ? kPlatformResultSuccess : kPlatformResultFailure;
}

#if WARM_CONFIG_SUPPORT_THREAD

PlatformResult AddRemoveThreadAddress(InterfaceType inInterfaceType, const Inet::IPAddress &inAddress, bool inAdd)
{
    otError otErr;
    otNetifAddress otAddress;

    memset(&otAddress, 0, sizeof(otAddress));
    otAddress.mAddress = ToOpenThreadIP6Address(inAddress);
    otAddress.mPrefixLength = 64;
    otAddress.mValid = true;
    otAddress.mPreferred = true;

    ThreadStackMgrImpl().LockThreadStack();

    if (inAdd)
    {
        otErr = otIp6AddUnicastAddress(ThreadStackMgrImpl().OTInstance(), &otAddress);
    }
    else
    {
        otErr = otIp6RemoveUnicastAddress(ThreadStackMgrImpl().OTInstance(), &otAddress.mAddress);
        // There are two possible errors from otIp6RemoveUnicastAddress:
        // OT_ERROR_INVALID_ARGS if the address was a multicast address, and
        // OT_ERROR_NOT_FOUND if the address does not exist on the thread
        // interface.  We squash the OT_ERROR_NOT_FOUND so that WARM sets its
        // state correctly.
        if (otErr == OT_ERROR_NOT_FOUND)
        {
            WeaveLogProgress(DeviceLayer, "otIp6RemoveUnicastAddress: already removed");
            otErr = OT_ERROR_NONE;
        }
    }

    ThreadStackMgrImpl().UnlockThreadStack();

    if (otErr == OT_ERROR_NONE)
    {
#if WEAVE_PROGRESS_LOGGING
        char ipAddrStr[INET6_ADDRSTRLEN];
        inAddress.ToString(ipAddrStr, sizeof(ipAddrStr));
        WeaveLogProgress(DeviceLayer, "%s %s %s OpenThread stack: %s/64",
                 (inAdd) ? "Adding" : "Removing",
                 CharacterizeIPv6Address(inAddress),
                 (inAdd) ? "to" : "from",
                 ipAddrStr);
#endif // WEAVE_PROGRESS_LOGGING
    }
    else
    {
        WeaveLogError(DeviceLayer, "AddRemoveThreadAddress() failed: %s", ::nl::ErrorStr(MapOpenThreadError(otErr)));
    }

    return (otErr == OT_ERROR_NONE) ? kPlatformResultSuccess : kPlatformResultFailure;
}

#endif // WARM_CONFIG_SUPPORT_THREAD

#if WARM_CONFIG_SUPPORT_THREAD_ROUTING

#error "Weave Thread router support not implemented"

PlatformResult StartStopThreadAdvertisement(InterfaceType inInterfaceType, const Inet::IPPrefix &inPrefix, bool inStart)
{
    // TODO: implement me
}

#endif // WARM_CONFIG_SUPPORT_THREAD_ROUTING

#if WARM_CONFIG_SUPPORT_BORDER_ROUTING

#error "Weave border router support not implemented"

PlatformResult AddRemoveThreadRoute(InterfaceType inInterfaceType, const Inet::IPPrefix &inPrefix, RoutePriority inPriority, bool inAdd)
{
    // TODO: implement me
}

PlatformResult SetThreadRoutePriority(InterfaceType inInterfaceType, const Inet::IPPrefix &inPrefix, RoutePriority inPriority)
{
    // TODO: implement me
}

#endif // WARM_CONFIG_SUPPORT_BORDER_ROUTING

} // namespace Platform
} // namespace Warm
} // namespace Weave
} // namespace nl

// ==================== WARM Utility Functions ====================

namespace nl {
namespace Weave {
namespace DeviceLayer {
namespace Internal {

WEAVE_ERROR GetLwIPNetifForWarmInterfaceType(InterfaceType inInterfaceType, struct netif *& netif)
{
    WEAVE_ERROR err = WEAVE_NO_ERROR;

    for (netif = netif_list; netif != NULL; netif = netif->next)
    {
        if (inInterfaceType == kInterfaceTypeWiFi &&
            netif->name[0] == WEAVE_DEVICE_CONFIG_LWIP_WIFI_STATION_IF_NAME[0] &&
            netif->name[1] == WEAVE_DEVICE_CONFIG_LWIP_WIFI_STATION_IF_NAME[1])
        {
            ExitNow(err = WEAVE_NO_ERROR);
        }

        if (inInterfaceType == kInterfaceTypeTunnel &&
            netif->name[0] == WEAVE_DEVICE_CONFIG_LWIP_SERVICE_TUN_IF_NAME[0] &&
            netif->name[1] == WEAVE_DEVICE_CONFIG_LWIP_SERVICE_TUN_IF_NAME[1])
        {
            ExitNow(err = WEAVE_NO_ERROR);
        }

        if (inInterfaceType == kInterfaceTypeThread &&
            netif->name[0] == WEAVE_DEVICE_CONFIG_LWIP_THREAD_IF_NAME[0] &&
            netif->name[1] == WEAVE_DEVICE_CONFIG_LWIP_THREAD_IF_NAME[1])
        {
            ExitNow(err = WEAVE_NO_ERROR);
        }
    }

    ExitNow(err = INET_ERROR_UNKNOWN_INTERFACE);

exit:
    return err;
}

bool LwIPNetifSupportsMLD(struct netif * netif)
{
    // Determine if the given netif supports IPv6 MLD.  Unfortunately, the LwIP MLD6 netif flag
    // is an unreliable indication of MLD support in older versions of LwIP.
    return (((netif->flags & NETIF_FLAG_MLD6) != 0) ||
            (netif->name[0] == WEAVE_DEVICE_CONFIG_LWIP_WIFI_STATION_IF_NAME[0] &&
             netif->name[1] == WEAVE_DEVICE_CONFIG_LWIP_WIFI_STATION_IF_NAME[1]));
}

const char * WarmInterfaceTypeToStr(InterfaceType inInterfaceType)
{
    switch (inInterfaceType)
    {
    case kInterfaceTypeLegacy6LoWPAN:
        return "Legacy 6LoWPAN";
    case kInterfaceTypeThread:
        return "Thread";
    case kInterfaceTypeWiFi:
        return "WiFi station";
    case kInterfaceTypeTunnel:
        return "Tunnel";
    case kInterfaceTypeCellular:
        return "Cellular";
    default:
        return "(unknown)";
    }
}

} // namespace Internal
} // namespace DeviceLayer
} // namespace Weave
} // namespace nl
