#include <Wire.h>
#include <Adafruit_NeoPixel.h>
#include <LiquidCrystal_I2C.h>
#define PIN           A0  // 修改为A0作为数据引脚 It is modified to A0 as the data pin
#define NUMPIXELS     30  // 修改LED的数量为12 The number of leds is modified to 12
#define buttonPin     2   // 按钮引脚 Button pin
#define Light         A3  // 光敏电阻检测引脚 Photoresistor detection pin

int buttonState;                      // 按钮状态 Button status
int lastButtonState = HIGH;           // 上一次的按钮状态 The last button state
bool Recording_time_switch;           // 记录时间的开关 A switch to record time
unsigned long lastDebounceTime = 0;   // 上一次的稳定时间 Last settling time
unsigned long debounceDelay = 20;     // 按键防抖延时 Key stabilization delay
unsigned long longPressDelay = 500;   // 长按时间阈值 Long press time threshold```
int color_mode = 0;       //灯光颜色模式 Light color mode
int sensorValue1;         //用于存储读取的电压值 Used to store the voltage value of the read
int Light_mode= 0;        //白天或者夜晚模式 Day or night mode
bool Light_switch = 0;    //灯光开关 Light switch
bool one_step = 0;        //只执行一步操作 Perform a single operation

LiquidCrystal_I2C lcd(0x27, 16, 2); // 设置I2C地址为0x27，LCD有16列和2行 The I2C address is set to 0x27 and the LCD has 16 columns and 2 rows

Adafruit_NeoPixel strip = Adafruit_NeoPixel(NUMPIXELS, PIN, NEO_GRB + NEO_KHZ800);

void setup() {
  strip.begin();        // 初始化NeoPixel库 Initialize the NeoPixel library
  strip.show();         // 初始化时关闭所有LED按键被按下 Initialize when turn off all LED keys are pressed
  Serial.begin(9600);   // 初始化串口 Initialize the serial port
  lcd.init();           // 初始化LCD Initialize LCD
  lcd.backlight(); 
  lcd.clear();                      // 清除LCD屏幕内容 Clear the LCD screen contents
  lcd.setCursor(5, 0);              // 设置光标位置为第二行第一列 Set the cursor position to the second row, first column
  lcd.print("Merry");     // 在LCD上打印 "Merry Christmas" Print "Merry Christmas" on LCD
  lcd.setCursor(3, 1);              // 设置光标位置为第一行第一列 Set the cursor position to the first row and column
  lcd.print("Christmas");           // 在LCD上打印 "Christmas" Print "Christmas" on the LCD
  // 在此处可以设置亮度
  strip.setBrightness(100);
  pinMode(buttonPin, INPUT_PULLUP); //配置按键为上拉输入 The configuration button is a pull-up input
  pinMode(Light, INPUT);            //设置为输入引脚 Set to the input pin
}

void loop() {
  sensorValue1 = analogRead(Light);
  if(sensorValue1 >= 800){  //检测环境亮度 如过检测数值大于800 Detect ambient brightness such as over-detection value greater than 800
    Light_mode = 0;         //设定为模式0，即夜间 Set to mode 0, which is night
  }else{
    Light_mode = 1;         //设定为模式1，即白天 Set to mode 1, which is daytime
  }
  Serial.println(sensorValue1); //打印光敏电阻器A3引脚输入值

  if(Light_mode == 0){          //模式0，夜间模式 Mode 0, night mode
      if(one_step == 0){        //判断如果上一步为0，执行操作 Determine if the previous step is 0, perform the action
          color_mode = 5;       //将所有LED的颜色设置为黄色 Set the color of all leds to yellow
          one_step = 1;         //设置为1，防止再次执行该段函数 Set to 1 to prevent the function from being executed again
          Light_switch = 1;     //将灯光状态标记为打开 Mark the light state as on
      }
  }else if(Light_mode == 1){    //亮度高、白天 High brightness, daytime
      if(one_step == 1){        //判断如果上一步为1，执行一次操作 Determine if the previous step is 1, perform an action
          color_mode = 0;       //将所有LED关闭 Turn off all leds
          one_step = 0;         //设置为0，防止再次执行该段函数 Set to 0 to prevent the function from being executed again
          Light_switch = 0;     //将灯光状态标记为关闭 Mark the light state as off
      }
  }
  
  int reading = digitalRead(buttonPin); //读取按键状态，将按键状态保存到reading函数 Read the state of the key pressed and save the state to the reading function
  if (reading != lastButtonState) {     //如果reading不等于上一次的按钮状态 If reading is not equal to the last button state
    if(Recording_time_switch == 0){     //判断Recording_time_switch是否为0 Determine whether Recording_time_switch is 0
      lastDebounceTime = millis();      //读取一次当前计时保存到lastDebounceTime Read the current timer once and save it to lastDebounceTime
      Recording_time_switch = 1;        //设置Recording_time_switch等于1，防止重复读取当前计时 Recording_time_switch is set to 1 to prevent the current timer from being read again
    }
  }

  if ((millis() - lastDebounceTime) > debounceDelay) {  //如果按下的时间，超过20ms  If pressed for time, more than 20ms
    if (reading != buttonState) {                       //如果读取按键状态不等于buttonState  If reading the state of the key is not equal to buttonState
      buttonState = reading;                            //将reading赋值到buttonState  Assign reading to buttonState
      if (buttonState == LOW) {                         //如果如果buttonState等于低电平，按键按下等于低电平，按键按下  If if buttonState is equal to low, key press is equal to low, key press
        // Serial.println("Button Pressed");
      } else {  //如果buttonState等于高电平，按键松开  If buttonState is equal to high, release the key
        // Serial.println("Button Released");

        // 判断按键按下的时间，执行单击或长按操作
        if ((millis() - lastDebounceTime) < longPressDelay) { //如果按下的时间小于设定的500ms，为短按  If the press time is less than the set 500ms, it is a short press
          Recording_time_switch = 0;                          //将Recording_time_switch设置为0，等待下一次按键按下，再读取当前系统时间  It sets Recording_time_switch to 0 and waits for the next key press before reading the current system time
          if(Light_switch == 1){                              //如果灯光状态标记为打开状态  If the light state is marked as on
            color_mode++;                                     //逐一递增，切换灯光状态  Increment one by one, switching the light state
            if(color_mode > 5){                               //限制灯光状态在1-5范围内  Limit the light state to 1-5
            color_mode =1;
            }
          }
        } else {                                            //按下时间大于500ms，为长按  If the press time is longer than 500ms, it is a long press
          Recording_time_switch = 0;                        //将Recording_time_switch设置为0，等待下一次按键按下，再读取当前系统时间  It sets Recording_time_switch to 0 and waits for the next key press before reading the current system time
          Light_switch = !Light_switch;                     //切换灯光状态标记  Toggle the light state marker
          if(Light_switch == 0){                            //如果灯光状态标记为关闭  If the light state is marked off
            color_mode = 0;                                 //关闭灯光  Turn off the lights
          }else if(Light_switch == 1){                      //如果灯光状态标记为打开  If the light state is marked as on
            if(Light_mode == 0){                            //判断是否为夜间  Determine if it is nighttime
              color_mode = 5;                               //切换为4暖光灯  Switch to 5 warm light
            }else{
              color_mode = 1;                               //切换到1红光  Switch to 1 red light
            }
          }
        }
      }
    }
  }
  lastButtonState = reading;  //在下一次循环迭代时保留前一次按钮的状态 The state of the previous button is retained for the next iteration of the loop

  //判断该显示的颜色
  if(color_mode == 0){
    // 将所有RGB关闭
    colorWipe(strip.Color(0, 0, 0), 1); // 1mm延时
  }else if(color_mode == 1){
    // 将所有RGB的颜色设置为红色  Set the color of all RGBs to red
    colorWipe(strip.Color(255, 0, 0), 1);
  }else if(color_mode == 2){
    // 将所有RGB的颜色设置为绿色  Set the color of all RGBs to green
    colorWipe(strip.Color(0, 255, 0), 1);
  }else if( color_mode == 3){
    // 将所有RGB的颜色设置为蓝色  Set the color of all RGBs to blue
    colorWipe(strip.Color(0, 0, 255), 1);
  }else if(color_mode == 4){
    // 将所有RGB的颜色设置为白色  Set the color of all RGBs to white
    colorWipe(strip.Color(100, 100, 100), 1);
  }else if(color_mode == 5){
    // 将所有RGB的颜色设置为黄色  Set the color of all RGBs to yellow
    colorWipe(strip.Color(180, 75, 0), 1);
  }
}
// 使所有RGB为指定颜色  Set all RGB to the specified color
void colorWipe(uint32_t color, int wait) {
  for(int i=0; i<strip.numPixels(); i++) {
    strip.setPixelColor(i, color);
    strip.show();
    delay(wait);
  }
}
