/*===============================*\
# 7x10 RGB dot display for        #
#  displaying Xmas date/countdown #
\*===============================*/

#define Version "2.5.2" 

/*
 * A snake of WS2812b dot-RGB LEDs for a 10 width x 8 height display

 - bugfixes
  Simple display the first few days, and last day
  [Done] Cleanup Marquee code, so it cycles properly
  Date scene better timeinterval.
  Snow to be non-random
 - nicetohave now
  [Done]Advent picture on Sundays  (dates not to be hardcoded)
  Lucia picture on 13th
 - major enhancments
  [Done]Real RTC
  static scene for pre,1st post 24th  
  "Movie" and/or crossfade (using real RGB)
  ...

*/
#include "Timer.h"     // Timers and Clock
#include "Display.h"   // W1228b output
#include "Scenes.h"    // 

Timer TmrOne ;         // timer that toggles between scenes
byte Scene = 0;        // Start Scene
byte LstImg=1 ;        // last image, for looping images
int DBG=0 ;            // something to aid in debugging

void setup() {
  Serial.begin(115200/*9600*/);  // Highspeed for ANSI display
  delay(10); // seems the Serial needs a time to settle?
  Serial.print("Version ");Serial.println(Version);
  Display.setup() ;
  Clock.start();
  Serial.println("\033[H\033[2JGo");
}

void loop() {
  Clock.loop() ;

  switch ( Scene ) {
    case 0: Display.test() ; Display.refresh() ; delay(1000) ; // powerup test sequence
            Scene++ ;                                          // drop through to scene 1
    case 1: Display.clear(RGB6(0,2,2)); Serial.println(FirstAdvent()) ; 
            if ( Clock.Day>24 ) Scene = 6 ; // skip to pictures if after 24th
            Scene++ ; break ;
    
    case 2: Date.start() ; Scene++ ; break ;
    case 3: if ( Date.loop() ) Scene++ ;
           break ;

    case 4: //Picture or special day  (hardcoded for 2021)
            if ( ! (Clock.Day == 5 || Clock.Day == 12 || Clock.Day == 19 ) ) 
              { Scene = 7 ; break ; }
            // if ( Clock.Day == 13 ) Scene = ?
            Scene++ ; // advent drop thru

    case 5: Advent.start(Clock.Day/7+2) ;        // kludgy signal 2, 3 or 4th advent
            Scene++ ; break ;
    case 6: if ( Advent.loop() ) {
            Advent.stop() ;  Scene=2 ;           // ** only date and candles in advent
            }
            break ;

    case 7: Picture.start(LstImg) ; TmrOne.Set(10000) ; Scene++ ; break ;
    case 8: Picture.loop() ; if ( TmrOne.Chk() ) { 
              if ( ++LstImg >= sizeof(IMG)/(XX*YY) ) LstImg=1 ; 
              Scene++ ;
            }
           break ;

    case 9: GodJul.start() ; TmrOne.Set(8000) ; 
            Display.clear(RGB6(0,2,0)); Scene++ ; break ;
    case 10: GodJul.loop() ; if ( TmrOne.Chk() ) {
                GodJul.stop() ; Scene++ ; }
           break ;
    default: Date.stop() ; GodJul.stop() ; Snow.stop() ; Scene = 1 ;
  }
  Display.refresh() ;
  // Display.test() ; while(1) ;
}

int FirstAdvent() {
  // we have from the 27thNov to the 3rdDec inclusive as candiates, returned as -3..3
  int First = Clock.Day ;
Serial.print(First);Serial.print(',');
  if ( First >=27 ) First -= 30 ;  // negative daynumber in november
Serial.print(First);Serial.print(',');
  while ( First > 3 ) First -= 7 ; // Skip weeks backward until 1st week
Serial.print(First);Serial.print(',');
  First -= Clock.Weekday ;         // Go back to previous Sunday
Serial.print(First);Serial.print(',');
  if ( First < -3 ) First += 7 ;   // adjust a week forward if before 27thNov
Serial.print('.') ;
  return First ;
}