/*
 *
 *    Copyright (c) 2022 Project CHIP Authors
 *
 *    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.
 */

#pragma once

#include <lib/support/BitFlags.h>

namespace chip {

/**
 * Stores bit masks and flags in a more typesafe manner.
 *
 * Extends BitFlags for boolean flags and also adds support for bit-mask set options.
 *
 */
template <typename FlagsEnum, typename StorageType = typename std::underlying_type_t<FlagsEnum>>
class BitMask : public BitFlags<FlagsEnum, StorageType>
{
public:
    using IntegerType = typename BitFlags<FlagsEnum, StorageType>::IntegerType;

    BitMask() : BitFlags<FlagsEnum, StorageType>() {}
    BitMask(const BitFlags<FlagsEnum, StorageType> & other) : BitFlags<FlagsEnum, StorageType>(other) {}
    BitMask(BitFlags<FlagsEnum, StorageType> && other) : BitFlags<FlagsEnum, StorageType>(std::move(other)) {}
    BitMask(const BitMask &) = default;

    explicit BitMask(FlagsEnum value) : BitFlags<FlagsEnum, StorageType>(value) {}
    explicit BitMask(IntegerType value) : BitFlags<FlagsEnum, StorageType>(value) {}

    template <typename... Args>
    BitMask(FlagsEnum flag, Args &&... args) : BitFlags<FlagsEnum, StorageType>(flag, std::forward<Args>(args)...)
    {}

    template <typename... Args>
    BitMask(IntegerType value, Args &&... args) : BitFlags<FlagsEnum, StorageType>(value, std::forward<Args>(args)...)
    {}

    BitMask & operator=(const BitMask &) = default;

    BitMask & operator=(const BitFlags<FlagsEnum, StorageType> & other)
    {
        BitFlags<FlagsEnum, StorageType>::SetRaw(other.Raw());
        return *this;
    }

    BitMask & operator=(FlagsEnum value)
    {
        BitFlags<FlagsEnum, StorageType>::SetRaw(static_cast<StorageType>(value));
        return *this;
    }

    /**
     * Set a field within the bit mask integer.
     *
     * Fields are assumed to be contiguous bits within the underlying integer, for example:
     * A mask of 0x70 == 0b01110000 means that a 3 bit value is encoded at bits [4;6].
     *
     * Calling SetField(0x70, n) is equivalent to "(value & ~0x70) | (n << 4)"
     *
     * @param mask  The mask, code assumes a continous bit mask
     * @param value The value, NOT shifted, MUST fit within the number of bits of the mask
     */
    constexpr BitMask & SetField(FlagsEnum mask, IntegerType value)
    {
        IntegerType bitMask = static_cast<IntegerType>(mask);
        IntegerType shift   = GetShiftToFirstSetBit(bitMask);

        // NOTE: value should be fully contained within the shift mask.
        //
        // assert((value & (mask >> shift)) == value);

        // Clear bits overlayed by the mask
        IntegerType updated = static_cast<IntegerType>(BitFlags<FlagsEnum, StorageType>::Raw() & ~bitMask);

        // Set the right bits
        updated |= static_cast<IntegerType>(bitMask & (value << shift));

        BitFlags<FlagsEnum, StorageType>::SetRaw(updated);

        return *this;
    }

    /**
     * Gets an underlying field that is contained within a bit subset of the integer.
     * Examples:
     *    GetField(0x70) == GetField(0b01110000) == ((n & 0x70) >> 4) == ((n >> 4) 0x07)
     *    GetField(0xC0) == GetField(0b11000000) == ((n & 0xC0) >> 6) == ((n >> 6) 0x03)
     *
     * @param mask The bit mask to be used, assumed to be a contigous bit mask
     */
    IntegerType GetField(FlagsEnum mask) const
    {
        IntegerType bitMask = static_cast<IntegerType>(mask);
        IntegerType shift   = GetShiftToFirstSetBit(bitMask);

        // Forward the right bits
        return static_cast<IntegerType>(((BitFlags<FlagsEnum, StorageType>::Raw() & bitMask) >> shift));
    }

protected:
    /// Get the shift amount to reach the first non-zero bit in a bitmask
    ///
    /// Examples:
    ///    GetShiftToFirstSetBit(0b0000001) == 0
    ///    GetShiftToFirstSetBit(0b0011100) == 2
    ///    GetShiftToFirstSetBit(0b0110000) == 4
    ///
    /// Note: This does NOT validate if the given mask is a valid mask. So:
    ///    GetShiftToFirstSetBit(0b0100010) == 1
    ///    GetShiftToFirstSetBit(0b010110100) == 2
    static constexpr IntegerType GetShiftToFirstSetBit(IntegerType bitMask)
    {
        IntegerType count = 0;
        IntegerType mask  = 0x01;

        if (bitMask == 0)
        {
            return sizeof(bitMask); // generally invalid value
        }

        while ((mask & bitMask) == 0)
        {
            mask = static_cast<IntegerType>(mask << 1);
            count++;
        }
        return count;
    }
};

} // namespace chip
