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


//
// For convenience
//

// Comment this to test without using the convenience shortcut
#define USE_CONVENIENCE_SHORTCUT

static constexpr eCxx::uint8_t LEDCount = 6;

#ifdef USE_CONVENIENCE_SHORTCUT

using CompoundAPA102C = eCxx::ColorAnimator1D_APA102C<eCxx::XBGRColor, PIN_DATA, PIN_CLOCK, 2000000UL, 1, LEDCount>;

#else

using ColorType       = eCxx::XBGRColor          <eCxx::APA102XPolicy>;
using ColorFX1DType   = eCxx::ColorFX1D          <ColorType, LEDCount, eCxx::CBP::RawBuffer>;
using ColorAnim1DType = eCxx::ColorAnimator1D    <1, ColorFX1DType>;
using APA102CDriver   = eCxx::GenericSPILEDDriver<LEDCount, PIN_DATA, PIN_CLOCK, 2000000UL, ColorFX1DType>;

#endif


//
// Instantiate the APA102C driver, color effect buffer, animator, and procedure
//
#ifdef USE_CONVENIENCE_SHORTCUT

using ChaserProc = eCxx::Animation1DProc_Chaser<CompoundAPA102C::ColorAnimator1DType>;

static CompoundAPA102C compoundAPA102C;

#else

using ChaserProc = eCxx::Animation1DProc_Chaser<ColorAnim1DType>;

static APA102CDriver   apa102c;

static ColorFX1DType   colorFX1D;
static ColorAnim1DType colorAnim1D(colorFX1D);

#endif

static const eCxx::uint8_t brightValue = eCxx::cie1931lut58(8);
static const eCxx::uint8_t dimValue    = eCxx::cie1931lut58(3);

static ChaserProc chaserProc(
    ChaserProc::Mode::LightBouncing,
    eCxx::RGBColor(0,           0,           0          ),
    eCxx::RGBColor(dimValue,    dimValue,    dimValue   ),
    eCxx::RGBColor(brightValue, brightValue, brightValue)
);


//
// Helper functions
//
static void eCxx_user_init_initializeAnimationAndDriver()
{
    // Initialize the animator
#ifdef USE_CONVENIENCE_SHORTCUT
    compoundAPA102C.colorAnim1D[0].initSegment(0, chaserProc);
#else
    colorAnim1D.initSegment(0, chaserProc);
    colorAnim1D.reset();
#endif

    // Initialize the driver and update the APA102C for the first time (turn off all LEDs)
#ifdef USE_CONVENIENCE_SHORTCUT
    compoundAPA102C.begin();
#else
    apa102c.begin(colorFX1D);
    apa102c.update();
#endif
}


static void eCxx_user_task_updateAnimation()
{
    // Process event and delay
    static eCxx::uint32_t prvMillis = 0;
           eCxx::uint32_t curMillis = App::processEvent();
    if(curMillis - prvMillis < 100) return;
    else                            prvMillis = curMillis;

    // Update the APA102C animation
#ifdef USE_CONVENIENCE_SHORTCUT
    compoundAPA102C.update();
#else
    colorAnim1D.update();
    apa102c.update();
#endif
}
