/*
 * Copyright (C) 2020-2021 Aloysius Indrayanto
 *
 * This file is part of the eCxx library, see LICENSE file for the license details.
 */


#ifndef ECXX_CTL_GFX_COLOR_GENERATOR_1D_H
#define ECXX_CTL_GFX_COLOR_GENERATOR_1D_H


namespace eCxx {


/*
 * The CRTP base class for all simple color generator classes used by
 * some 1-dimensional animation processor implementations
 *
 * All derived (implementation) classes must implement these member functions:
 *
 *     void reset_impl();
 *
 *     const ColorType generate_impl(
 *         uint8_t id,
 *         bool    state
 *     );
 *
 *     const ColorType generate_impl(
 *         uint8_t id,
 *         uint8_t lerpFactor
 *     );
 *
 *     const ColorType generate_impl(
 *         BufferSizeType elemBeginIdx,
 *         BufferSizeType elemEndIdx,
 *         BufferSizeType elemCurrentIdx,
 *         bool           state
 *     );
 *
 *     const ColorType generate_impl(
 *         BufferSizeType elemBeginIdx,
 *         BufferSizeType elemEndIdx,
 *         BufferSizeType elemCurrentIdx,
 *         uint8_t        lerpFactor
 *     );
 *
 *     CBP::QUInt estimatedTotalAnimationFrameCount_impl() const;
 *
 * NOTE : that estimatedTotalAnimationFrameCount_impl() will only be used in x86 platform to assist
 *        with LED simulation.
 */
template <
    typename ImplementationT,
    typename ColorT,
    typename BufferSizeT
>
class ColorGenerator1D_CRTPBase {
    public:
        using ColorType      = ColorT;
        using BufferSizeType = BufferSizeT;

    public:
        inline ColorGenerator1D_CRTPBase() = default;
        inline ~ColorGenerator1D_CRTPBase() = default;

        inline void reset() __ECXX_ATTR_ALWAYS_INLINE
        { return static_cast<ImplementationT*>(this)->reset_impl(); }

        inline const ColorType generate(
            uint8_t id,
            bool    state
        ) __ECXX_ATTR_ALWAYS_INLINE
        {
            return static_cast<ImplementationT*>(this)->generate_impl(
                id, state
            );
        }

        inline const ColorType generate(
            uint8_t id,
            uint8_t lerpFactor
        ) __ECXX_ATTR_ALWAYS_INLINE
        {
            return static_cast<ImplementationT*>(this)->generate_impl(
                id, lerpFactor
            );
        }

        inline const ColorType generate(
            BufferSizeType elemBeginIdx,
            BufferSizeType elemEndIdx,
            BufferSizeType elemCurrentIdx,
            bool           state
        ) __ECXX_ATTR_ALWAYS_INLINE
        {
            return static_cast<ImplementationT*>(this)->generate_impl(
                elemBeginIdx, elemEndIdx, elemCurrentIdx, state
            );
        }

        inline const ColorType generate(
            BufferSizeType elemBeginIdx,
            BufferSizeType elemEndIdx,
            BufferSizeType elemCurrentIdx,
            uint8_t        lerpFactor
        ) __ECXX_ATTR_ALWAYS_INLINE
        {
            return static_cast<ImplementationT*>(this)->generate_impl(
                elemBeginIdx, elemEndIdx, elemCurrentIdx, lerpFactor
            );
        }

#if defined(__x86_64__) || defined(__i386__)
        // NOTE : Some color generator implementations may require reset() to be
        //        called first for this function to work properly
        inline CBP::QUInt estimatedTotalAnimationFrameCount() const __ECXX_ATTR_ALWAYS_INLINE
        { return static_cast<const ImplementationT*>(this)->estimatedTotalAnimationFrameCount_impl(); }
#endif
};


} // namespace eCxx


#endif
