/*
 *  Copyright (c) 2016, 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 the Thread Network Data managed by the Thread Leader.
 */

#define WPP_NAME "network_data_leader.tmh"

#include <openthread/config.h>

#include "network_data_leader.hpp"

#include <openthread/platform/random.h>

#include "coap/coap_header.hpp"
#include "common/code_utils.hpp"
#include "common/debug.hpp"
#include "common/encoding.hpp"
#include "common/logging.hpp"
#include "common/message.hpp"
#include "common/timer.hpp"
#include "mac/mac_frame.hpp"
#include "thread/mle_router.hpp"
#include "thread/lowpan.hpp"
#include "thread/thread_netif.hpp"
#include "thread/thread_tlvs.hpp"
#include "thread/thread_uri_paths.hpp"

using ot::Encoding::BigEndian::HostSwap16;

namespace ot {
namespace NetworkData {

LeaderBase::LeaderBase(ThreadNetif &aThreadNetif):
    NetworkData(aThreadNetif, false)
{
    Reset();
}

void LeaderBase::Reset(void)
{
    mVersion = static_cast<uint8_t>(otPlatRandomGet());
    mStableVersion = static_cast<uint8_t>(otPlatRandomGet());
    mLength = 0;
    GetNetif().SetStateChangedFlags(OT_CHANGED_THREAD_NETDATA);
}

otError LeaderBase::GetContext(const Ip6::Address &aAddress, Lowpan::Context &aContext)
{
    ThreadNetif &netif = GetNetif();
    PrefixTlv *prefix;
    ContextTlv *contextTlv;

    aContext.mPrefixLength = 0;

    if (PrefixMatch(netif.GetMle().GetMeshLocalPrefix(), aAddress.mFields.m8, 64) >= 0)
    {
        aContext.mPrefix = netif.GetMle().GetMeshLocalPrefix();
        aContext.mPrefixLength = 64;
        aContext.mContextId = 0;
        aContext.mCompressFlag = true;
    }

    for (NetworkDataTlv *cur = reinterpret_cast<NetworkDataTlv *>(mTlvs);
         cur < reinterpret_cast<NetworkDataTlv *>(mTlvs + mLength);
         cur = cur->GetNext())
    {
        if (cur->GetType() != NetworkDataTlv::kTypePrefix)
        {
            continue;
        }

        prefix = static_cast<PrefixTlv *>(cur);

        if (PrefixMatch(prefix->GetPrefix(), aAddress.mFields.m8, prefix->GetPrefixLength()) < 0)
        {
            continue;
        }

        contextTlv = FindContext(*prefix);

        if (contextTlv == NULL)
        {
            continue;
        }

        if (prefix->GetPrefixLength() > aContext.mPrefixLength)
        {
            aContext.mPrefix = prefix->GetPrefix();
            aContext.mPrefixLength = prefix->GetPrefixLength();
            aContext.mContextId = contextTlv->GetContextId();
            aContext.mCompressFlag = contextTlv->IsCompress();
        }
    }

    return (aContext.mPrefixLength > 0) ? OT_ERROR_NONE : OT_ERROR_NOT_FOUND;
}

otError LeaderBase::GetContext(uint8_t aContextId, Lowpan::Context &aContext)
{
    otError error = OT_ERROR_NOT_FOUND;
    PrefixTlv *prefix;
    ContextTlv *contextTlv;

    if (aContextId == 0)
    {
        aContext.mPrefix = GetNetif().GetMle().GetMeshLocalPrefix();
        aContext.mPrefixLength = 64;
        aContext.mContextId = 0;
        aContext.mCompressFlag = true;
        ExitNow(error = OT_ERROR_NONE);
    }

    for (NetworkDataTlv *cur = reinterpret_cast<NetworkDataTlv *>(mTlvs);
         cur < reinterpret_cast<NetworkDataTlv *>(mTlvs + mLength);
         cur = cur->GetNext())
    {
        if (cur->GetType() != NetworkDataTlv::kTypePrefix)
        {
            continue;
        }

        prefix = static_cast<PrefixTlv *>(cur);
        contextTlv = FindContext(*prefix);

        if (contextTlv == NULL)
        {
            continue;
        }

        if (contextTlv->GetContextId() != aContextId)
        {
            continue;
        }

        aContext.mPrefix = prefix->GetPrefix();
        aContext.mPrefixLength = prefix->GetPrefixLength();
        aContext.mContextId = contextTlv->GetContextId();
        aContext.mCompressFlag = contextTlv->IsCompress();
        ExitNow(error = OT_ERROR_NONE);
    }

exit:
    return error;
}

#if OPENTHREAD_ENABLE_DHCP6_SERVER || OPENTHREAD_ENABLE_DHCP6_CLIENT
otError LeaderBase::GetRlocByContextId(uint8_t aContextId, uint16_t &aRloc16)
{
    otError error = OT_ERROR_NOT_FOUND;
    Lowpan::Context lowpanContext;

    if ((GetContext(aContextId, lowpanContext)) == OT_ERROR_NONE)
    {
        otNetworkDataIterator iterator = OT_NETWORK_DATA_ITERATOR_INIT;
        otBorderRouterConfig config;

        while (GetNextOnMeshPrefix(&iterator, &config) == OT_ERROR_NONE)
        {
            if (otIp6PrefixMatch(&(config.mPrefix.mPrefix),
                                 reinterpret_cast<const otIp6Address *>(lowpanContext.mPrefix)) >= config.mPrefix.mLength)
            {
                aRloc16 = config.mRloc16;
                ExitNow(error = OT_ERROR_NONE);
            }
        }
    }

exit:
    return error;
}
#endif  // OPENTHREAD_ENABLE_DHCP6_SERVER || OPENTHREAD_ENABLE_DHCP6_CLIENT

bool LeaderBase::IsOnMesh(const Ip6::Address &aAddress)
{
    PrefixTlv *prefix;
    bool rval = false;

    if (memcmp(aAddress.mFields.m8, GetNetif().GetMle().GetMeshLocalPrefix(), 8) == 0)
    {
        ExitNow(rval = true);
    }

    for (NetworkDataTlv *cur = reinterpret_cast<NetworkDataTlv *>(mTlvs);
         cur < reinterpret_cast<NetworkDataTlv *>(mTlvs + mLength);
         cur = cur->GetNext())
    {
        if (cur->GetType() != NetworkDataTlv::kTypePrefix)
        {
            continue;
        }

        prefix = static_cast<PrefixTlv *>(cur);

        if (PrefixMatch(prefix->GetPrefix(), aAddress.mFields.m8, prefix->GetPrefixLength()) < 0)
        {
            continue;
        }

        if (FindBorderRouter(*prefix) == NULL)
        {
            continue;
        }

        ExitNow(rval = true);
    }

exit:
    return rval;
}

otError LeaderBase::RouteLookup(const Ip6::Address &aSource, const Ip6::Address &aDestination,
                                uint8_t *aPrefixMatch, uint16_t *aRloc16)
{
    otError error = OT_ERROR_NO_ROUTE;
    PrefixTlv *prefix;

    for (NetworkDataTlv *cur = reinterpret_cast<NetworkDataTlv *>(mTlvs);
         cur < reinterpret_cast<NetworkDataTlv *>(mTlvs + mLength);
         cur = cur->GetNext())
    {
        if (cur->GetType() != NetworkDataTlv::kTypePrefix)
        {
            continue;
        }

        prefix = static_cast<PrefixTlv *>(cur);

        if (PrefixMatch(prefix->GetPrefix(), aSource.mFields.m8, prefix->GetPrefixLength()) >= 0)
        {
            if (ExternalRouteLookup(prefix->GetDomainId(), aDestination, aPrefixMatch, aRloc16) == OT_ERROR_NONE)
            {
                ExitNow(error = OT_ERROR_NONE);
            }

            if (DefaultRouteLookup(*prefix, aRloc16) == OT_ERROR_NONE)
            {
                if (aPrefixMatch)
                {
                    *aPrefixMatch = 0;
                }

                ExitNow(error = OT_ERROR_NONE);
            }
        }
    }

exit:
    return error;
}

otError LeaderBase::ExternalRouteLookup(uint8_t aDomainId, const Ip6::Address &aDestination,
                                        uint8_t *aPrefixMatch, uint16_t *aRloc16)
{
    ThreadNetif &netif = GetNetif();
    otError error = OT_ERROR_NO_ROUTE;
    PrefixTlv *prefix;
    HasRouteTlv *hasRoute;
    HasRouteEntry *entry;
    HasRouteEntry *rvalRoute = NULL;
    uint8_t rval_plen = 0;
    int8_t plen;
    NetworkDataTlv *cur;
    NetworkDataTlv *subCur;

    for (cur = reinterpret_cast<NetworkDataTlv *>(mTlvs);
         cur < reinterpret_cast<NetworkDataTlv *>(mTlvs + mLength);
         cur = cur->GetNext())
    {
        if (cur->GetType() != NetworkDataTlv::kTypePrefix)
        {
            continue;
        }

        prefix = static_cast<PrefixTlv *>(cur);

        if (prefix->GetDomainId() != aDomainId)
        {
            continue;
        }

        plen = PrefixMatch(prefix->GetPrefix(), aDestination.mFields.m8, prefix->GetPrefixLength());

        if (plen > rval_plen)
        {
            // select border router
            for (subCur = prefix->GetSubTlvs(); subCur < prefix->GetNext(); subCur = subCur->GetNext())
            {
                if (subCur->GetType() != NetworkDataTlv::kTypeHasRoute)
                {
                    continue;
                }

                hasRoute = static_cast<HasRouteTlv *>(subCur);

                for (uint8_t i = 0; i < hasRoute->GetNumEntries(); i++)
                {
                    entry = hasRoute->GetEntry(i);

                    if (rvalRoute == NULL ||
                        entry->GetPreference() > rvalRoute->GetPreference() ||
                        (entry->GetPreference() == rvalRoute->GetPreference() &&
                         (entry->GetRloc() == netif.GetMle().GetRloc16() ||
                          (rvalRoute->GetRloc() != netif.GetMle().GetRloc16() &&
                           netif.GetMle().GetCost(entry->GetRloc()) < netif.GetMle().GetCost(rvalRoute->GetRloc())))))
                    {
                        rvalRoute = entry;
                        rval_plen = static_cast<uint8_t>(plen);
                    }
                }

            }
        }
    }

    if (rvalRoute != NULL)
    {
        if (aRloc16 != NULL)
        {
            *aRloc16 = rvalRoute->GetRloc();
        }

        if (aPrefixMatch != NULL)
        {
            *aPrefixMatch = rval_plen;
        }

        error = OT_ERROR_NONE;
    }

    return error;
}

otError LeaderBase::DefaultRouteLookup(PrefixTlv &aPrefix, uint16_t *aRloc16)
{
    ThreadNetif &netif = GetNetif();
    otError error = OT_ERROR_NO_ROUTE;
    BorderRouterTlv *borderRouter;
    BorderRouterEntry *entry;
    BorderRouterEntry *route = NULL;

    for (NetworkDataTlv *cur = aPrefix.GetSubTlvs(); cur < aPrefix.GetNext(); cur = cur->GetNext())
    {
        if (cur->GetType() != NetworkDataTlv::kTypeBorderRouter)
        {
            continue;
        }

        borderRouter = static_cast<BorderRouterTlv *>(cur);

        for (uint8_t i = 0; i < borderRouter->GetNumEntries(); i++)
        {
            entry = borderRouter->GetEntry(i);

            if (entry->IsDefaultRoute() == false)
            {
                continue;
            }

            if (route == NULL ||
                entry->GetPreference() > route->GetPreference() ||
                (entry->GetPreference() == route->GetPreference() &&
                 (entry->GetRloc() == netif.GetMle().GetRloc16() ||
                  (route->GetRloc() != netif.GetMle().GetRloc16() &&
                   netif.GetMle().GetCost(entry->GetRloc()) < netif.GetMle().GetCost(route->GetRloc())))))
            {
                route = entry;
            }
        }
    }

    if (route != NULL)
    {
        if (aRloc16 != NULL)
        {
            *aRloc16 = route->GetRloc();
        }

        error = OT_ERROR_NONE;
    }

    return error;
}

void LeaderBase::SetNetworkData(uint8_t aVersion, uint8_t aStableVersion, bool aStable,
                                const uint8_t *aData, uint8_t aDataLength)
{
    mVersion = aVersion;
    mStableVersion = aStableVersion;
    memcpy(mTlvs, aData, aDataLength);
    mLength = aDataLength;

    if (aStable)
    {
        RemoveTemporaryData(mTlvs, mLength);
    }

    otDumpDebgNetData(GetInstance(), "set network data", mTlvs, mLength);

    GetNetif().SetStateChangedFlags(OT_CHANGED_THREAD_NETDATA);
}

otError LeaderBase::SetCommissioningData(const uint8_t *aValue, uint8_t aValueLength)
{
    otError error = OT_ERROR_NONE;
    uint8_t remaining = kMaxSize - mLength;
    CommissioningDataTlv *commissioningDataTlv;

    VerifyOrExit(sizeof(NetworkDataTlv) + aValueLength < remaining, error = OT_ERROR_NO_BUFS);

    RemoveCommissioningData();

    if (aValueLength > 0)
    {
        commissioningDataTlv = reinterpret_cast<CommissioningDataTlv *>(mTlvs + mLength);
        Insert(reinterpret_cast<uint8_t *>(commissioningDataTlv), sizeof(CommissioningDataTlv) + aValueLength);
        commissioningDataTlv->Init();
        commissioningDataTlv->SetLength(aValueLength);
        memcpy(commissioningDataTlv->GetValue(), aValue, aValueLength);
    }

    mVersion++;
    GetNetif().SetStateChangedFlags(OT_CHANGED_THREAD_NETDATA);

exit:
    return error;
}

NetworkDataTlv *LeaderBase::GetCommissioningData(void)
{
    NetworkDataTlv *cur = reinterpret_cast<NetworkDataTlv *>(mTlvs);
    NetworkDataTlv *end = reinterpret_cast<NetworkDataTlv *>(mTlvs + mLength);

    for (; cur < end; cur = cur->GetNext())
    {
        if (cur->GetType() == NetworkDataTlv::kTypeCommissioningData)
        {
            ExitNow();
        }
    }

    cur = NULL;

exit:
    return cur;
}

MeshCoP::Tlv *LeaderBase::GetCommissioningDataSubTlv(MeshCoP::Tlv::Type aType)
{
    MeshCoP::Tlv *rval = NULL;
    NetworkDataTlv *commissioningDataTlv;
    MeshCoP::Tlv *cur;
    MeshCoP::Tlv *end;

    commissioningDataTlv = GetCommissioningData();
    VerifyOrExit(commissioningDataTlv != NULL);

    cur = reinterpret_cast<MeshCoP::Tlv *>(commissioningDataTlv->GetValue());
    end = reinterpret_cast<MeshCoP::Tlv *>(commissioningDataTlv->GetValue() + commissioningDataTlv->GetLength());

    for (; cur < end; cur = cur->GetNext())
    {
        if (cur->GetType() == aType)
        {
            ExitNow(rval = cur);
        }
    }

exit:
    return rval;
}

bool LeaderBase::IsJoiningEnabled(void)
{
    MeshCoP::Tlv *steeringData;
    bool rval = false;

    VerifyOrExit(GetCommissioningDataSubTlv(MeshCoP::Tlv::kBorderAgentLocator) != NULL);

    steeringData = GetCommissioningDataSubTlv(MeshCoP::Tlv::kSteeringData);
    VerifyOrExit(steeringData != NULL);

    for (int i = 0; i < steeringData->GetLength(); i++)
    {
        if (steeringData->GetValue()[i] != 0)
        {
            ExitNow(rval = true);
        }
    }

exit:
    return rval;
}

otError LeaderBase::RemoveCommissioningData(void)
{
    otError error = OT_ERROR_NOT_FOUND;

    for (NetworkDataTlv *cur = reinterpret_cast<NetworkDataTlv *>(mTlvs);
         cur < reinterpret_cast<NetworkDataTlv *>(mTlvs + mLength);
         cur = cur->GetNext())
    {
        if (cur->GetType() == NetworkDataTlv::kTypeCommissioningData)
        {
            Remove(reinterpret_cast<uint8_t *>(cur), sizeof(NetworkDataTlv) + cur->GetLength());
            ExitNow(error = OT_ERROR_NONE);
        }
    }

exit:
    return error;
}

}  // namespace NetworkData
}  // namespace ot
