#include <Adafruit_GFX.h>
#include <Adafruit_SSD1306.h>
#include <Wire.h>

#define SCREEN_WIDTH 128
#define SCREEN_HEIGHT 64
#define OLED_RESET -1

Adafruit_SSD1306 display(SCREEN_WIDTH, SCREEN_HEIGHT, &Wire, OLED_RESET);
void showText(String text, int x, int y, int size = 1) {
  display.setRotation(2);  
  
  display.setTextSize(size);         // rozmiar tekstu: 1, 2, 3...
  display.setTextColor(SSD1306_WHITE);
  display.setCursor(x, y);           // pozycja startowa (piksele)
  display.println(text);             // tekst do wyświetlenia
  
}

// Wierzchołki kostki
float cube[8][3] = {
  {-1, -1, -1}, {1, -1, -1},
  {1, 1, -1},  {-1, 1, -1},
  {-1, -1, 1}, {1, -1, 1},
  {1, 1, 1},   {-1, 1, 1}
};

float scale = 1.0;       // aktualna skala kostki
int scaleState = 0;      // 0: normalna, 1: powiększona, 2: pomniejszona
bool buttonPressed = false;  // do obsługi jednokrotnego kliknięcia


float angleX = 0, angleY = 0;
float projected[8][2];  // globalna tablica do rzutowania
int timer =0;

void setup() {
  Serial.begin(9600);
  display.begin(SSD1306_SWITCHCAPVCC, 0x3C);
  display.clearDisplay();
  display.display();

  pinMode(4, INPUT_PULLUP);  // GP
  pinMode(5, INPUT_PULLUP);  // DL
  pinMode(7, INPUT_PULLUP);  // Góra
  pinMode(10, INPUT_PULLUP); // Dół
  pinMode(8, INPUT_PULLUP);  // Lewo
  pinMode(9, INPUT_PULLUP);  // Prawo
}

void loop() {
  bool updated = false;

  if (digitalRead(5) == LOW) {
  if (!buttonPressed) {
    buttonPressed = true;

    // zmiana stanu skali
    scaleState = (scaleState + 1) % 3;

    if (scaleState == 0) scale = 1.0;
    else if (scaleState == 1) scale = 2.0;
    else if (scaleState == 2) scale = 0.5;

    Serial.print("Skala kostki: ");
    Serial.println(scale);
    timer =0;
  }
} else {
  buttonPressed = false;  // reset przy puszczeniu przycisku
}


  if (digitalRead(7) == LOW) { angleX -= 0.1; updated = true; timer =0; }  // Góra
  if (digitalRead(10) == LOW) { angleY += 0.1; updated = true; timer =0; } // Dół
  if (digitalRead(8) == LOW) { angleY -= 0.1; updated = true; timer =0; }  // Lewo
  if (digitalRead(9) == LOW) { angleX += 0.1; updated = true; timer =0; }  // Prawo
  if(digitalRead(4) == LOW) {angleX=0;angleY=0;updated=true; timer=0;}  //home
 if (digitalRead(7) == LOW && digitalRead(10) == LOW && digitalRead(8) == LOW && digitalRead(9) == LOW) { display.clearDisplay();
 if (timer > 1000){angleX += 0.1; updated = true; angleY += 0.1;}
showText("BOOM", 10, 10,4);  // tekst, x=10, y=10, rozmiar=2
display.display();
delay(500); display.setRotation(0);   }  // Góra

  if (updated) {
    Serial.print("angleX: ");
    Serial.print(angleX);
    Serial.print("  angleY: ");
    Serial.println(angleY);
    Serial.print("  timer: ");
    Serial.println(timer);
  }

  display.clearDisplay();

  // Transformacja i rzutowanie 3D -> 2D
  for (int i = 0; i < 8; i++) {
    float x = cube[i][0];
    float y = cube[i][1];
    float z = cube[i][2];

    // Obrót wokół X
    float y1 = cos(angleX) * y - sin(angleX) * z;
    float z1 = sin(angleX) * y + cos(angleX) * z;

    // Obrót wokół Y
    float x1 = cos(angleY) * x + sin(angleY) * z1;
    float z2 = -sin(angleY) * x + cos(angleY) * z1;

    // Rzutowanie ortogonalne na ekran 2D
   projected[i][0] = x1 * 20 * scale + SCREEN_WIDTH / 2;
projected[i][1] = y1 * 20 * scale + SCREEN_HEIGHT / 2;

  }

  // Tylne krawędzie – kreskowane
  drawDashedLine(0,1); drawDashedLine(1,2);
  drawDashedLine(2,3); drawDashedLine(3,0);
  drawDashedLine(0,4); drawDashedLine(1,5);
  drawDashedLine(2,6); drawDashedLine(3,7);

  // Przednie krawędzie – pełne
  drawLine(4,5); drawLine(5,6);
  drawLine(6,7); drawLine(7,4);

  display.display();
  delay(30);
  timer += 1;
}

void drawLine(int i, int j) {
  display.drawLine(projected[i][0], projected[i][1], projected[j][0], projected[j][1], SSD1306_WHITE);
}

void drawDashedLine(int i, int j) {
  float x0 = projected[i][0];
  float y0 = projected[i][1];
  float x1 = projected[j][0];
  float y1 = projected[j][1];

  int segments = 10;
  for (int s = 0; s < segments; s += 2) {
    float t0 = (float)s / segments;
    float t1 = (float)(s + 1) / segments;
    int xa = x0 + (x1 - x0) * t0;
    int ya = y0 + (y1 - y0) * t0;
    int xb = x0 + (x1 - x0) * t1;
    int yb = y0 + (y1 - y0) * t1;
    display.drawLine(xa, ya, xb, yb, SSD1306_WHITE);
  }
}
