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


#ifndef ECXX_PLATFORM_X86_LED_SIMULATOR_SDF_2D_H
#define ECXX_PLATFORM_X86_LED_SIMULATOR_SDF_2D_H


namespace eCxx {


//
// Internal helper functions
//
template <typename colorFX2D_T>
static inline SDFFile __beginSDF_2D_RowMajor_impl(
    const char*        fileName,   // Name of the simulation data file
    const colorFX2D_T& colorFX2D,  // ColorFX2D<T> instance that will be used to generate the simulation data
    const char*        colorType,  // Color type
    uint8_t            frameDelay, // Frame delay in multiple of 10 mS
    int16_t            exitDelay   // < 0 : loop mode ; >= 0 : no loop mode with the specified exit delay
)
{
    eCxx::ignoreUnused(colorFX2D);

    return __beginSDF_XD_RowMajor_impl(
        fileName,
        colorFX2D_T::XElementCount,
        colorFX2D_T::YElementCount,
        colorType,
        frameDelay,
        exitDelay
    );
}


//
// Helper functions to generate simulation data files for 2-dimensional LED simulation
//
template <typename colorFX2D_T>
static inline SDFFile beginSDF_2D_RowMajor_HSV(
    const char*        fileName,   // Name of the simulation data file
    const colorFX2D_T& colorFX2D,  // ColorFX2D<T> instance that will be used to generate the simulation data
    uint8_t            frameDelay, // Frame delay in multiple of 10 mS
    int16_t            exitDelay   // < 0 : loop mode ; >= 0 : no loop mode with the specified exit delay
)
{ return __beginSDF_2D_RowMajor_impl(fileName, colorFX2D, "HSV", frameDelay, exitDelay); }


template <typename colorFX2D_T>
static inline SDFFile beginSDF_2D_RowMajor_HSL(
    const char*        fileName,   // Name of the simulation data file
    const colorFX2D_T& colorFX2D,  // ColorFX2D<T> instance that will be used to generate the simulation data
    uint8_t            frameDelay, // Frame delay in multiple of 10 mS
    int16_t            exitDelay   // < 0 : loop mode ; >= 0 : no loop mode with the specified exit delay
)
{ return __beginSDF_2D_RowMajor_impl(fileName, colorFX2D, "HSL", frameDelay, exitDelay); }


template <typename colorFX2D_T>
static inline SDFFile beginSDF_2D_RowMajor_W(
    const char*        fileName,   // Name of the simulation data file
    const colorFX2D_T& colorFX2D,  // ColorFX2D<T> instance that will be used to generate the simulation data
    uint8_t            frameDelay, // Frame delay in multiple of 10 mS
    int16_t            exitDelay   // < 0 : loop mode ; >= 0 : no loop mode with the specified exit delay
)
{ return __beginSDF_2D_RowMajor_impl(fileName, colorFX2D, "W", frameDelay, exitDelay); }


template <typename colorFX2D_T>
static inline SDFFile beginSDF_2D_RowMajor_RGB(
    const char*        fileName,   // Name of the simulation data file
    const colorFX2D_T& colorFX2D,  // ColorFX2D<T> instance that will be used to generate the simulation data
    uint8_t            frameDelay, // Frame delay in multiple of 10 mS
    int16_t            exitDelay   // < 0 : loop mode ; >= 0 : no loop mode with the specified exit delay
)
{ return __beginSDF_2D_RowMajor_impl(fileName, colorFX2D, "RGB", frameDelay, exitDelay); }


template <typename colorFX2D_T>
static inline SDFFile beginSDF_2D_RowMajor_RGBW(
    const char*        fileName,   // Name of the simulation data file
    const colorFX2D_T& colorFX2D,  // ColorFX2D<T> instance that will be used to generate the simulation data
    uint8_t            frameDelay, // Frame delay in multiple of 10 mS
    int16_t            exitDelay   // < 0 : loop mode ; >= 0 : no loop mode with the specified exit delay
)
{ return __beginSDF_2D_RowMajor_impl(fileName, colorFX2D, "RGBW", frameDelay, exitDelay); }


template <typename colorFX2D_T>
static inline void writeSDF_2D_HSV(SDFFile h, const colorFX2D_T& colorFX2D)
{
    // Write the frame color data (each line is one pixel)
    for(typename colorFX2D_T::BufferSizeType y = 0; y < colorFX2D_T::YElementCount; ++y) {
        for(typename colorFX2D_T::BufferSizeType x = 0; x < colorFX2D_T::XElementCount; ++x) {
            const HSVColor& color = colorFX2D.getXY(x, y);
            fprintf( h, "%d,%d,%d\n", (int) color.h(), (int) color.s(), (int) color.v() );
        }
    }

    // Add a new line for frame separator
    fprintf( h, "\n" );
}


template <typename colorFX2D_T>
static inline void writeSDF_2D_HSL(SDFFile h, const colorFX2D_T& colorFX2D)
{
    // Write the frame color data (each line is one pixel)
    for(typename colorFX2D_T::BufferSizeType y = 0; y < colorFX2D_T::YElementCount; ++y) {
        for(typename colorFX2D_T::BufferSizeType x = 0; x < colorFX2D_T::XElementCount; ++x) {
            const HSLColor& color = colorFX2D.getXY(x, y);
            fprintf( h, "%d,%d,%d\n", (int) color.h(), (int) color.s(), (int) color.l() );
        }
    }

    // Add a new line for frame separator
    fprintf( h, "\n" );
}


template <typename colorFX2D_T>
static inline void writeSDF_2D_W(SDFFile h, const colorFX2D_T& colorFX2D)
{
    // Write the frame color data (each line is one pixel)
    for(typename colorFX2D_T::BufferSizeType y = 0; y < colorFX2D_T::YElementCount; ++y) {
        for(typename colorFX2D_T::BufferSizeType x = 0; x < colorFX2D_T::XElementCount; ++x) {
            const WColor& color = colorFX2D.getXY(x, y);
            fprintf( h, "%d\n", (int) color.w() );
        }
    }

    // Add a new line for frame separator
    fprintf( h, "\n" );
}


template <typename colorFX2D_T>
static inline void writeSDF_2D_RGB(SDFFile h, const colorFX2D_T& colorFX2D)
{
    // Write the frame color data (each line is one pixel)
    for(typename colorFX2D_T::BufferSizeType y = 0; y < colorFX2D_T::YElementCount; ++y) {
        for(typename colorFX2D_T::BufferSizeType x = 0; x < colorFX2D_T::XElementCount; ++x) {
            const RGBColor& color = colorFX2D.getXY(x, y);
            fprintf( h, "%d,%d,%d\n", (int) color.r(), (int) color.g(), (int) color.b() );
        }
    }

    // Add a new line for frame separator
    fprintf( h, "\n" );
}


template <typename colorFX2D_T>
static inline void writeSDF_2D_RGBW(SDFFile h, const colorFX2D_T& colorFX2D)
{
    // Write the frame color data (each line is one pixel)
    for(typename colorFX2D_T::BufferSizeType y = 0; y < colorFX2D_T::YElementCount; ++y) {
        for(typename colorFX2D_T::BufferSizeType x = 0; x < colorFX2D_T::XElementCount; ++x) {
            const RGBWColor& color = colorFX2D.getXY(x, y);
            fprintf( h, "%d,%d,%d,%d\n", (int) color.r(), (int) color.g(), (int) color.b(), (int) color.w() );
        }
    }

    // Add a new line for frame separator
    fprintf( h, "\n" );
}


} // namespace eCxx


#endif
