/*
 * Step 2: 순차적 폭포 애니메이션
 *
 * 목적:
 * - 단일 LED가 위에서 아래로 떨어지는 애니메이션
 * - 한 LED가 끝까지 떨어진 후 다음 LED 시작
 * - (0,0) → (1,0) → (2,0) → ... → (7,0) 순서로 순차 실행
 *
 * 하드웨어:
 * - Arduino 보드 (Uno, Nano 등)
 * - MAX7219 8x8 LED Matrix 모듈
 *
 * 핀 연결:
 * - VCC  → 5V
 * - GND  → GND
 * - DIN  → 디지털 핀 11 (MOSI)
 * - CLK  → 디지털 핀 13 (SCK)
 * - CS   → 디지털 핀 10 (SS)
 *
 * 라이브러리:
 * - LedControl
 */
#include <LedControl.h>
// 상수 정의
constexpr uint8_t MATRIX_WIDTH = 8;
constexpr uint8_t MATRIX_HEIGHT = 8;
constexpr uint8_t PIN_DIN = 11;
constexpr uint8_t PIN_CLK = 13;
constexpr uint8_t PIN_CS = 10;
constexpr uint8_t NUM_DEVICES = 1;
constexpr uint32_t DROP_INTERVAL = 100; // LED 떨어지는 속도 (ms)
// 사용자 설정 변수
constexpr uint8_t TAIL_LENGTH = 2; // 떨어지는 LED 꼬리 길이 (1~8)
constexpr uint8_t DROP_WIDTH = 1;  // 한 번에 떨어지는 열 개수 (1~8)
constexpr uint8_t DROP_HEIGHT = 1; // 한 번에 이동하는 행 개수 (1~8)
// LED 매트릭스 객체
LedControl matrix = LedControl(PIN_DIN, PIN_CLK, PIN_CS, NUM_DEVICES);
// 물방울 상태 변수
uint32_t previous_millis = 0;
uint8_t current_column = 0;                               // 현재 시작 열
int8_t column_rows[8] = {-1, -1, -1, -1, -1, -1, -1, -1}; // 각 열의 현재 행 위치 (-1: 비활성)
void setup()
{
    Serial.begin(115200);
    while (!Serial && millis() < 3000)
    {
        // 시리얼 대기 (최대 3초)
    }
    Serial.println("=== Step 2: Waterfall Sequence Animation ===");
    Serial.println("Matrix Size: 8x8");
    Serial.println("Sequential drop pattern");
    Serial.print("Tail Length: ");
    Serial.println(TAIL_LENGTH);
    Serial.print("Drop Width (Columns): ");
    Serial.println(DROP_WIDTH);
    Serial.print("Drop Height (Rows per step): ");
    Serial.println(DROP_HEIGHT);
    Serial.println();
    // LED 매트릭스 초기화
    matrix.shutdown(0, false);
    matrix.setIntensity(0, 8);
    matrix.clearDisplay(0);
    Serial.println("Matrix initialized successfully!");
    Serial.println("Starting waterfall animation...");
    Serial.println();
}
void loop()
{
    uint32_t current_millis = millis();
    // 주기적으로 LED 한 칸씩 아래로 이동
    if (current_millis - previous_millis >= DROP_INTERVAL)
    {
        previous_millis = current_millis;
        // LED 위치 업데이트
        update_waterdrop();
    }
}
// 물방울 위치 업데이트 및 렌더링
void update_waterdrop()
{
    // 화면 지우기
    matrix.clearDisplay(0);
    // 전체 매트릭스의 모든 열을 확인하여 렌더링
    for (uint8_t col = 0; col < MATRIX_WIDTH; col++)
    {
        // 이 열이 시작할 시점인지 확인
        if (col == 0)
        {
            // 첫 번째 열: 아직 시작 안했으면 시작
            if (column_rows[col] == -1)
            {
                column_rows[col] = 0;
            }
        }
        else
        {
            // 이후 열: 이전 열이 TAIL_LENGTH만큼 진행했는지 확인
            if (column_rows[col - 1] >= (TAIL_LENGTH - 1) && column_rows[col] == -1)
            {
                column_rows[col] = 0;
            }
        }
        // 이 열이 활성화되어 있고 아직 완료되지 않았으면 렌더링
        if (column_rows[col] >= 0 && column_rows[col] < MATRIX_HEIGHT + TAIL_LENGTH)
        {
            // 꼬리 효과: 현재 위치부터 위로 TAIL_LENGTH 개의 LED 켜기
            for (uint8_t i = 0; i < TAIL_LENGTH; i++)
            {
                int8_t tail_row = column_rows[col] - i;
                // 유효한 행 범위인지 확인
                if (tail_row >= 0 && tail_row < MATRIX_HEIGHT)
                {
                    matrix.setLed(0, tail_row, col, true);
                }
            }
        }
    }
    // 디버그 출력 (활성화된 열만)
    Serial.print("Active columns: ");
    bool has_active = false;
    for (uint8_t col = 0; col < MATRIX_WIDTH; col++)
    {
        if (column_rows[col] >= 0 && column_rows[col] < MATRIX_HEIGHT + TAIL_LENGTH)
        {
            Serial.print("C");
            Serial.print(col);
            Serial.print(":");
            Serial.print(column_rows[col]);
            Serial.print(" ");
            has_active = true;
        }
    }
    if (!has_active)
    {
        Serial.print("None");
    }
    Serial.println();
    // 각 활성화된 열의 행 위치를 DROP_HEIGHT만큼 이동
    bool all_completed = true;
    for (uint8_t col = 0; col < MATRIX_WIDTH; col++)
    {
        if (column_rows[col] >= 0 && column_rows[col] < MATRIX_HEIGHT + TAIL_LENGTH)
        {
            // 활성화되어 있고 아직 완전히 사라지지 않은 경우 이동
            column_rows[col] += DROP_HEIGHT;
            all_completed = false;
        }
    }
    // 모든 열이 완료되었으면 다시 시작
    if (all_completed)
    {
        // 모든 열 상태 초기화
        for (uint8_t col = 0; col < MATRIX_WIDTH; col++)
        {
            column_rows[col] = -1;
        }
        Serial.println();
        Serial.println("=== All columns completed! Restarting... ===");
        Serial.println();
    }
}