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

#include "test_platform.h"

#include <openthread/config.h>

#include "test_util.h"
#include "common/code_utils.hpp"
#include "common/instance.hpp"
#include "thread/child.hpp"

namespace ot {

static ot::Instance *sInstance;

enum
{
    kMaxChildIp6Addresses = OPENTHREAD_CONFIG_MLE_IP_ADDRS_PER_CHILD,
};

void VerifyChildIp6Addresses(const Child &aChild, uint8_t aAddressListLength, const Ip6::Address aAddressList[])
{
    Ip6::Address::TypeFilter filters[] = {Ip6::Address::kTypeUnicast, Ip6::Address::kTypeMulticast};
    bool                     addressObserved[kMaxChildIp6Addresses];
    bool                     hasMeshLocal = false;

    for (uint8_t index = 0; index < aAddressListLength; index++)
    {
        VerifyOrQuit(aChild.HasIp6Address(aAddressList[index]));
    }

    memset(addressObserved, 0, sizeof(addressObserved));

    for (const Ip6::Address &address : aChild.IterateIp6Addresses())
    {
        bool addressIsInList = false;

        for (uint8_t index = 0; index < aAddressListLength; index++)
        {
            if (address == aAddressList[index])
            {
                addressIsInList        = true;
                addressObserved[index] = true;
                break;
            }
        }

        VerifyOrQuit(addressIsInList, "Child::IterateIp6Addresses() returned an address not in the expected list");
    }

    for (uint8_t index = 0; index < aAddressListLength; index++)
    {
        Ip6::Address address;

        VerifyOrQuit(addressObserved[index], "Child::IterateIp6Addresses() missed an entry from the expected list");

        if (sInstance->Get<Mle::MleRouter>().IsMeshLocalAddress(aAddressList[index]))
        {
            SuccessOrQuit(aChild.GetMeshLocalIp6Address(address));
            VerifyOrQuit(address == aAddressList[index], "GetMeshLocalIp6Address() did not return expected address");
            hasMeshLocal = true;
        }
    }

    if (!hasMeshLocal)
    {
        Ip6::Address address;

        VerifyOrQuit(aChild.GetMeshLocalIp6Address(address) == kErrorNotFound,
                     "Child::GetMeshLocalIp6Address() returned an address not in the expected list");
    }

    // Iterate over unicast and multicast addresses separately.

    memset(addressObserved, 0, sizeof(addressObserved));

    for (Ip6::Address::TypeFilter filter : filters)
    {
        for (const Ip6::Address &address : aChild.IterateIp6Addresses(filter))
        {
            bool addressIsInList = false;

            switch (filter)
            {
            case Ip6::Address::kTypeMulticast:
                VerifyOrQuit(address.IsMulticast(), "Address::TypeFilter failed");
                break;

            case Ip6::Address::kTypeUnicast:
                VerifyOrQuit(!address.IsMulticast(), "Address::TypeFilter failed");
                break;

            default:
                break;
            }

            VerifyOrQuit(address.MatchesFilter(filter));

            for (uint8_t index = 0; index < aAddressListLength; index++)
            {
                if (address == aAddressList[index])
                {
                    VerifyOrQuit(addressObserved[index] == false,
                                 "Child::IterateIp6Addresses() returned duplicate addr");
                    addressObserved[index] = true;
                    addressIsInList        = true;
                    break;
                }
            }

            VerifyOrQuit(addressIsInList, "Child::IterateIp6Addresses() returned an address not in the expected list");
        }
    }

    for (uint8_t index = 0; index < aAddressListLength; index++)
    {
        VerifyOrQuit(addressObserved[index], "Child::IterateIp6Addresses() missed an entry from the expected list");
    }

    // Verify behavior of `Child::AddressIterator
    {
        Child::AddressIterator        iter1(aChild);
        Child::AddressIterator        iter2(aChild);
        Child::AddressIterator::Index iterIndex;

        for (const Ip6::Address &address : aChild.IterateIp6Addresses())
        {
            VerifyOrQuit(iter1 == iter2);
            VerifyOrQuit(!iter1.IsDone());
            VerifyOrQuit(*iter1.GetAddress() == address);
            VerifyOrQuit(*iter1.GetAddress() == *iter2.GetAddress());

            iterIndex = iter1.GetAsIndex();
            VerifyOrQuit(iter2.GetAsIndex() == iterIndex);

            {
                Child::AddressIterator iter3(aChild, iterIndex);
                VerifyOrQuit(iter3 == iter1, "AddressIterator(iterIndex) failed");

                iter3++;
                VerifyOrQuit(iter3 != iter1, "AddressIterator(iterIndex) failed");
            }

            iter1++;
            VerifyOrQuit(iter1 != iter2);
            iter2++;
        }

        VerifyOrQuit(iter1.IsDone());
        VerifyOrQuit(iter2.IsDone());
        VerifyOrQuit(iter1 == iter2);

        iterIndex = iter1.GetAsIndex();
        VerifyOrQuit(iter2.GetAsIndex() == iterIndex);

        {
            Child::AddressIterator iter3(aChild, iterIndex);
            VerifyOrQuit(iter3 == iter1, "AddressIterator(iterIndex) failed");
        }
    }
}

void TestChildIp6Address(void)
{
    Child        child;
    Ip6::Address addresses[kMaxChildIp6Addresses];
    uint8_t      numAddresses;
    const char  *ip6Addresses[] = {
         "fd00:1234::1234",
         "ff6b:e251:52fb:0:12e6:b94c:1c28:c56a",
         "fd00:1234::204c:3d7c:98f6:9a1b",
    };

    const uint8_t            meshLocalIidArray[] = {0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77, 0x88};
    Ip6::InterfaceIdentifier meshLocalIid;

    meshLocalIid.SetBytes(meshLocalIidArray);

    sInstance = testInitInstance();
    VerifyOrQuit(sInstance != nullptr);

    child.Init(*sInstance);

    //- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -

    printf("\nConverting IPv6 addresses from string");

    numAddresses = 0;

    // First addresses uses the mesh local prefix (mesh-local address).
    addresses[numAddresses] = sInstance->Get<Mle::MleRouter>().GetMeshLocal64();
    addresses[numAddresses].SetIid(meshLocalIid);

    numAddresses++;

    for (const char *ip6Address : ip6Addresses)
    {
        VerifyOrQuit(numAddresses < kMaxChildIp6Addresses, "Too many IPv6 addresses in the unit test");
        SuccessOrQuit(addresses[numAddresses++].FromString(ip6Address));
    }

    printf(" -- PASS\n");

    //- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
    printf("Child state after init");
    child.Clear();
    VerifyChildIp6Addresses(child, 0, nullptr);
    printf(" -- PASS\n");

    //- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
    printf("Adding a single IPv6 address");

    for (uint8_t index = 0; index < numAddresses; index++)
    {
        SuccessOrQuit(child.AddIp6Address(addresses[index]));
        VerifyChildIp6Addresses(child, 1, &addresses[index]);

        child.ClearIp6Addresses();
        VerifyChildIp6Addresses(child, 0, nullptr);
    }

    printf(" -- PASS\n");

    //- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
    printf("Adding multiple IPv6 addresses");

    for (uint8_t index = 0; index < numAddresses; index++)
    {
        SuccessOrQuit(child.AddIp6Address(addresses[index]));
        VerifyChildIp6Addresses(child, index + 1, addresses);
    }

    printf(" -- PASS\n");

    //- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
    printf("Checking for failure when adding an address already in list");

    for (uint8_t index = 0; index < numAddresses; index++)
    {
        VerifyOrQuit(child.AddIp6Address(addresses[index]) == kErrorAlready,
                     "AddIp6Address() did not fail when adding same address");
        VerifyChildIp6Addresses(child, numAddresses, addresses);
    }

    printf(" -- PASS\n");

    //- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
    printf("Removing addresses from list starting from front of the list");

    for (uint8_t index = 0; index < numAddresses; index++)
    {
        SuccessOrQuit(child.RemoveIp6Address(addresses[index]));
        VerifyChildIp6Addresses(child, numAddresses - 1 - index, &addresses[index + 1]);

        VerifyOrQuit(child.RemoveIp6Address(addresses[index]) == kErrorNotFound,
                     "RemoveIp6Address() did not fail when removing an address not on the list");
    }

    VerifyChildIp6Addresses(child, 0, nullptr);
    printf(" -- PASS\n");

    //- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
    printf("Removing addresses from list starting from back of the list");

    for (uint8_t index = 0; index < numAddresses; index++)
    {
        SuccessOrQuit(child.AddIp6Address(addresses[index]));
    }

    for (uint8_t index = numAddresses - 1; index > 0; index--)
    {
        SuccessOrQuit(child.RemoveIp6Address(addresses[index]));
        VerifyChildIp6Addresses(child, index, &addresses[0]);

        VerifyOrQuit(child.RemoveIp6Address(addresses[index]) == kErrorNotFound,
                     "RemoveIp6Address() did not fail when removing an address not on the list");
    }

    printf(" -- PASS\n");

    //- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
    printf("Removing address entries from middle of the list");

    for (uint8_t indexToRemove = 1; indexToRemove < numAddresses - 1; indexToRemove++)
    {
        child.ClearIp6Addresses();

        for (uint8_t index = 0; index < numAddresses; index++)
        {
            SuccessOrQuit(child.AddIp6Address(addresses[index]));
        }

        SuccessOrQuit(child.RemoveIp6Address(addresses[indexToRemove]));

        VerifyOrQuit(child.RemoveIp6Address(addresses[indexToRemove]) == kErrorNotFound,
                     "RemoveIp6Address() did not fail when removing an address not on the list");

        {
            Ip6::Address updatedAddressList[kMaxChildIp6Addresses];
            uint8_t      updatedListIndex = 0;

            for (uint8_t index = 0; index < numAddresses; index++)
            {
                if (index != indexToRemove)
                {
                    updatedAddressList[updatedListIndex++] = addresses[index];
                }
            }

            VerifyChildIp6Addresses(child, updatedListIndex, updatedAddressList);
        }
    }

    printf(" -- PASS\n");

    testFreeInstance(sInstance);
}

} // namespace ot

int main(void)
{
    ot::TestChildIp6Address();
    printf("\nAll tests passed.\n");
    return 0;
}
