#include <LedControlMS.h>

#define NBR_MTX 3

// MAX7219 pins: DIN, CLK, CS
LedControl lc = LedControl(27, 26, 25, NBR_MTX);

// ----- Pin definitions -----
const int SENSOR_BUTTON_PIN = 33;   // shared analog pin for LDR + button
const int RELAY_PIN         = 32;   // relay control pin

// ----- Thresholds -----
// 根據剛才的監測數據先設為 500。
// 若用手電筒照射感測器時數值大於 500,代表有光;若電路特性相反,請修改下方邏輯。
const int BRIGHT_THRESHOLD  = 300;  

// ----- Relay state -----
bool relayState = false;

// ----- Button control -----
bool lastPressed = false;
unsigned long lastPressTime = 0;
const unsigned long debounceDelay = 250;

// ----- 亮度記憶 -----
bool isTooBright = false;

void setup() {
  Serial.begin(115200);
  Serial.println("System Start");

  pinMode(RELAY_PIN, OUTPUT);
  digitalWrite(RELAY_PIN, LOW);   // relay OFF initially

  // LED matrix setup
  for (int i = 0; i < NBR_MTX; i++) {
    lc.shutdown(i, false);
    lc.setIntensity(i, 8);
    lc.clearDisplay(i);
  }

  showOFF();
}

void loop() {
  int sensorValue = analogRead(SENSOR_BUTTON_PIN);

  // 考量 ESP32 類比讀取的微小雜訊,設定 <= 5 確保按鈕能穩定觸發
  bool pressed = (sensorValue <= 300);

  // 關鍵:只有在按鈕「沒有被按下」時,才讀取並更新環境亮度。
  if (!pressed) {
    isTooBright = (sensorValue > BRIGHT_THRESHOLD); 
    // 💡 注意:如果你的電路是「越亮數值越小」,請把上面的 > 改成 <
  }

  // 每 500 毫秒印一次資訊,避免 Serial 狂洗畫面導致看不清
  static unsigned long lastPrintTime = 0;
  if (millis() - lastPrintTime > 500) {
    Serial.print("Analog value: ");
    Serial.print(sensorValue);
    Serial.print(" | Bright: ");
    Serial.print(isTooBright ? "YES" : "NO");
    Serial.print(" | Button: ");
    Serial.print(pressed ? "PRESSED" : "RELEASED");
    Serial.print(" | Relay: ");
    Serial.println(relayState ? "ON" : "OFF");
    lastPrintTime = millis();
  }

  // 防彈跳與狀態切換邏輯
  if (pressed && !lastPressed && (millis() - lastPressTime > debounceDelay)) {
    lastPressTime = millis();

    // 依據題目:有接收燈光時 (isTooBright 為 true) 按按鈕才會切換
    if (isTooBright) {
      relayState = !relayState;
      updateRelayAndDisplay();

      Serial.print("Relay changed to: ");
      Serial.println(relayState ? "ON" : "OFF");
    } else {
      Serial.println("Not bright enough, button disabled.");
    }
  }

  lastPressed = pressed;
  delay(20); // 稍微縮短延遲,讓按鈕反應更靈敏
}

void updateRelayAndDisplay() {
  if (relayState) {
    digitalWrite(RELAY_PIN, HIGH);
    showON();
  } else {
    digitalWrite(RELAY_PIN, LOW);
    showOFF();
  }
}
void drawSmallPattern(const char* pattern[8]) {
  lc.clearAll();

  for (int row = 0; row < 8; row++) {
    for (int col = 0; col < 24; col++) {
      if (pattern[row][col] == '1') {
        int matrix = col / 8;
        int localCol = col % 8;
        lc.setLed(matrix, row, localCol, true);
      }
    }
  }
}

void showON() {
  const char* onPattern[8] = {
    "000000011100010001000000",
    "000000100010011001000000",
    "000000100010010101000000",
    "000000100010010011000000",
    "000000100010010001000000",
    "000000100010010001000000",
    "000000011100010001000000",
    "000000000000000000000000"
  };
  drawSmallPattern(onPattern);
}

void showOFF() {
  const char* offPattern[8] = {
    "000011100010001111110000",
    "000100010101001000010000",
    "000100010101001000010000",
    "000100010111001111100000",
    "000100010101001000010000",
    "000100010101001000010000",
    "000011100010001000010000",
    "000000000000000000000000"
  };
  drawSmallPattern(offPattern);
}
  #include <LedControlMS.h>

  #define NBR_MTX 3

  // MAX7219 pins: DIN, CLK, CS
  LedControl lc = LedControl(27, 26, 25, NBR_MTX);

  // ----- Pin definitions -----
  const int SENSOR_BUTTON_PIN = 33;   // shared analog pin for LDR + button
  const int RELAY_PIN         = 32;   // relay control pin

  // ----- Thresholds -----
  const int BUTTON_THRESHOLD  = 4000; // above this = button pressed
  const int LIGHT_MIN         = 350;  // light ON lower bound
  const int LIGHT_MAX         = 550;  // light ON upper bound

  // ----- Relay state -----
  bool relayState = false;

  // ----- Button control -----
  bool lastPressed = false;
  unsigned long lastPressTime = 0;
  const unsigned long debounceDelay = 250;

  // ----- Remember last light state -----
  bool lightDetected = false;

  void setup() {
    Serial.begin(115200);
    Serial.println("System Start");

    pinMode(RELAY_PIN, OUTPUT);
    digitalWrite(RELAY_PIN, LOW);   // relay OFF initially

    // LED matrix setup
    for (int i = 0; i < NBR_MTX; i++) {
      lc.shutdown(i, false);
      lc.setIntensity(i, 8);
      lc.clearDisplay(i);
    }

    showOFF();
  }

  void loop() {
    int sensorValue = analogRead(SENSOR_BUTTON_PIN);

    // Button pressed when analog value is above 4000
    bool pressed = (sensorValue > BUTTON_THRESHOLD);

    // Only update light state when button is NOT pressed
    // because button press changes the analog reading
    if (!pressed) {
      lightDetected = (sensorValue >= LIGHT_MIN && sensorValue <= LIGHT_MAX);
    }

    // Print status every 500 ms
    static unsigned long lastPrintTime = 0;
    if (millis() - lastPrintTime > 500) {
      Serial.print("Analog value: ");
      Serial.print(sensorValue);
      Serial.print(" | Light: ");
      Serial.print(lightDetected ? "ON" : "OFF");
      Serial.print(" | Button: ");
      Serial.print(pressed ? "PRESSED" : "RELEASED");
      Serial.print(" | Relay: ");
      Serial.println(relayState ? "ON" : "OFF");
      lastPrintTime = millis();
    }

    // Debounced button press detection
    if (pressed && !lastPressed && (millis() - lastPressTime > debounceDelay)) {
      lastPressTime = millis();

      // Only allow toggle if light is detected
      if (lightDetected) {
        relayState = !relayState;
        updateRelayAndDisplay();

        Serial.print("Relay changed to: ");
        Serial.println(relayState ? "ON" : "OFF");
      } else {
        Serial.println("Light is OFF, button disabled.");
      }
    }

    lastPressed = pressed;
    delay(20);
  }

  void updateRelayAndDisplay() {
    if (relayState) {
      digitalWrite(RELAY_PIN, HIGH);
      showON();
    } else {
      digitalWrite(RELAY_PIN, LOW);
      showOFF();
    }
  }

  void drawSmallPattern(const char* pattern[8]) {
    lc.clearAll();

    for (int row = 0; row < 8; row++) {
      for (int col = 0; col < 24; col++) {
        if (pattern[row][col] == '1') {
          int matrix = col / 8;
          int localCol = col % 8;
          lc.setLed(matrix, row, localCol, true);
        }
      }
    }
  }

  void showON() {
    const char* onPattern[8] = {
      "000000000110001010000000",
      "000000001001001110000000",
      "000000001001001010000000",
      "000000001001001010000000",
      "000000001001001010000000",
      "000000000110001010000000",
      "000000000000000000000000",
      "000000000000000000000000"
    };
    drawSmallPattern(onPattern);
  }

  void showOFF() {
    const char* offPattern[8] = {
      "000000000110001111000000",
      "000000001001001100000000",
      "000000001001001110000000",
      "000000001001001100000000",
      "000000001001001100000000",
      "000000000110001100000000",
      "000000000000000000000000",
      "000000000000000000000000"
    };
    drawSmallPattern(offPattern);
  }
#include <LedControlMS.h>

#define NBR_MTX 3

// MAX7219 pins: DIN, CLK, CS
LedControl lc = LedControl(27, 26, 25, NBR_MTX);

// ----- Pin definitions -----
const int SENSOR_BUTTON_PIN = 33;   // shared analog pin for LDR + button
const int RELAY_PIN         = 32;   // relay control pin
const int Light_Pin = 35;

// ----- Thresholds -----
const int BUTTON_THRESHOLD  = 4000; // 數值大於 4000 代表按鈕被按下
const int LIGHT_THRESHOLD   = 300;  // 數值大於 300 代表有光

// ----- Relay state -----
bool relayState = false;

// ----- Button control -----
bool lastPressed = false;
unsigned long lastPressTime = 0;
const unsigned long debounceDelay = 250;

// ----- Remember last light state -----
bool lightDetected = false;

void setup() {
  Serial.begin(115200);
  Serial.println("System Start");

  pinMode(RELAY_PIN, OUTPUT);
  pinMode(Light_Pin, INPUT);
  digitalWrite(RELAY_PIN, LOW);   // relay OFF initially

  // LED matrix setup
  for (int i = 0; i < NBR_MTX; i++) {
    lc.shutdown(i, false);
    lc.setIntensity(i, 8);    // 亮度設定 (0~15)
    lc.clearDisplay(i);
  }

  showOFF(); // 初始顯示 OFF
}

void loop() {
  int sensorValue = analogRead(SENSOR_BUTTON_PIN);
  int lightValue =   analogRead(Light_Pin);

  // 判斷是否按下按鈕 (數值大於 4000)
  bool pressed = (sensorValue > BUTTON_THRESHOLD);

  // 只有在「沒有按下按鈕」的時候,才去更新光線狀態
  if (!pressed) {
    lightDetected = (sensorValue >= LIGHT_THRESHOLD);
  }

  // 每 500ms 印出一次狀態方便觀察
  static unsigned long lastPrintTime = 0;
  if (millis() - lastPrintTime > 500) {
    Serial.print("Analog value: ");
    Serial.print(sensorValue);
    Serial.print(" | Light: ");
    Serial.print(lightDetected ? "ON" : "OFF");
    Serial.print(" | Button: ");
    Serial.print(pressed ? "PRESSED" : "RELEASED");
    Serial.print(" | Relay: ");
    Serial.println(relayState ? "ON" : "OFF");
    Serial.print(" | Light: " );
    Serial.print(lightValue);
    lastPrintTime = millis();
  }

  // 處理按鈕防彈跳與觸發邏輯
  if (pressed && !lastPressed && (millis() - lastPressTime > debounceDelay)) {
    lastPressTime = millis();

    // 只有在「有光」的狀態下,按鈕才會有反應
    if (lightDetected) {
      relayState = !relayState;
      updateRelayAndDisplay();

      Serial.print("Relay changed to: ");
      Serial.println(relayState ? "ON" : "OFF");
    } else {
      Serial.println("Light is OFF, button disabled.");
    }
  }

  lastPressed = pressed;
  delay(20);
}

void updateRelayAndDisplay() {
  if (relayState == true) {
    digitalWrite(RELAY_PIN, HIGH);
      showOFF();

  } else {
    digitalWrite(RELAY_PIN, LOW);
      showON();

  }
}

// ===== LED 顯示功能 =====

void showON() {
  // 先清空 3 塊面板
  for (int i = 0; i < NBR_MTX; i++) {
    lc.clearDisplay(i);
  }
  
  // 利用函式庫內建的字庫顯示字元
  // 參數: (第幾個矩陣, 字元在字庫中的索引)
  lc.displayChar(0, lc.getCharArrayPosition('O'));
  lc.displayChar(1, lc.getCharArrayPosition('N'));
  lc.displayChar(2, lc.getCharArrayPosition(' ')); // 第三塊留白
}

void showOFF() {
  // 先清空 3 塊面板
  for (int i = 0; i < NBR_MTX; i++) {
    lc.clearDisplay(i);
  }

  lc.displayChar(1, lc.getCharArrayPosition('O'));
  lc.displayChar(0, lc.getCharArrayPosition('F'));
  lc.displayChar(2, lc.getCharArrayPosition('F'));
}