#include <U8g2lib.h>
#include <Wire.h>
#include <math.h>
U8G2_SSD1306_128X64_NONAME_F_HW_I2C u8g2(U8G2_R0, /* reset=*/U8X8_PIN_NONE);
#define SCREEN_WIDTH 128
#define SCREEN_HEIGHT 64
#define NUM_COUNT 5
#define NUM_MIN 1
#define NUM_MAX 45
#define ANIMATION_TIME 500 // ms (3배 빠르게)
#define FONT_HEIGHT 11
#define FONT u8g2_font_fub11_tr
#define SWING_AMPLITUDE 5 // 흔들림 진폭(픽셀)
#define GROUP_SIZE 5
#define TOTAL_NUM NUM_MAX
#define GROUP_COUNT ((TOTAL_NUM + GROUP_SIZE - 1) / GROUP_SIZE)
struct RollingNumber
{
  int value;
  int x;
  int y;
  int dir; // -1: right->left, 1: left->right
  int speed;
  unsigned long startTime;
  unsigned long duration;
  bool active;
};
RollingNumber numbers[NUM_COUNT];
int selected[NUM_COUNT];
int allNumbers[TOTAL_NUM]; // 1~45 섞인 배열
int groupIndex = 0;        // 현재 장면(그룹) 인덱스
unsigned long sceneStart = 0;
void shuffleAllNumbers()
{
  for (int i = 0; i < TOTAL_NUM; ++i)
    allNumbers[i] = i + 1;
  for (int i = TOTAL_NUM - 1; i > 0; --i)
  {
    int j = random(i + 1);
    int t = allNumbers[i];
    allNumbers[i] = allNumbers[j];
    allNumbers[j] = t;
  }
}
void setupNumbers()
{
  int lineHeight = SCREEN_HEIGHT / GROUP_SIZE;
  int base = groupIndex * GROUP_SIZE;
  for (int i = 0; i < GROUP_SIZE; ++i)
  {
    int idx = base + i;
    numbers[i].value = (idx < TOTAL_NUM) ? allNumbers[idx] : -1; // -1이면 빈칸
    numbers[i].y = (i * lineHeight) + (lineHeight + FONT_HEIGHT) / 2 - 1;
    numbers[i].dir = (i % 2 == 0) ? 1 : -1;
    numbers[i].speed = random(3, 6);
    numbers[i].duration = ANIMATION_TIME;
    numbers[i].startTime = sceneStart;
    numbers[i].active = false;
    if (numbers[i].dir == 1)
      numbers[i].x = -40;
    else
      numbers[i].x = SCREEN_WIDTH + 10;
  }
}
void setup()
{
  u8g2.begin();
  u8g2.setFont(FONT);
  randomSeed(analogRead(0));
  shuffleAllNumbers();
  groupIndex = 0;
  sceneStart = millis();
  setupNumbers();
}
void drawNumber(RollingNumber &num, float progress)
{
  if (num.value < 0)
    return;
  char buf[4];
  sprintf(buf, "%d", num.value);
  float swing = sin(progress * 3.14159 * 2) * SWING_AMPLITUDE;
  int y = num.y + (int)swing;
  u8g2.setFontDirection(0);
  u8g2.drawStr(num.x, y, buf);
}
void drawSixCirclesWithNumbers()
{
  // 원 위치 계산 (128x64 기준, 겹치지 않게)
  const int r = 15; // 반지름
  const int cx[6] = {24, 64, 104, 24, 64, 104};
  const int cy[6] = {15, 15, 15, 48, 48, 48};   // 위쪽 3개만 20->15로 -5 이동
  const int nums[6] = {11, 22, 33, 44, 55, 66}; // 2자리 숫자
  u8g2.clearBuffer();
  u8g2.setFont(FONT);
  for (int i = 0; i < 6; ++i)
  {
    u8g2.drawCircle(cx[i], cy[i], r, U8G2_DRAW_ALL);
    // 숫자 중앙 정렬, 전체 -y축 1픽셀 이동 (기존 +4에서 +3으로)
    char buf[4];
    sprintf(buf, "%d", nums[i]);
    int tw = u8g2.getStrWidth(buf);
    int th = FONT_HEIGHT;
    u8g2.drawStr(cx[i] - tw / 2, cy[i] + th / 2 - 2 + 3, buf);
  }
  u8g2.sendBuffer();
}
void drawSixCirclesWithNumbersAnimated() {
  const int r = 15;
  const int cx[6] = {24, 64, 104, 24, 64, 104};
  const int cy[6] = {15, 15, 15, 48, 48, 48};
  const int nums[6] = {11, 22, 33, 44, 55, 66};
  // 방향: 0=오른쪽->왼쪽(왼쪽위/아래), 1=아래->위(가운데위), 2=위->아래(가운데아래), 3=왼쪽->오른쪽(오른쪽위/아래)
  const int dir[6] = {0, 1, 3, 0, 2, 3};
  const int animTime = 400; // ms
  unsigned long start = millis();
  unsigned long now;
  bool done = false;
  while (!done) {
    now = millis();
    u8g2.clearBuffer();
    done = true;
    for (int i = 0; i < 6; ++i) {
      u8g2.drawCircle(cx[i], cy[i], r, U8G2_DRAW_ALL);
      float t = (float)(now - start) / animTime;
      if (t > 1) t = 1;
      int x = cx[i], y = cy[i];
      if (dir[i] == 0) { // 오른쪽->왼쪽
        x = cx[i] + (int)((1-t) * (SCREEN_WIDTH - cx[i]));
      } else if (dir[i] == 1) { // 아래->위
        y = cy[i] + (int)((1-t) * (SCREEN_HEIGHT - cy[i]));
      } else if (dir[i] == 2) { // 위->아래
        y = cy[i] - (int)((1-t) * (cy[i]));
      } else if (dir[i] == 3) { // 왼쪽->오른쪽
        x = cx[i] - (int)((1-t) * (cx[i]));
      }
      char buf[4];
      sprintf(buf, "%d", nums[i]);
      int tw = u8g2.getStrWidth(buf);
      int th = FONT_HEIGHT;
      u8g2.drawStr(x - tw/2, y + th/2 - 2 + 3, buf);
      if (t < 1) done = false;
    }
    u8g2.sendBuffer();
    delay(16);
  }
}
void loop()
{
  unsigned long now = millis();
  u8g2.clearBuffer();
  bool anyActive = false;
  for (int i = 0; i < GROUP_SIZE; ++i)
  {
    RollingNumber &num = numbers[i];
    if (num.value < 0)
      continue;
    if (now >= num.startTime && now < num.startTime + num.duration)
    {
      num.active = true;
      int totalMove = SCREEN_WIDTH + 50;
      float progress = (float)(now - num.startTime) / num.duration;
      if (num.dir == 1)
        num.x = -40 + progress * totalMove;
      else
        num.x = SCREEN_WIDTH + 10 - progress * totalMove;
      drawNumber(num, progress);
      anyActive = true;
    }
    else
    {
      num.active = false;
    }
  }
  u8g2.sendBuffer();
  if (now > sceneStart + ANIMATION_TIME)
  {
    groupIndex++;
    if (groupIndex < GROUP_COUNT)
    {
      sceneStart = millis();
      setupNumbers();
    }
    else
    {
      // 모든 장면 끝: 6개 원과 1~6 숫자 애니메이션으로 표시
      delay(500);
      drawSixCirclesWithNumbersAnimated();
      while (1)
        ;
    }
  }
  delay(20);
}