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


#include <eCxx/eCxx_ColorSpace.h>

#include "TestUtility.h"


//
// Helper functions
//
static void dumpK2RGB(eCxx::uint16_t k)
{
    eCxx::uint8_t r, g, b;

    eCxx::k2rgb(r, g, b, k);

    printf("K(%5d) -> RGB(%3d, %3d, %3d)\n", (int) k, (int) r, (int) g, (int) b);
}


static void dumpHSV2RGB(eCxx::uint16_t h, eCxx::uint8_t s, eCxx::uint8_t v)
{
    eCxx::uint8_t r, g, b;

    eCxx::hsv2rgb(r, g, b, h, s, v);

    printf("HSV(%3d, %3d, %3d) -> RGB(%3d, %3d, %3d)\n", (int) h, (int) s, (int) v, (int) r, (int) g, (int) b);
}


static void dumpHSL2RGB(eCxx::uint16_t h, eCxx::uint8_t s, eCxx::uint8_t l)
{
    eCxx::uint8_t r, g, b;

    eCxx::hsl2rgb(r, g, b, h, s, l);

    printf("HSL(%3d, %3d, %3d) -> RGB(%3d, %3d, %3d)\n", (int) h, (int) s, (int) l, (int) r, (int) g, (int) b);
}


static void dumpRGB2RGBW(eCxx::uint16_t r_, eCxx::uint8_t g_, eCxx::uint8_t b_)
{
    eCxx::uint8_t r, g, b, w;

    eCxx::rgb2rgbw(r, g, b, w, r_, g_, b_);

    printf("RGB(%3d, %3d, %3d) -> RGBW(%3d, %3d, %3d, %3d)\n", (int) r_, (int) g_, (int) b_, (int) r, (int) g, (int) b, (int) w);
}


template <eCxx::uint8_t N>
static void dumpCIE1931LCC(eCxx::CIE1931LVal (&lut)[N], eCxx::uint8_t inb, eCxx::uint8_t outb, eCxx::uint8_t v)
{
    v <<= (8 - inb);

    printf(
        "cie1931lcc%d%d : %3d -> %3d\n",
        (int) inb, (int) outb, (int) v, (int) eCxx::cie1931lcc(lut, v)
    );
}


template <typename ColorT>
static void dumpLERPColor3(const char* cs, const ColorT& from, const ColorT& to, eCxx::uint8_t progressPercent)
{
    ColorT dst;

    eCxx::lerpColor(dst, from, to, progressPercent);
    printf(
        "LERP<ALL> %s(%3d, %3d, %3d) -> %s(%3d, %3d, %3d) [%3d] = %s(%3d, %3d, %3d)\n",
        cs, (int) from.c0, (int) from.c1, (int) from.c2,
        cs, (int) to  .c0, (int) to  .c1, (int) to  .c2,
        (int) progressPercent,
        cs, (int) dst .c0, (int) dst .c1, (int) dst .c2
    );
}


template <eCxx::uint8_t ChannelIndex, typename ColorT>
static void dumpLERPColor3(const char* cs, const ColorT& from, const ColorT& to, eCxx::uint8_t progressPercent)
{
    ColorT dst;

    eCxx::lerpColor<ChannelIndex>(dst, from, to, progressPercent);

    printf(
        "LERP<CH%d> %s(%3d, %3d, %3d) -> %s(%3d, %3d, %3d) [%3d] = %s(%3d, %3d, %3d)\n",
        (int) eCxx::CCI::toPlainIndex<ChannelIndex>::Value,
        cs, (int) from.c0, (int) from.c1, (int) from.c2,
        cs, (int) to  .c0, (int) to  .c1, (int) to  .c2,
        (int) progressPercent,
        cs, (int) dst .c0, (int) dst .c1, (int) dst .c2
    );
}


//
// Test application
//
int main()
{
    // Light types according to https://www.tcpi.com/what-is-lighting-color-temperature
    //           <= 2000K : dim light; close to candlelight
    //     2000K to 3000K : warm light with hints of yellow
    //     3100K to 4500K : bright white light
    //     4600K to 6500K : bright blue-white light; daylight = approximately 5200K
    //           >= 6500K : bright bluish light
    //
    // The results seem to be consistent with the table from https://andi-siess.de/rgb-to-color-temperature
    //
    printf("\n");
    dumpK2RGB( 1000);
    dumpK2RGB( 1500);
    dumpK2RGB( 2000);
    printf("\n");
    dumpK2RGB( 2100);
    dumpK2RGB( 2550);
    dumpK2RGB( 3000);
    printf("\n");
    dumpK2RGB( 3100);
    dumpK2RGB( 3800);
    dumpK2RGB( 4500);
    printf("\n");
    dumpK2RGB( 4600);
    dumpK2RGB( 5550);
    dumpK2RGB( 6500);
    printf("\n");
    dumpK2RGB( 7000);
    dumpK2RGB(10000);
    dumpK2RGB(12000);
    printf("\n");
    dumpK2RGB(15000);
    dumpK2RGB(25000);
    dumpK2RGB(40000);
    printf("\n");
    _DIVIDERLINE_DASHSTR_NL1();

    _DIVIDERLINE_DASHSTR_NL1();
    _DIVIDERLINE_DASHSTR_NL1();



    printf("\n");
    dumpHSV2RGB(  0, 200, 200);
    dumpHSV2RGB( 60, 200, 200);
    dumpHSV2RGB(120, 200, 200);
    dumpHSV2RGB(180, 200, 200);
    dumpHSV2RGB(240, 200, 200);
    dumpHSV2RGB(300, 200, 200);
    printf("\n");
    _DIVIDERLINE_DASHSTR_NL1();

    printf("\n");
    dumpHSV2RGB(  0, 100, 200);
    dumpHSV2RGB( 60, 100, 200);
    dumpHSV2RGB(120, 100, 200);
    dumpHSV2RGB(180, 100, 200);
    dumpHSV2RGB(240, 100, 200);
    dumpHSV2RGB(300, 100, 200);
    printf("\n");
    _DIVIDERLINE_DASHSTR_NL1();

    printf("\n");
    dumpHSV2RGB(  0, 200, 100);
    dumpHSV2RGB( 60, 200, 100);
    dumpHSV2RGB(120, 200, 100);
    dumpHSV2RGB(180, 200, 100);
    dumpHSV2RGB(240, 200, 100);
    dumpHSV2RGB(300, 200, 100);
    printf("\n");
    _DIVIDERLINE_DASHSTR_NL1();

    printf("\n");
    dumpHSV2RGB(  0, 100, 100);
    dumpHSV2RGB( 60, 100, 100);
    dumpHSV2RGB(120, 100, 100);
    dumpHSV2RGB(180, 100, 100);
    dumpHSV2RGB(240, 100, 100);
    dumpHSV2RGB(300, 100, 100);
    printf("\n");
    _DIVIDERLINE_DASHSTR_NL1();

    printf("\n");
    dumpHSV2RGB(  0,   0, 100);
    dumpHSV2RGB( 60,   0, 100);
    dumpHSV2RGB(120,   0, 100);
    dumpHSV2RGB(180,   0, 100);
    dumpHSV2RGB(240,   0, 100);
    dumpHSV2RGB(300,   0, 100);
    printf("\n");
    _DIVIDERLINE_DASHSTR_NL1();

    printf("\n");
    dumpHSV2RGB(  0, 100,   0);
    dumpHSV2RGB( 60, 100,   0);
    dumpHSV2RGB(120, 100,   0);
    dumpHSV2RGB(180, 100,   0);
    dumpHSV2RGB(240, 100,   0);
    dumpHSV2RGB(300, 100,   0);
    printf("\n");
    _DIVIDERLINE_DASHSTR_NL1();

    printf("\n");
    dumpHSV2RGB(  0, 200, 200);
    dumpHSV2RGB( 30, 200, 200);
    dumpHSV2RGB( 60, 200, 200);
    dumpHSV2RGB( 90, 200, 200);
    dumpHSV2RGB(120, 200, 200);
    dumpHSV2RGB(150, 200, 200);
    dumpHSV2RGB(180, 200, 200);
    dumpHSV2RGB(210, 200, 200);
    dumpHSV2RGB(240, 200, 200);
    dumpHSV2RGB(270, 200, 200);
    dumpHSV2RGB(300, 200, 200);
    dumpHSV2RGB(330, 200, 200);
    dumpHSV2RGB(  0, 200, 200);
    printf("\n");
    _DIVIDERLINE_DASHSTR_NL1();

    _DIVIDERLINE_DASHSTR_NL1();
    _DIVIDERLINE_DASHSTR_NL1();



    printf("\n");
    dumpHSL2RGB(  0, 200, 200);
    dumpHSL2RGB( 60, 200, 200);
    dumpHSL2RGB(120, 200, 200);
    dumpHSL2RGB(180, 200, 200);
    dumpHSL2RGB(240, 200, 200);
    dumpHSL2RGB(300, 200, 200);
    printf("\n");
    _DIVIDERLINE_DASHSTR_NL1();

    printf("\n");
    dumpHSL2RGB(  0, 100, 200);
    dumpHSL2RGB( 60, 100, 200);
    dumpHSL2RGB(120, 100, 200);
    dumpHSL2RGB(180, 100, 200);
    dumpHSL2RGB(240, 100, 200);
    dumpHSL2RGB(300, 100, 200);
    printf("\n");
    _DIVIDERLINE_DASHSTR_NL1();

    printf("\n");
    dumpHSL2RGB(  0, 200, 100);
    dumpHSL2RGB( 60, 200, 100);
    dumpHSL2RGB(120, 200, 100);
    dumpHSL2RGB(180, 200, 100);
    dumpHSL2RGB(240, 200, 100);
    dumpHSL2RGB(300, 200, 100);
    printf("\n");
    _DIVIDERLINE_DASHSTR_NL1();

    printf("\n");
    dumpHSL2RGB(  0, 100, 100);
    dumpHSL2RGB( 60, 100, 100);
    dumpHSL2RGB(120, 100, 100);
    dumpHSL2RGB(180, 100, 100);
    dumpHSL2RGB(240, 100, 100);
    dumpHSL2RGB(300, 100, 100);
    printf("\n");
    _DIVIDERLINE_DASHSTR_NL1();

    printf("\n");
    dumpHSL2RGB(  0,   0, 100);
    dumpHSL2RGB( 60,   0, 100);
    dumpHSL2RGB(120,   0, 100);
    dumpHSL2RGB(180,   0, 100);
    dumpHSL2RGB(240,   0, 100);
    dumpHSL2RGB(300,   0, 100);
    printf("\n");
    _DIVIDERLINE_DASHSTR_NL1();

    printf("\n");
    dumpHSL2RGB(  0, 100,   0);
    dumpHSL2RGB( 60, 100,   0);
    dumpHSL2RGB(120, 100,   0);
    dumpHSL2RGB(180, 100,   0);
    dumpHSL2RGB(240, 100,   0);
    dumpHSL2RGB(300, 100,   0);
    printf("\n");
    _DIVIDERLINE_DASHSTR_NL1();

    printf("\n");
    dumpHSL2RGB(  0, 200, 100);
    dumpHSL2RGB( 30, 200, 100);
    dumpHSL2RGB( 60, 200, 100);
    dumpHSL2RGB( 90, 200, 100);
    dumpHSL2RGB(120, 200, 100);
    dumpHSL2RGB(150, 200, 100);
    dumpHSL2RGB(180, 200, 100);
    dumpHSL2RGB(210, 200, 100);
    dumpHSL2RGB(240, 200, 100);
    dumpHSL2RGB(270, 200, 100);
    dumpHSL2RGB(300, 200, 100);
    dumpHSL2RGB(330, 200, 100);
    dumpHSL2RGB(  0, 200, 100);
    printf("\n");
    _DIVIDERLINE_DASHSTR_NL1();

    printf("\n");
    for(eCxx::uint8_t s = 0; s <= 200; s += 25) {
        for(eCxx::uint8_t l = 95; l <= 105; l += 5) {
            dumpHSL2RGB(0, s, l);
        }
        printf("\n");
    }
    printf("\n");
    _DIVIDERLINE_DASHSTR_NL1();

    _DIVIDERLINE_DASHSTR_NL1();
    _DIVIDERLINE_DASHSTR_NL1();



    printf("\n");
    dumpRGB2RGBW(255,   0,   0);
    dumpRGB2RGBW(255, 255,   0);
    dumpRGB2RGBW(  0, 255,   0);
    dumpRGB2RGBW(  0, 255, 255);
    dumpRGB2RGBW(  0,   0, 255);
    dumpRGB2RGBW(255,   0, 255);
    printf("\n");
    dumpRGB2RGBW(255, 127, 127);
    dumpRGB2RGBW(255, 255, 127);
    dumpRGB2RGBW(127, 255, 127);
    dumpRGB2RGBW(127, 255, 255);
    dumpRGB2RGBW(127, 127, 255);
    dumpRGB2RGBW(255, 127, 255);
    printf("\n");
    dumpRGB2RGBW(200,  16,  16);
    dumpRGB2RGBW(200,  32,  16);
    dumpRGB2RGBW(200,  16,  32);
    dumpRGB2RGBW(200,  32,  32);
    dumpRGB2RGBW(200, 200, 200);
    printf("\n");
    _DIVIDERLINE_DASHSTR_NL1();

    _DIVIDERLINE_DASHSTR_NL1();
    _DIVIDERLINE_DASHSTR_NL1();



    printf("\n");
    dumpCIE1931LCC(eCxx::CIE1931L_MSB3_O5, 3, 5, 0);
    dumpCIE1931LCC(eCxx::CIE1931L_MSB3_O5, 3, 5, 5);
    dumpCIE1931LCC(eCxx::CIE1931L_MSB3_O6, 3, 6, 5);
    dumpCIE1931LCC(eCxx::CIE1931L_MSB3_O7, 3, 7, 5);
    dumpCIE1931LCC(eCxx::CIE1931L_MSB3_O8, 3, 8, 5);
    printf("\n");
    dumpCIE1931LCC(eCxx::CIE1931L_MSB4_O7, 4, 7, 5);
    dumpCIE1931LCC(eCxx::CIE1931L_MSB4_O8, 4, 8, 5);
    printf("\n");
    dumpCIE1931LCC(eCxx::CIE1931L_MSB5_O8, 5, 8, 5);
    printf("\n");
    _DIVIDERLINE_DASHSTR_NL1();

    _DIVIDERLINE_DASHSTR_NL1();
    _DIVIDERLINE_DASHSTR_NL1();



    printf("\n");
    eCxx::RGBColor rgb1(  0,   0,   0);
    eCxx::RGBColor rgb2( 63, 127, 255);
    dumpLERPColor3("RGB", rgb1, rgb2,   0);
    dumpLERPColor3("RGB", rgb1, rgb2,  20);
    dumpLERPColor3("RGB", rgb1, rgb2,  40);
    dumpLERPColor3("RGB", rgb1, rgb2,  60);
    dumpLERPColor3("RGB", rgb1, rgb2,  80);
    dumpLERPColor3("RGB", rgb1, rgb2, 100);
    printf("\n");
    eCxx::HSVColor hsv1(270, 200,   0);
    eCxx::HSVColor hsv2(270, 200, 200);
    dumpLERPColor3<eCxx::HSVColor::V>("HSV", hsv1, hsv2,   0);
    dumpLERPColor3<eCxx::HSVColor::V>("HSV", hsv1, hsv2,  20);
    dumpLERPColor3<eCxx::HSVColor::V>("HSV", hsv1, hsv2,  40);
    dumpLERPColor3<eCxx::HSVColor::V>("HSV", hsv1, hsv2,  60);
    dumpLERPColor3<eCxx::HSVColor::V>("HSV", hsv1, hsv2,  80);
    dumpLERPColor3<eCxx::HSVColor::V>("HSV", hsv1, hsv2, 100);
    printf("\n");
    _DIVIDERLINE_DASHSTR_NL1();

    _DIVIDERLINE_DASHSTR_NL1();
    _DIVIDERLINE_DASHSTR_NL1();



    printf("\n");
    printf( "HSV(%3d, %3d, %3d)\n", hsv1.h(), hsv1.s(), hsv1.v() );
    hsv1 = hsv2;
    printf( "HSV(%3d, %3d, %3d)\n", hsv1.h(), hsv1.s(), hsv1.v() );
    eCxx::RGBColor rgbc = hsv1;
    printf( "RGB(%3d, %3d, %3d)\n", rgbc.r(), rgbc.g(), rgbc.b() );
    eCxx::GRBColor grbc = hsv1;
    printf( "GRB(%3d, %3d, %3d)\n", grbc.g(), grbc.r(), grbc.b() );
    eCxx::BGRColor bgrc = grbc;
    printf( "BGR(%3d, %3d, %3d)\n", bgrc.b(), bgrc.g(), bgrc.r() );
    printf("\n");
    eCxx::XBGRColor<eCxx::SK9822XPolicy> xbgrc1 = hsv1;
    printf( "XBGR(%3d, %3d, %3d, %3d)\n", xbgrc1.gx(), xbgrc1.b(), xbgrc1.g(), xbgrc1.r() );
    eCxx::XBGRColor<eCxx::P9813BGRXPolicy> xbgrc2 = hsv1;
    printf( "XBGR(%3d, %3d, %3d, %3d)\n", xbgrc2.gx(), xbgrc2.b(), xbgrc2.g(), xbgrc2.r() );
    printf("\n");
    eCxx::WColor wc1 = xbgrc1;
    printf( "W(%3d)\n", wc1.w() );
    eCxx::WColor wc2 = xbgrc2;
    printf( "W(%3d)\n", wc2.w() );
    printf("\n");

    rgbc = wc1;
    printf( "RGB(%3d, %3d, %3d)\n", rgbc.r(), rgbc.g(), rgbc.b() );
    printf("\n");
    xbgrc1 = wc1;
    printf( "XBGR(%3d, %3d, %3d, %3d)\n", xbgrc1.gx(), xbgrc1.b(), xbgrc1.g(), xbgrc1.r() );
    xbgrc2 = wc1;
    printf( "XBGR(%3d, %3d, %3d, %3d)\n", xbgrc2.gx(), xbgrc2.b(), xbgrc2.g(), xbgrc2.r() );
    printf("\n");

    eCxx::XBGRColor<eCxx::APA102XPolicy  > xbgr1 = hsv1;
    eCxx::BGRXColor<eCxx::APA102XPolicy  > bgrx1 = hsv1;
    printf( "XBGR(%3d, %3d, %3d, %3d)\n", xbgr1.x(), xbgr1.b(), xbgr1.g(), xbgr1.r() );
    printf( "BGRX(%3d, %3d, %3d, %3d)\n", bgrx1.b(), bgrx1.g(), bgrx1.r(), bgrx1.x() );
    printf("\n");
    eCxx::XBGRColor<eCxx::P9813BGRXPolicy> xbgr2 = hsv1;
    eCxx::BGRXColor<eCxx::P9813BGRXPolicy> bgrx2 = hsv1;
    printf( "XBGR(%3d, %3d, %3d, %3d)\n", xbgr2.x(), xbgr2.b(), xbgr2.g(), xbgr2.r() );
    printf( "BGRX(%3d, %3d, %3d, %3d)\n", bgrx2.b(), bgrx2.g(), bgrx2.r(), bgrx2.x() );
    printf("\n");

    eCxx::KColor k1(5200);
    rgbc = k1;
    printf( "RGB(%3d, %3d, %3d)\n", rgbc.r(), rgbc.g(), rgbc.b() );
    wc1 = k1;
    printf( "W(%3d)\n", wc1.w() );
    wc1 = rgbc;
    printf( "W(%3d)\n", wc1.w() );
    printf("\n");

    rgbc.fromHTMLHexString("#7F3FFF");
    printf( "RGB (     %3d, %3d, %3d     )\n", rgbc.r(), rgbc.g(), rgbc.b() );
    eCxx::RGBWColor rgbwc;
    rgbwc.fromHTMLHexString("#7F3FFF");
    printf( "RGBW(     %3d, %3d, %3d, %3d)\n", rgbwc.r(), rgbwc.g(), rgbwc.b(), rgbwc.w() );
    eCxx::WRGBColor wrgbc;
    wrgbc.fromHTMLHexString("#7F3FFF");
    printf( "RGBW(%3d, %3d, %3d, %3d     )\n", wrgbc.w(), wrgbc.r(), wrgbc.g(), wrgbc.b() );
    wc1.fromHTMLHexString("#7F3FFF");
    printf( "W   (          %3d          )\n", wc1.w() );
    printf("\n");
    rgbc.fromHTMLHex(0x7F3FFF);
    printf( "RGB (     %3d, %3d, %3d     )\n", rgbc.r(), rgbc.g(), rgbc.b() );
    rgbwc.fromHTMLHex(0x7F3FFF);
    printf( "RGBW(     %3d, %3d, %3d, %3d)\n", rgbwc.r(), rgbwc.g(), rgbwc.b(), rgbwc.w() );
    wrgbc.fromHTMLHex(0x7F3FFF);
    printf( "RGBW(%3d, %3d, %3d, %3d     )\n", wrgbc.w(), wrgbc.r(), wrgbc.g(), wrgbc.b() );
    wc1.fromHTMLHex(0x7F3FFF);
    printf( "W   (          %3d          )\n", wc1.w() );
    printf("\n");
    _DIVIDERLINE_DASHSTR_NL1();

    _DIVIDERLINE_DASHSTR_NL1();
    _DIVIDERLINE_DASHSTR_NL1();



    #define PRINT_K(COLOR) printf( "%-12s K(%5d)\n", STRINGIFY(COLOR), (int) eCxx::Ext::K::COLOR.k() )
    printf("\n");
    PRINT_K(volcanicLava);
    PRINT_K(match       );
    PRINT_K(candle      );
    PRINT_K(highPressure);
    PRINT_K(incandescent);
    PRINT_K(warmWhite   );
    PRINT_K(halogen     );
    PRINT_K(metalHalide );
    PRINT_K(naturalWhite);
    PRINT_K(sunlight    );
    PRINT_K(dayWhite    );
    PRINT_K(cloudySky   );
    PRINT_K(coolWhite   );
    PRINT_K(blueSky     );

    printf("\n");
    #define PRINT_K_RGB(COLOR) do {                                                                      \
        const eCxx::RGBColor& c = eCxx::Ext::K::COLOR;                                                   \
        printf( "%-12s RGB(%3d, %3d, %3d)\n", STRINGIFY(COLOR), (int) c.r(), (int) c.g(), (int) c.b() ); \
    } while(0)
    PRINT_K_RGB(volcanicLava);
    PRINT_K_RGB(match       );
    PRINT_K_RGB(candle      );
    PRINT_K_RGB(highPressure);
    PRINT_K_RGB(incandescent);
    PRINT_K_RGB(warmWhite   );
    PRINT_K_RGB(halogen     );
    PRINT_K_RGB(metalHalide );
    PRINT_K_RGB(naturalWhite);
    PRINT_K_RGB(sunlight    );
    PRINT_K_RGB(dayWhite    );
    PRINT_K_RGB(cloudySky   );
    PRINT_K_RGB(coolWhite   );
    PRINT_K_RGB(blueSky     );
    printf("\n");
    _DIVIDERLINE_DASHSTR_NL1();

    #define PRINT_RGB(COLOR) printf( "%-11s RGB(%3d, %3d, %3d)\n", STRINGIFY(COLOR), (int) eCxx::Ext::RGB::COLOR.r(), (int) eCxx::Ext::RGB::COLOR.g(), (int) eCxx::Ext::RGB::COLOR.b() )
    printf("\n");
    PRINT_RGB(black      );
    PRINT_RGB(white      );
    PRINT_RGB(darkGray   );
    PRINT_RGB(gray       );
    printf("\n");
    PRINT_RGB(darkRed    );
    PRINT_RGB(red        );
    PRINT_RGB(darkGreen  );
    PRINT_RGB(green      );
    PRINT_RGB(darkBlue   );
    PRINT_RGB(blue       );
    printf("\n");
    PRINT_RGB(darkYellow );
    PRINT_RGB(yellow     );
    PRINT_RGB(darkMagenta);
    PRINT_RGB(magenta    );
    PRINT_RGB(darkCyan   );
    PRINT_RGB(cyan       );
    printf("\n");
    PRINT_RGB(darkBrown  );
    PRINT_RGB(brown      );
    PRINT_RGB(darkOrange );
    PRINT_RGB(orange     );
    PRINT_RGB(darkPurple );
    PRINT_RGB(purple     );
    printf("\n");
    PRINT_RGB(darkPink   );
    PRINT_RGB(pink       );
    PRINT_RGB(darkSalmon );
    PRINT_RGB(salmon     );
    PRINT_RGB(warmWhite  );
    PRINT_RGB(coolWhite  );
    printf("\n");
    _DIVIDERLINE_DASHSTR_NL1();

    #define PRINT_RGBW(COLOR) printf( "%-11s RGBW(%3d, %3d, %3d, %3d)\n", STRINGIFY(COLOR), (int) eCxx::Ext::RGBW::COLOR.r(), (int) eCxx::Ext::RGBW::COLOR.g(), (int) eCxx::Ext::RGBW::COLOR.b(), (int) eCxx::Ext::RGBW::COLOR.w() )
    printf("\n");
    PRINT_RGBW(black      );
    PRINT_RGBW(white      );
    PRINT_RGBW(darkGray   );
    PRINT_RGBW(gray       );
    printf("\n");
    PRINT_RGBW(darkRed    );
    PRINT_RGBW(red        );
    PRINT_RGBW(darkGreen  );
    PRINT_RGBW(green      );
    PRINT_RGBW(darkBlue   );
    PRINT_RGBW(blue       );
    printf("\n");
    PRINT_RGBW(darkYellow );
    PRINT_RGBW(yellow     );
    PRINT_RGBW(darkMagenta);
    PRINT_RGBW(magenta    );
    PRINT_RGBW(darkCyan   );
    PRINT_RGBW(cyan       );
    printf("\n");
    PRINT_RGBW(darkBrown  );
    PRINT_RGBW(brown      );
    PRINT_RGBW(darkOrange );
    PRINT_RGBW(orange     );
    PRINT_RGBW(darkPurple );
    PRINT_RGBW(purple     );
    printf("\n");
    PRINT_RGBW(darkPink   );
    PRINT_RGBW(pink       );
    PRINT_RGBW(darkSalmon );
    PRINT_RGBW(salmon     );
    PRINT_RGBW(warmWhite  );
    PRINT_RGBW(coolWhite  );
    printf("\n");
    _DIVIDERLINE_DASHSTR_NL1();

    #define PRINT_HSV(COLOR) printf( "%-11s HSV(%3d, %3d, %3d)\n", STRINGIFY(COLOR), (int) eCxx::Ext::HSV::COLOR.h(), (int) eCxx::Ext::HSV::COLOR.s(), (int) eCxx::Ext::HSV::COLOR.v() )
    printf("\n");
    PRINT_HSV(black      );
    PRINT_HSV(white      );
    PRINT_HSV(darkGray   );
    PRINT_HSV(gray       );
    printf("\n");
    PRINT_HSV(darkRed    );
    PRINT_HSV(red        );
    PRINT_HSV(darkGreen  );
    PRINT_HSV(green      );
    PRINT_HSV(darkBlue   );
    PRINT_HSV(blue       );
    printf("\n");
    PRINT_HSV(darkYellow );
    PRINT_HSV(yellow     );
    PRINT_HSV(darkMagenta);
    PRINT_HSV(magenta    );
    PRINT_HSV(darkCyan   );
    PRINT_HSV(cyan       );
    printf("\n");
    PRINT_HSV(darkBrown  );
    PRINT_HSV(brown      );
    PRINT_HSV(darkOrange );
    PRINT_HSV(orange     );
    PRINT_HSV(darkPurple );
    PRINT_HSV(purple     );
    printf("\n");
    PRINT_HSV(darkPink   );
    PRINT_HSV(pink       );
    PRINT_HSV(darkSalmon );
    PRINT_HSV(salmon     );
    PRINT_HSV(warmWhite  );
    PRINT_HSV(coolWhite  );
    printf("\n");
    _DIVIDERLINE_DASHSTR_NL1();

    #define PRINT_HSL(COLOR) printf( "%-11s HSL(%3d, %3d, %3d)\n", STRINGIFY(COLOR), (int) eCxx::Ext::HSL::COLOR.h(), (int) eCxx::Ext::HSL::COLOR.s(), (int) eCxx::Ext::HSL::COLOR.l() )
    printf("\n");
    PRINT_HSL(black      );
    PRINT_HSL(white      );
    PRINT_HSL(darkGray   );
    PRINT_HSL(gray       );
    printf("\n");
    PRINT_HSL(darkRed    );
    PRINT_HSL(red        );
    PRINT_HSL(darkGreen  );
    PRINT_HSL(green      );
    PRINT_HSL(darkBlue   );
    PRINT_HSL(blue       );
    printf("\n");
    PRINT_HSL(darkYellow );
    PRINT_HSL(yellow     );
    PRINT_HSL(darkMagenta);
    PRINT_HSL(magenta    );
    PRINT_HSL(darkCyan   );
    PRINT_HSL(cyan       );
    printf("\n");
    PRINT_HSL(darkBrown  );
    PRINT_HSL(brown      );
    PRINT_HSL(darkOrange );
    PRINT_HSL(orange     );
    PRINT_HSL(darkPurple );
    PRINT_HSL(purple     );
    printf("\n");
    PRINT_HSL(darkPink   );
    PRINT_HSL(pink       );
    PRINT_HSL(darkSalmon );
    PRINT_HSL(salmon     );
    PRINT_HSL(warmWhite  );
    PRINT_HSL(coolWhite  );
    printf("\n");



    return 0;
}
