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

/**
 * @file
 *   This file includes definitions for Thread child table.
 */

#ifndef CHILD_TABLE_HPP_
#define CHILD_TABLE_HPP_

#include "openthread-core-config.h"

#include "common/locator.hpp"
#include "thread/topology.hpp"

namespace ot {

#if OPENTHREAD_FTD

/**
 * This class represents the Thread child table.
 *
 */
class ChildTable : public InstanceLocator
{
public:
    /**
     * This enumeration defines child state filters used for finding a child or iterating through the child table.
     *
     * Each filter definition accepts a subset of `Child:State` values.
     *
     */
    enum StateFilter
    {
        kInStateValid,                     ///< Accept child only in `Child::kStateValid`.
        kInStateValidOrRestoring,          ///< Accept child with `Child::IsStateValidOrRestoring()` being `true`.
        kInStateChildIdRequest,            ///< Accept child only in `Child:kStateChildIdRequest`.
        kInStateValidOrAttaching,          ///< Accept child with `Child::IsStateValidOrAttaching()` being `true`.
        kInStateAnyExceptInvalid,          ///< Accept child in any state except `Child:kStateInvalid`.
        kInStateAnyExceptValidOrRestoring, ///< Accept child in any state except `Child::IsStateValidOrRestoring()`.
    };

    /**
     * This class represents an iterator for iterating through the child entries in the child table.
     *
     */
    class Iterator : public InstanceLocator
    {
    public:
        /**
         * This constructor initializes an `Iterator` instance to start from beginning of the child table.
         *
         * @param[in] aInstance  A reference to the OpenThread instance.
         * @param[in] aFilter    A child state filter.
         *
         */
        Iterator(Instance &aInstance, StateFilter aFilter);

        /**
         * This constructor initializes an `Iterator` instance to start from a given child.
         *
         * This constructor allows the iterator to start from a given `Child` entry. The iterator will start from the
         * given child and will go through all entries in the child table (matching the filter) till it gets back to
         * the starting `Child` entry.
         *
         * If the given starting `Child` pointer is `NULL`, then the iterator starts from beginning of the child table.
         *
         * @param[in] aInstance        A reference to the OpenThread instance.
         * @param[in] aFilter          A child state filter.
         * @param[in] aStartingChild   A pointer to a child. If non-NULL, the iterator starts from the given entry.
         *
         */
        Iterator(Instance &aInstance, StateFilter aFilter, Child *aStartingChild);

        /**
         * This method resets the iterator to start over.
         *
         */
        void Reset(void);

        /**
         * This method indicates whether there are no more `Child` entries in the list (iterator has reached end of
         * the list).
         *
         * @retval TRUE   There are no more entries in the list (reached end of the list).
         * @retval FALSE  The current entry is valid.
         *
         */
        bool IsDone(void) const { return (mChild == NULL); }

        /**
         * This method advances the iterator.
         *
         * The iterator is moved to point to the next `Child` entry matching the given state filter in the constructor.
         * If there are no more `Child` entries matching the given filter, the iterator becomes empty (i.e.,
         * `GetChild()` returns `NULL` and `IsDone()` returns `true`).
         *
         */
        void Advance(void);

        /**
         * This method overloads `++` operator (pre-increment) to advance the iterator.
         *
         * The iterator is moved to point to the next `Child` entry matching the given state filter in the constructor.
         * If there are no more `Child` entries matching the given filter, the iterator becomes empty (i.e.,
         * `GetChild()` returns `NULL` and `IsDone()` returns `true`).
         *
         */
        void operator++(void) { Advance(); }

        /**
         * This method overloads `++` operator (post-increment) to advance the iterator.
         *
         * The iterator is moved to point to the next `Child` entry matching the given state filter in the constructor.
         * If there are no more `Child` entries matching the given filter, the iterator becomes empty (i.e.,
         * `GetChild()` returns `NULL` and `IsDone()` returns `true`).
         *
         */
        void operator++(int) { Advance(); }

        /**
         * This method gets the `Child` entry to which the iterator is currently pointing.
         *
         * @returns A pointer to the `Child` entry, or `NULL` if the iterator is done and/or empty.
         *
         */
        Child *GetChild(void) { return mChild; }

    private:
        StateFilter mFilter;
        Child *     mStart;
        Child *     mChild;
    };

    /**
     * This constructor initializes a `ChildTable` instance.
     *
     * @param[in]  aInstance     A reference to the OpenThread instance.
     *
     */
    explicit ChildTable(Instance &aInstance);

    /**
     * This method clears the child table.
     *
     */
    void Clear(void) { memset(mChildren, 0, sizeof(mChildren)); }

    /**
     * This method returns the child table index for a given `Child` instance.
     *
     * @param[in]  aChild  A reference to a `Child`
     *
     * @returns The index corresponding to @p aChild.
     *
     */
    uint16_t GetChildIndex(const Child &aChild) const { return static_cast<uint16_t>(&aChild - mChildren); }

    /**
     * This method returns a pointer to a `Child` entry at a given index, or `NULL` if the index is out of bounds,
     * i.e., index is larger or equal to maximum number of children allowed (@sa GetMaxChildrenAllowed()).
     *
     * @param[in]  aChildIndex  A child index.
     *
     * @returns A pointer to the `Child` corresponding to the given index, or `NULL` if the index is out of bounds.
     *
     */
    Child *GetChildAtIndex(uint16_t aChildIndex);

    /**
     * This method gets a new/unused `Child` entry from the child table.
     *
     * @note The returned child entry will be cleared (`memset` to zero).
     *
     * @returns A pointer to a new `Child` entry, or `NULL` if all `Child` entries are in use.
     *
     */
    Child *GetNewChild(void);

    /**
     * This method searches the child table for a `Child` with a given RLOC16 also matching a given state filter.
     *
     * @param[in]  aRloc16  A RLOC16 address.
     * @param[in]  aFilter  A child state filter.
     *
     * @returns  A pointer to the `Child` entry if one is found, or `NULL` otherwise.
     *
     */
    Child *FindChild(uint16_t aRloc16, StateFilter aFilter);

    /**
     * This method searches the child table for a `Child` with a given extended address also matching a given state
     * filter.
     *
     * @param[in]  aAddress A reference to an extended address.
     * @param[in]  aFilter  A child state filter.
     *
     * @returns  A pointer to the `Child` entry if one is found, or `NULL` otherwise.
     *
     */
    Child *FindChild(const Mac::ExtAddress &aAddress, StateFilter aFilter);

    /**
     * This method searches the child table for a `Child` with a given address also matching a given state filter.
     *
     * @param[in]  aAddress A reference to a MAC address.
     * @param[in]  aFilter  A child state filter.
     *
     * @returns  A pointer to the `Child` entry if one is found, or `NULL` otherwise.
     *
     */
    Child *FindChild(const Mac::Address &aAddress, StateFilter aFilter);

    /**
     * This method indicates whether the child table contains any child matching a given state filter.
     *
     * @param[in]  aFilter  A child state filter.
     *
     * @returns  TRUE if the table contains at least one child table matching the given filter, FALSE otherwise.
     *
     */
    bool HasChildren(StateFilter aFilter) const;

    /**
     * This method returns the number of children in the child table matching a given state filter.
     *
     * @param[in]  aFilter  A child state filter.
     *
     * @returns Number of children matching the given state filer.
     *
     */
    uint16_t GetNumChildren(StateFilter aFilter) const;

    /**
     * This method returns the maximum number of children that can be supported (build-time constant).
     *
     * @note Number of children allowed (from `GetMaxChildrenAllowed()`) can be less than maximum number of supported
     * children.
     *
     * @returns  The maximum number of children supported
     *
     */
    uint16_t GetMaxChildren(void) const { return kMaxChildren; }

    /**
     * This method get the maximum number of children allowed.
     *
     * @returns  The maximum number of children allowed.
     *
     */
    uint16_t GetMaxChildrenAllowed(void) const { return mMaxChildrenAllowed; }

    /**
     * This method sets the maximum number of children allowed.
     *
     * The number of children allowed must be at least one and at most same as maximum supported children (@sa
     * GetMaxChildren()). It can be changed only if the child table is empty.
     *
     * @param[in]  aMaxChildren  Maximum number of children allowed.
     *
     * @retval OT_ERROR_NONE          The number of allowed children changed successfully.
     * @retval OT_ERROR_INVALID_ARGS  If @p aMaxChildren is not in the range [1, Max supported children].
     * @retval OT_ERROR_INVALID_STATE The child table is not empty.
     *
     */
    otError SetMaxChildrenAllowed(uint16_t aMaxChildren);

private:
    enum
    {
        kMaxChildren = OPENTHREAD_CONFIG_MLE_MAX_CHILDREN,
    };

    static bool MatchesFilter(const Child &aChild, StateFilter aFilter);

    uint16_t mMaxChildrenAllowed;
    Child    mChildren[kMaxChildren];
};

#endif // OPENTHREAD_FTD

#if OPENTHREAD_MTD

class ChildTable : public InstanceLocator
{
public:
    enum StateFilter
    {
        kInStateValid,
        kInStateValidOrRestoring,
        kInStateChildIdRequest,
        kInStateValidOrAttaching,
        kInStateAnyExceptInvalid,
    };

    class Iterator
    {
    public:
        Iterator(Instance &, StateFilter) {}
        Iterator(Instance &, StateFilter, Child *) {}
        void   Reset(void) {}
        bool   IsDone(void) const { return true; }
        void   Advance(void) {}
        void   operator++(void) {}
        void   operator++(int) {}
        Child *GetChild(void) { return NULL; }
    };

    explicit ChildTable(Instance &aInstance)
        : InstanceLocator(aInstance)
    {
    }
    void Clear(void) {}

    uint16_t GetChildIndex(const Child &) const { return 0; }
    Child *  GetChildAtIndex(uint16_t) { return NULL; }

    Child *GetNewChild(void) { return NULL; }

    Child *FindChild(uint16_t, StateFilter) { return NULL; }
    Child *FindChild(const Mac::ExtAddress &, StateFilter) { return NULL; }
    Child *FindChild(const Mac::Address &, StateFilter) { return NULL; }

    bool     HasChildren(StateFilter) const { return false; }
    uint16_t GetNumChildren(StateFilter) const { return 0; }
    uint16_t GetMaxChildren(void) const { return 0; }
    uint16_t GetMaxChildrenAllowed(void) const { return 0; }
    otError  SetMaxChildrenAllowed(uint16_t) { return OT_ERROR_INVALID_STATE; }
};

#endif // OPENTHREAD_MTD

} // namespace ot

#endif // CHILD_TABLE_HPP_
