/*
 *  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 MAC Channel Mask
 */

#ifndef MAC_CHANNEL_MASK_HPP_
#define MAC_CHANNEL_MASK_HPP_

#include "openthread-core-config.h"

#include <limits.h>
#include <openthread/platform/radio.h>

#include "common/equatable.hpp"
#include "common/string.hpp"
#include "radio/radio.hpp"

namespace ot {
namespace Mac {

/**
 * @addtogroup core-mac
 *
 * @brief
 *   This module includes definitions for MAC Channel Mask.
 *
 * @{
 *
 */

/**
 * This class defines a channel mask.
 *
 * It is a wrapper class around a `uint32_t` bit vector representing a set of channels.
 *
 */
class ChannelMask : public Unequatable<ChannelMask>
{
public:
    /**
     * This constant specifies the value to pass in `GetNextChannel()` to get the first channel in the mask.
     *
     */
    static constexpr uint8_t kChannelIteratorFirst = 0xff;

    static constexpr uint16_t kInfoStringSize = 45; ///< Recommended buffer size to use with `ToString()`.

    /**
     * This type defines the fixed-length `String` object returned from `ToString()`.
     *
     */
    typedef String<kInfoStringSize> InfoString;

    /**
     * This constructor initializes a `ChannelMask` instance.
     *
     */
    ChannelMask(void)
        : mMask(0)
    {
    }

    /**
     * This constructor initializes a `ChannelMask` instance with a given mask.
     *
     * @param[in]  aMask   A channel mask (as a `uint32_t` bit-vector mask with bit 0 (lsb) -> channel 0, and so on).
     *
     */
    explicit ChannelMask(uint32_t aMask)
        : mMask(aMask)
    {
    }

    /**
     * This method clears the channel mask.
     *
     */
    void Clear(void) { mMask = 0; }

    /**
     * This method gets the channel mask (as a `uint32_t` bit-vector mask with bit 0 (lsb) -> channel 0, and so on).
     *
     * @returns The channel mask.
     *
     */
    uint32_t GetMask(void) const { return mMask; }

    /**
     * This method sets the channel mask.
     *
     * @param[in]  aMask   A channel mask (as a `uint32_t` bit-vector mask with bit 0 (lsb) -> channel 0, and so on).
     *
     */
    void SetMask(uint32_t aMask) { mMask = aMask; }

    /**
     * This method indicates if the mask is empty.
     *
     * @returns TRUE if the mask is empty, FALSE otherwise.
     *
     */
    bool IsEmpty(void) const { return (mMask == 0); }

    /**
     * This method indicates if the mask contains only a single channel.
     *
     * @returns TRUE if channel mask contains a single channel, FALSE otherwise
     *
     */
    bool IsSingleChannel(void) const { return ((mMask != 0) && ((mMask & (mMask - 1)) == 0)); }

    /**
     * This method indicates if the mask contains a given channel.
     *
     * @param[in]  aChannel  A channel.
     *
     * @returns TRUE if the channel @p aChannel is included in the mask, FALSE otherwise.
     *
     */
    bool ContainsChannel(uint8_t aChannel) const
    {
        return (aChannel < sizeof(mMask) * CHAR_BIT) ? ((1UL << aChannel) & mMask) != 0 : false;
    }

    /**
     * This method adds a channel to the channel mask.
     *
     * @param[in]  aChannel  A channel
     *
     */
    void AddChannel(uint8_t aChannel)
    {
        if (aChannel < sizeof(mMask) * CHAR_BIT)
        {
            mMask |= (1UL << aChannel);
        }
    }

    /**
     * This method removes a channel from the channel mask.
     *
     * @param[in]  aChannel  A channel
     *
     */
    void RemoveChannel(uint8_t aChannel)
    {
        if (aChannel < sizeof(mMask) * CHAR_BIT)
        {
            mMask &= ~(1UL << aChannel);
        }
    }

    /**
     * This method updates the channel mask by intersecting it with another mask.
     *
     * @param[in]  aOtherMask  Another channel mask.
     *
     */
    void Intersect(const ChannelMask &aOtherMask) { mMask &= aOtherMask.mMask; }

    /**
     * This method returns the number of channels in the mask.
     *
     * @returns Number of channels in the mask.
     *
     */
    uint8_t GetNumberOfChannels(void) const;

    /**
     * This method gets the next channel in the channel mask.
     *
     * This method can be used to iterate over all channels in the channel mask. To get the first channel (channel with
     * lowest number) in the mask the @p aChannel should be set to `kChannelIteratorFirst`.
     *
     * @param[in,out] aChannel       A reference to a `uint8_t`.
     *                               On entry it should contain the previous channel or `kChannelIteratorFirst`.
     *                               On exit it contains the next channel.
     *
     * @retval  kErrorNone       Got the next channel, @p aChannel updated successfully.
     * @retval  kErrorNotFound   No next channel in the channel mask (note: @p aChannel may be changed).
     *
     */
    Error GetNextChannel(uint8_t &aChannel) const;

    /**
     * This method randomly chooses a channel from the channel mask.
     *
     * @returns A randomly chosen channel from the given mask, or `kChannelIteratorFirst` if the mask is empty.
     *
     */
    uint8_t ChooseRandomChannel(void) const;

    /**
     * This method overloads `==` operator to indicate whether two masks are equal.
     *
     * @param[in] aAnother   A reference to another mask to compare with the current one.
     *
     * @returns TRUE if the two masks are equal, FALSE otherwise.
     *
     */
    bool operator==(const ChannelMask &aAnother) const { return (mMask == aAnother.mMask); }

    /**
     * This method converts the channel mask into a human-readable string.
     *
     * Examples of possible output:
     *  -  empty mask      ->  "{ }"
     *  -  all channels    ->  "{ 11-26 }"
     *  -  single channel  ->  "{ 20 }"
     *  -  multiple ranges ->  "{ 11, 14-17, 20-22, 24, 25 }"
     *  -  no range        ->  "{ 14, 21, 26 }"
     *
     * @returns  An `InfoString` object representing the channel mask.
     *
     */
    InfoString ToString(void) const;

private:
    static_assert((Radio::kChannelMin < 32) && (Radio::kChannelMax < 32),
                  "The channel number is larger than 32. `ChannelMask` uses 32 bit mask.");
    uint32_t mMask;
};

/**
 * @}
 *
 */

} // namespace Mac
} // namespace ot

#endif // MAC_CHANNEL_MASK_HPP_
