#include <FastLED.h>

template<int PIN>
class Custom7SegD {
public:
    // Constructor
    Custom7SegD(int numDisplays, int brightness);

    // Function to display a digit on a specific display
    void displayDigit(int displayNum, int digit, CRGB color, int brightness);

    // Function to light a specific segment on a specific display
    void lightSegment(int displayNum, char segment, CRGB color, int brightness);

private:
    int numDisplays;
    int numLeds;
    int initialBrightness;
    CRGB *leds;
    const byte segmentMap[7][2] = {
        {3, 4},   // A
        {5, 6},   // B
        {12, 13}, // C
        {0, 1},   // D
        {7, 8},   // E
        {9, 10},  // F
        {2, 11}   // G
    };
    /*
    byte digitStates[10][14] = {
        {1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 1, 1}, // 0
        {0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 0, 0, 1, 1}, // 1
        {1, 1, 1, 1, 0, 0, 1, 1, 1, 1, 1, 1, 0, 0}, // 2
        {1, 1, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1}, // 3
        {0, 0, 0, 0, 1, 1, 0, 0, 1, 1, 1, 1, 1, 1}, // 4
        {1, 1, 0, 0, 1, 1, 1, 1, 0, 0, 1, 1, 1, 1}, // 5
        {1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 1, 1, 1, 1}, // 6
        {0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 0, 0, 1, 1}, // 7
        {1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1}, // 8
        {1, 1, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1}  // 9
    };
    */
    byte digitStates[10] =
    {
      //   A
      // F   B
      //   G
      // E   C
      //   D

      //GFEDCBA
      0b0111111, // 0
      0b0000110, // 1
      0b1011011, // 2
      0b1001111, // 3
      0b1100110, // 4
      0b1101101, // 5
      0b1111101, // 6
      0b0000111, // 7
      0b1111111, // 8
      0b1101111, // 9
    };
};

// Constructor
template<int PIN>
Custom7SegD<PIN>::Custom7SegD(int numDisplays, int brightness)
    : numDisplays(numDisplays), numLeds(numDisplays * 14) {
    leds = new CRGB[numLeds];
    FastLED.addLeds<WS2812B, PIN, GRB>(leds, numLeds).setCorrection(TypicalLEDStrip);
    FastLED.setBrightness(brightness);
}

// Function to display a digit
template<int PIN>
void Custom7SegD<PIN>::displayDigit(int displayNum, int digit, CRGB color, int brightness) {
    // Calculate the starting LED index for the specified display
    int startIdx = (displayNum - 1) * 14;
    /*
    // Turn off all LEDs first
    for (int i = 0; i < 14; i++) {
        leds[startIdx + i] = CRGB::Black;
    }
    // Light up the LEDs for the specified digit
    for (int segment = 0; segment < 14; segment++) {
        if (digitStates[digit][segment] == 1) {
            leds[startIdx + segment] = color;
        }
    }
    */

    for ( uint8_t segment = 0; segment < 7; ++segment )
    {
      size_t id = startIdx + ( segment * 2 );

      if ( bitRead( digitStates[digit], segment ) == 1 )
      {
        leds[id]   = color;
        leds[id+1] = color;
      }
      else
      {
        leds[id]   = CRGB::Black;
        leds[id+1] = CRGB::Black;
      }
    }

    FastLED.setBrightness(brightness);
    FastLED.show();
}

// Function to light up a specific segment
template<int PIN>
void Custom7SegD<PIN>::lightSegment(int displayNum, char segment, CRGB color, int brightness) {
    // Define segment to LED mapping
    int segmentMapping[7][2] = {
        {0, 1}, // Segment A
        {2, 3}, // Segment B
        {4, 5}, // Segment C
        {6, 7}, // Segment D
        {8, 9}, // Segment E
        {10, 11}, // Segment F
        {12, 13}  // Segment G
    };

    // Calculate the starting LED index for the specified display
    int startIdx = (displayNum - 1) * 14;

    // Light up the LEDs for the specified segment
    if (segment >= 'A' && segment <= 'G') {
        int segIdx = segment - 'A';
        for (int i = segmentMapping[segIdx][0]; i <= segmentMapping[segIdx][1]; i++) {
            leds[startIdx + i] = color;
        }
        FastLED.setBrightness(brightness);
        FastLED.show();
    }
}




#define LED_PIN 5         // Pin where the WS2812B LEDs are connected
#define NUM_DISPLAYS 1    // Number of 7-segment displays in the chain

// Create an instance of the Custom7SegD class with 1 display, connected to LED_PIN, and initial brightness of 150
Custom7SegD<LED_PIN> myDisplay(NUM_DISPLAYS, 150);

void setup() {
  // Nothing needed here since the brightness is set during initialization
}

void loop() {
  // Loop to count from 0 to 9
  for (int digit = 0; digit <= 9; digit++) {
    myDisplay.displayDigit(1, digit, CRGB::Magenta, 150);  // Display digit on the first (and only) display with brightness 150
    delay(1000); // Wait for 1 second before moving to the next digit
  }
}