#include <Arduino.h>
#include <FastLED.h>
#include <colorutils.h>

#define BRIGHTNESS        255  // maximum brightness is 255  on real leds this should probably be about 100
// the purpose of this application is to share the brightness between the
// four closest lights to the calculated position of each leaper
// this gives the feel of a display with many more pixels
// the technoligy is called anti-alliasing
#define COLOR_ORDER       GRB
#define CHIPSET           WS2812B

// Define the LED matrix parameters
#define LED_PIN     3
#define NUM_LEDS_X  40
#define NUM_LEDS_Y  12
#define NUM_LEDS    (NUM_LEDS_X * NUM_LEDS_Y)
#define SerialOut 1 // 1 = Print point in Serial windows,  0 = print nothing

CRGB leds[NUM_LEDS];

void setup() {
  FastLED.addLeds<WS2812B, LED_PIN, GRB>(leds, NUM_LEDS);

  Serial.begin(9600);
}

void loop() {
  int x1 = 7;
  int y1 = 2;
  int x2 = 33;
  int y2 = 10;
  //
  // // the following is to test the y azis with discreet lines

  // float xd = ((float)x2 - (float)x1) / ((float)y2 - (float)y1);

  //   DrawLineY(x1, y1, x2, y2, xd, 0);
  // } else {
  //   DrawLineY(x1, y2, x2, y1, xd, NUM_LEDS_X);
  // }

  // // the following is to test the x azis with discreet lines

    float yd = ((float)y2 - (float)y1) / ((float)x2 - (float)x1);

    if (x1 < x2) {
      DrawLineX(x1, y1, x2, y2, yd, 0);
    } else {
      DrawLineX(x2, y1, x1, y2, yd, 0);
    }

  // while (1) {}    // stop here

  //
  //
  // // the following for loop for X works correctly.
  // // This section of code should draw lines from top left to bottom right, incrementing across the top x
  // // axis and in reverse direction on the bottom x axis until a final line is drawn from top right to bottom left
  //
  // for (int i = 0; x1 <= NUM_LEDS_X; ++i) {
  //   x1 = x1 + 1;
  //   x2 = NUM_LEDS_X - x1;
  //   float yd = ((float)y2 - (float)y1) / ((float)x2 - (float)x1);
  //   if (x1 < x2) {
  //     DrawLineX(x1, y1, x2, y2, yd, 0);
  //   } else {
  //     DrawLineX(x2, y1, x1, y2, yd, NUM_LEDS_Y);
  //   }
  // }
  // // the following for loop for Y is not working yet.
  // // This section of code should draw lines from bottom left to top right, incrementing up the left hand
  // // y axis and down the right hand y axis until a final line is drawn from top left to bottom right

  // for (int i = 0; y1 <= NUM_LEDS_Y; ++i) {
  //   y1 = y1 + 1;
  //   y2 = NUM_LEDS_Y - y1;
  //   float xd = ((float)x2 - (float)x1) / ((float)y2 - (float)y1);
  //   if (y1 < y2) {
  //     DrawLineY(x1, y1, x2, y2, xd, 0);
  //   } else {
  //     DrawLineY(x1, y2, x2, y1, xd, 0);
  //   }
  // }
   while (1) {}    // stop here
}

void DrawLineX(int xa, int ya, int xb, int yb, float yd, float yinc) {
  // float yinc = 0;
  int y = 0;
  //  float yd = ((float)y2 - (float)y1) / ((float)x2 - (float)x1);
  // Draw a line on the LED matrix
  for (int x = xa; x < xb; ++x) {

    yinc = yinc + yd;
    y = round(yinc);
    if (SerialOut) {
      Serial.print("xa: ");
      Serial.print(xa);
      Serial.print(", xb: ");
      Serial.print(xb);
      Serial.print(", x: ");
      Serial.print(x);
      Serial.print(", yinc: ");
      Serial.print(yinc);
      Serial.print(", yd: ");
      Serial.print(yd);
      Serial.print(", y: ");
      Serial.println(y);
    }
    if (y < NUM_LEDS_Y) {
      leds[XY(x, y)] = CRGB::White;
    }

  }
  FastLED.show();
  if (SerialOut) {
    delay(100); // Adjust delay time as needed
  }
  // delay(1000); // Adjust delay time as needed
  fill_solid(leds, NUM_LEDS, CRGB::Black); // Clear the matrix


}

void DrawLineY(int xa, int ya, int xb, int yb, float xd, float xinc) {
  // float yinc = 0;
  int x = 0;
  // Draw a line on the LED matrix
  for (int y = ya; y < yb; ++y) {

    xinc = xinc + xd;
    x = round(xinc);
    if (SerialOut) {
      Serial.print("xa: ");
      Serial.print(xa);
      Serial.print(", xb: ");
      Serial.print(xb);
      Serial.print(", x: ");
      Serial.print(x);
      Serial.print(", xinc: ");
      Serial.print(xinc);
      Serial.print(", xd: ");
      Serial.print(xd);
      Serial.print(", y: ");
      Serial.println(y);
    }
    if (x < NUM_LEDS_X) {
      leds[XY(x, y)] = CRGB::White;
    }
  }
  FastLED.show();
  if (SerialOut) {
    delay(100); // Adjust delay time as needed
  }
  // delay(1000); // Adjust delay time as needed
  fill_solid(leds, NUM_LEDS, CRGB::Black); // Clear the matrix


}

// Function to map 2D (x, y) coordinates to 1D LED array index
int XY(int x, int y) {
  if (y % 2 == 0) {
    // For even rows, return index directly
    return y * NUM_LEDS_X + x;
  } else {
    // For odd rows, map x to reverse direction
    return y * NUM_LEDS_X + (NUM_LEDS_X - 1 - x);
  }
}

// uint16_t XY(uint8_t x, uint8_t y) {
//   uint8_t major, minor, sz_major, sz_minor;
//   if (x >= kMatrixWidth || y >= kMatrixHeight)
//     return NUM_LEDS;
//   if (XY_MATRIX & ROWMAJOR)
//     major = x, minor = y, sz_major = kMatrixWidth,  sz_minor = kMatrixHeight;
//   else
//     major = y, minor = x, sz_major = kMatrixHeight, sz_minor = kMatrixWidth;
//   if ((XY_MATRIX & FLIPMAJOR) ^ (minor & 1 && (XY_MATRIX & SERPENTINE)))
//     major = sz_major - 1 - major;
//   if (XY_MATRIX & FLIPMINOR)
//     minor = sz_minor - 1 - minor;
//   return (uint16_t) minor * sz_major + major;
// }