#include "frames.h"

const long * frames[] =
{
  Xmas001, Xmas002, Xmas003, Xmas004, Xmas005, Xmas006, Xmas007,
  Xmas008, Xmas009, Xmas010, Xmas011, Xmas012, Xmas013, Xmas014,
  Xmas015, Xmas016, Xmas017, Xmas018, Xmas019, Xmas020, Xmas021,
  Xmas022, Xmas023, Xmas024, Xmas025, Xmas026, Xmas027, Xmas028,
  Xmas029, Xmas030, Xmas031, Xmas032, Xmas033, Xmas034, Xmas035,
  Xmas036, Xmas037, Xmas038, Xmas039, Xmas040, Xmas041, Xmas042,
  Xmas043, Xmas044, Xmas045, Xmas046, Xmas047, Xmas048, Xmas049,
  Xmas050, Xmas051, Xmas052, Xmas053, Xmas054, Xmas055, Xmas056,
  Xmas057, Xmas058, Xmas059, Xmas060, Xmas061, Xmas062, Xmas063,
  Xmas064, Xmas065, Xmas066, Xmas067, Xmas068, Xmas069, Xmas070,
  Xmas071, Xmas072, Xmas073, Xmas074, Xmas075, Xmas076, Xmas077
};



class ArrayFormatter
{
  public :
  
  void start( const char * text, const size_t maxValuesPerLine = 10, const bool jumpLine = false )
  {
    if ( m_started )
    {
      return;
    }
    
    m_started = true;
    m_maxValuesPerLine = maxValuesPerLine;
    m_counter = 0;
    m_jumpLine = jumpLine;
    
    if ( sm_level == 0 )
    {
      Serial.print( text );
      Serial.print( " =\n" );
    }
    else
    {
      Serial.print( "// " );
      Serial.print( text );
      Serial.print( '\n' );
      
      for ( uint8_t i = 0; i < sm_level; i++ )
      {
        Serial.print( '\t' );
      }
    }
    
    Serial.print( "{\n" );
    
    sm_level++;
  }
  
  void add( const char * value )
  {
    if ( add() )
    {
      Serial.print( value );
    }
  }
  
  bool add()
  {
    if ( !m_started )
    {
      return false;
    }
    
    if ( m_counter == 0 )
    {
      for ( uint8_t i = 0; i < sm_level; i++ )
      {
        Serial.print( '\t' );
      }
    }
    else
    {
      if ( m_counter < m_maxValuesPerLine )
      {
        Serial.print( ", " );
      }
      else
      {
        m_counter = 0;
        Serial.print( ",\n" );
        
        if ( m_jumpLine )
        {
          Serial.print( '\n' );
        }
        
        for ( uint8_t i = 0; i < sm_level; i++ )
        {
          Serial.print( '\t' );
        }
      }
    }
    m_counter++;
    return true;
  }
  
  void end()
  {
    if ( !m_started )
    {
      return;
    }
    
    m_started = false;
    m_counter = 0;
    sm_level--;
    
    Serial.print( '\n' );
    
    if ( sm_level == 0 )
    {
      Serial.print( "};\n" );
    }
    else
    {
      for ( uint8_t i = 0; i < sm_level; i++ )
      {
        Serial.print( '\t' );
      }
      Serial.print( '}' );
    }
  }
  
  private :
  static uint8_t sm_level;
  bool   m_started = false;
  size_t m_maxValuesPerLine = 10;
  size_t m_counter = 0;
  bool   m_jumpLine = false;
};
uint8_t ArrayFormatter::sm_level = 0;



void printArrays()
{
  ArrayFormatter af, af2;
  char str[40];
  uint8_t colorsCounter = 0;
  uint32_t colorsList[16];
  uint8_t framesCount = sizeof(frames) / sizeof(frames[0]);
  
  Serial.print( "\n//---------------------------------------------------------------------------\n\n" );
  
  af.start( "const uint32_t frames[][32] PROGMEM", 1, true );
  for ( size_t i = 0; i < framesCount; i++ )
  {
    uint8_t nibblesCounter = 0;
    uint32_t nibbles = 0;
    
    af.add();
    snprintf( str, sizeof( str ), "frame %03u", i );
    af2.start( str, 4 );
    
    for ( size_t j = 0; j < 256; j++ )
    {
      //uint32_t pixelColor = pgm_read_dword( &(frames[i][j]) );
      uint32_t pixelColor = frames[i][j];
      
      uint8_t k = 0;
      for ( ; k < colorsCounter; k++ )
      {
        if ( pixelColor == colorsList[k] )
        {
          nibbles = (nibbles << 4) | k;
          break;
        }
      }
      if ( k == colorsCounter )
      {
        nibbles = (nibbles << 4) | k;
        colorsList[colorsCounter++] = pixelColor;
      }
      
      if ( ++nibblesCounter == 8 )
      {
        snprintf( str, sizeof( str ), "0x%08X", nibbles );
        af2.add( str );
        nibblesCounter = 0;
        nibbles = 0;
      }
    }
    af2.end();
  }
  af.end();
  
  Serial.print( "\nconst size_t framesCount = sizeof(frames) / sizeof(frames[0]);\n\n" );
  
  af.start( "const CRGB colorsList[]", 1 );
  for ( size_t i = 0; i < colorsCounter; i++ )
  {
    snprintf( str, sizeof( str ), "0x%06X", colorsList[i] );
    af.add( str );
  }
  af.end();
  
  Serial.print( "\n//---------------------------------------------------------------------------\n\n" );
}

void setup()
{
  Serial.begin( 921600 );
  printArrays();
}

void loop()
{
}