#include <SPI.h>
#include <MFRC522.h>
#include <FastLED.h>
#include <Arduino.h>
#include <driver/ledc.h>

// RFID引脚定义
#define RFID_RST_PIN   14      // RC522 复位引脚
#define RFID_SS_PIN    10      // RC522 片选引脚
#define RFID_MISO_PIN  13      // MISO 引脚
#define RFID_MOSI_PIN  12      // MOSI 引脚
#define RFID_SCK_PIN   11      // SCK 引脚

// LED定义
#define LED_PIN_1     4       // 1颗WS2812灯珠引脚
#define LED_PIN_2     5       // 160颗WS2812灯带引脚
#define LED_PIN_3     48      // 1颗WS2812灯珠引脚（新增）
#define LED_COUNT_1   1       // 1颗灯珠
#define LED_COUNT_2   186     // 160颗灯带
#define LED_COUNT_3   1       // 1颗灯珠（新增）

// PWM定义
#define PWM_PIN       6       // PWM输出引脚
#define PWM_CHANNEL   0       // PWM通道
#define PWM_FREQ      1000    // PWM频率(Hz)
#define PWM_RESOLUTION 10     // PWM分辨率(位)
#define DEFAULT_DUTY  819     // 默认占空比(80%)

// 按钮和输入引脚定义
#define BTN0_PIN      15      // 按钮0引脚
#define WAKEUP1_PIN   16      // 唤醒引脚1
#define BTN1_PIN      17      // 按钮1引脚
#define BTN2_PIN      18      // 按钮2引脚

// 任务句柄
TaskHandle_t TaskRFID, TaskLED1, TaskLED2, TaskLED3, TaskPWM, TaskBTN0, TaskWAKEUP1, TaskBTN1, TaskBTN2;

// 全局变量
MFRC522 rfid(RFID_SS_PIN, RFID_RST_PIN);  // 创建RFID实例
CRGB leds1[LED_COUNT_1];                   // 1颗灯珠数组
CRGB leds2[LED_COUNT_2];                   // 160颗灯带数组
CRGB leds3[LED_COUNT_3];                   // 1颗灯珠数组（新增）
String lastCardData = "";                  // 上次读取的RFID卡数据
int ledMode = 1;                           // 灯带模式，默认为1(白色)
int pwmDuty = DEFAULT_DUTY;                // PWM占空比
bool btn0State = HIGH;                     // 按钮0状态
bool btn0LongPress = false;                // 按钮0长按标志
bool wakeup1State = LOW;                   // 唤醒引脚1状态
bool btn1State = LOW;                      // 按钮1状态
bool btn2State = LOW;                      // 按钮2状态
int singleLedMode = 7;                     // 单颗LED模式，默认为7(白色)

// 灯带动画全局变量
static uint8_t rainbowHue = 0;
static int trainPos = 0;
static unsigned long lastUpdate = 0;
static const int TRAIN_LENGTH = 16;        // 火车灯长度
static int trainPhase = 0;                 // 火车阶段：0-正向出站，1-正向前进，2-正向进站，3-反向出站，4-反向前进，5-反向进站
static const int VIRTUAL_LED_COUNT = LED_COUNT_2 + TRAIN_LENGTH; // 虚拟灯带长度

// 单颗LED颜色数组
CRGB singleLedColors[8] = {
  CRGB::Black,      // 0: 熄灭
  CRGB::Blue,       // 1: 蓝色
  CRGB::Green,      // 2: 绿色
  CRGB::Orange,     // 3: 橙色
  CRGB::Red,        // 4: 红色
  CRGB::Purple,     // 5: 紫色
  CRGB::Yellow,     // 6: 黄色
  CRGB::White       // 7: 白色
};

// RFID读取任务
void TaskRFIDcode( void * pvParameters ) {
  for(;;) {
    // 寻找新卡片
    if ( ! rfid.PICC_IsNewCardPresent()) {
      delay(10);
      continue;
    }
    
    // 验证NUID是否可读
    if ( ! rfid.PICC_ReadCardSerial()) {
      delay(10);
      continue;
    }
    
    // 读取卡片数据（用户数据区）
    String cardData = "";
    MFRC522::MIFARE_Key key;
    
    // 准备认证密钥
    for (byte i = 0; i < 6; i++) key.keyByte[i] = 0xFF;
    
    // 选择卡片
    MFRC522::StatusCode status;
    status = rfid.PCD_Authenticate(MFRC522::PICC_CMD_MF_AUTH_KEY_A, 4, &key, &(rfid.uid));
    if (status != MFRC522::STATUS_OK) {
      Serial.print(F("Authentication failed: "));
      Serial.println(rfid.GetStatusCodeName(status));
      rfid.PICC_HaltA();
      rfid.PCD_StopCrypto1();
      delay(100);
      continue;
    }
    
    // 读取数据块
    byte buffer[18];
    byte size = sizeof(buffer);
    status = rfid.MIFARE_Read(4, buffer, &size);
    if (status != MFRC522::STATUS_OK) {
      Serial.print(F("Reading failed: "));
      Serial.println(rfid.GetStatusCodeName(status));
    } else {
      // 转换为ASCII字符串
      for (byte i = 0; i < 16; i++) {
        if (buffer[i] >= 32 && buffer[i] <= 126) { // 可打印ASCII字符
          cardData += (char)buffer[i];
        }
      }
      
      // 移除空白字符
      cardData.trim();
      
      // 卡片数据处理
      if (cardData != lastCardData && !cardData.isEmpty()) {
        lastCardData = cardData;
        Serial.println("SORC_" + cardData);
      }
    }
    
    // 使放置在读卡区的IC卡进入休眠状态，不再重复读卡
    rfid.PICC_HaltA();
    
    // 停止加密PCD
    rfid.PCD_StopCrypto1();
    
    delay(100);
  }
}

// LED1控制任务
void TaskLED1code( void * pvParameters ) {
  for(;;) {
    // 根据模式设置LED1颜色
    if (singleLedMode >= 0 && singleLedMode <= 7) {
      leds1[0] = singleLedColors[singleLedMode];
    } else {
      leds1[0] = CRGB::Blue; // 默认白色
    }
    
    // 更新LED
    FastLED.show();
    
    delay(20);
  }
}

// LED3控制任务（新增）
void TaskLED3code( void * pvParameters ) {
  for(;;) {
    // 强制设置GPIO48的灯珠为熄灭状态
    leds3[0] = CRGB::Black;
    
    // 更新LED
    FastLED.show();
    
    delay(20);
  }
}

// LED2控制任务
void TaskLED2code( void * pvParameters ) {
  for(;;) {
    // 根据不同模式控制灯带
    switch(ledMode) {
      case 0: // 全部熄灭
        fill_solid(leds2, LED_COUNT_2, CRGB::Black);
        break;
        
      case 1: // 纯白色
        fill_solid(leds2, LED_COUNT_2, CRGB::White);
        break;
        
      case 2: // 彩虹流水灯
        for(int i = 0; i < LED_COUNT_2; i++) {
          leds2[i] = CHSV(rainbowHue + i * 256 / LED_COUNT_2, 255, 255);
        }
        rainbowHue++;
        break;
        
      case 3: // 彩虹呼吸灯
        for(int i = 0; i < LED_COUNT_2; i++) {
          leds2[i] = CHSV(rainbowHue, 255, beatsin8(1, 64, 255));
        }
        rainbowHue++;
        break;
        
      case 4: // 彩虹火车灯
        if (millis() - lastUpdate > 30) { // 30ms更新一次
          lastUpdate = millis();
          
          // 清除所有灯珠
          fill_solid(leds2, LED_COUNT_2, CRGB::Black);
          
          switch (trainPhase) {
            case 0: // 正向出站（从起点开始出现）
              for (int i = 0; i < TRAIN_LENGTH; i++) {
                int pos = trainPos + i;
                if (pos >= 0 && pos < LED_COUNT_2) {
                  uint8_t hue = rainbowHue + (i * 256 / TRAIN_LENGTH);
                  leds2[pos] = CHSV(hue, 255, 255);
                }
              }
              
              trainPos += 1;
              
              // 检查是否完全出站
              if (trainPos >= 0) {
                trainPhase = 1; // 开始正向前进
                trainPos = 0;
              }
              break;
              
            case 1: // 正向前进
              for (int i = 0; i < TRAIN_LENGTH; i++) {
                int pos = trainPos + i;
                if (pos >= 0 && pos < LED_COUNT_2) {
                  uint8_t hue = rainbowHue + (i * 256 / TRAIN_LENGTH);
                  leds2[pos] = CHSV(hue, 255, 255);
                }
              }
              
              trainPos += 1;
              
              // 检查是否到达终点
              if (trainPos >= LED_COUNT_2 - TRAIN_LENGTH) {
                trainPhase = 2; // 开始正向进站
                trainPos = LED_COUNT_2 - TRAIN_LENGTH;
              }
              break;
              
            case 2: // 正向进站（从尾部开始消失）
              for (int i = 0; i < TRAIN_LENGTH; i++) {
                int displayPos = LED_COUNT_2 - 1 - i;
                if (displayPos >= trainPos) {
                  uint8_t hue = rainbowHue + (i * 256 / TRAIN_LENGTH);
                  leds2[displayPos] = CHSV(hue, 255, 255);
                }
              }
              
              trainPos += 1;
              
              // 检查是否完全进站
              if (trainPos >= LED_COUNT_2) {
                trainPhase = 3; // 开始反向出站
                trainPos = 0;
                rainbowHue += 64; // 改变彩虹颜色
              }
              break;
              
            case 3: // 反向出站（从终点开始出现）
              for (int i = 0; i < trainPos + 1; i++) {
                int pos = LED_COUNT_2 - 1 - i;
                if (pos >= 0) {
                  uint8_t hue = rainbowHue + ((TRAIN_LENGTH - 1 - i) * 256 / TRAIN_LENGTH);
                  leds2[pos] = CHSV(hue, 255, 255);
                }
              }
              
              trainPos += 1;
              
              // 检查是否完全出站
              if (trainPos >= TRAIN_LENGTH) {
                trainPhase = 4; // 开始反向前进
                trainPos = TRAIN_LENGTH;
              }
              break;
              
            case 4: // 反向前进
              for (int i = 0; i < TRAIN_LENGTH; i++) {
                int pos = LED_COUNT_2 - trainPos + i;
                if (pos >= 0 && pos < LED_COUNT_2) {
                  uint8_t hue = rainbowHue + ((TRAIN_LENGTH - 1 - i) * 256 / TRAIN_LENGTH);
                  leds2[pos] = CHSV(hue, 255, 255);
                }
              }
              
              trainPos += 1;
              
              // 检查是否到达起点
              if (trainPos >= LED_COUNT_2) {
                trainPhase = 5; // 开始反向进站
                trainPos = 0;
              }
              break;
              
            case 5: // 反向进站（从头部开始消失）
              for (int i = 0; i < TRAIN_LENGTH - trainPos; i++) {
                int pos = i;
                if (pos < LED_COUNT_2) {
                  uint8_t hue = rainbowHue + ((TRAIN_LENGTH - 1 - i) * 256 / TRAIN_LENGTH);
                  leds2[pos] = CHSV(hue, 255, 255);
                }
              }
              
              trainPos += 1;
              
              // 检查是否完全进站
              if (trainPos >= TRAIN_LENGTH) {
                trainPhase = 0; // 重新开始正向出站
                trainPos = -TRAIN_LENGTH;
                rainbowHue += 64; // 改变彩虹颜色
              }
              break;
          }
        }
        break;
        
      case 5: // 马卡龙火车灯（保留原功能，未修改）
        // 代码保持不变...
        break;
    }
    
    // 更新LED
    FastLED.show();
    
    // 根据模式调整延时
    if (ledMode == 4 || ledMode == 5) {
      delay(10); // 火车灯模式需要更快的更新速度
    } else {
      delay(30);
    }
  }
}

// PWM控制任务
void TaskPWMcode( void * pvParameters ) {
  for(;;) {
    // 设置PWM占空比
    ledc_set_duty(LEDC_LOW_SPEED_MODE, (ledc_channel_t)PWM_CHANNEL, pwmDuty);
    ledc_update_duty(LEDC_LOW_SPEED_MODE, (ledc_channel_t)PWM_CHANNEL);
    
    delay(100);
  }
}

// 按钮0检测任务
void TaskBTN0code( void * pvParameters ) {
  static unsigned long pressStartTime = 0;
  static bool lastState = HIGH;
  
  for(;;) {
    bool currentState = digitalRead(BTN0_PIN);
    
    // 检测下降沿(按下)
    if (lastState == HIGH && currentState == LOW) {
      pressStartTime = millis();
      btn0State = LOW;
      Serial.println("SO_BT0_HIGH");
      btn0LongPress = false;
    } 
    // 检测上升沿(释放)
    else if (lastState == LOW && currentState == HIGH) {
      btn0State = HIGH;
      Serial.println("SO_BT0_LOW");
      btn0LongPress = false;
    }
    // 检测长按
    else if (currentState == LOW && millis() - pressStartTime >= 2000 && !btn0LongPress) {
      btn0LongPress = true;
      Serial.println("SO_BT0_HIGHL");
    }
    
    lastState = currentState;
    delay(10);
  }
}

// WAKEUP1检测任务
void TaskWAKEUP1code( void * pvParameters ) {
  static bool lastState = LOW;
  
  for(;;) {
    bool currentState = digitalRead(WAKEUP1_PIN);
    
    // 检测上升沿
    if (lastState == LOW && currentState == HIGH) {
      wakeup1State = HIGH;
      Serial.println("SO_WAKEUP1");
    } 
    // 检测下降沿
    else if (lastState == HIGH && currentState == LOW) {
      wakeup1State = LOW;
      Serial.println("SO_WAKEUP0");
    }
    
    lastState = currentState;
    delay(10);
  }
}

// 按钮1检测任务
void TaskBTN1code( void * pvParameters ) {
  static bool lastState = LOW;
  
  for(;;) {
    bool currentState = digitalRead(BTN1_PIN);
    
    // 检测上升沿
    if (lastState == LOW && currentState == HIGH) {
      btn1State = HIGH;
      Serial.println("SO_BT1_HIGH");
    } 
    // 检测下降沿
    else if (lastState == HIGH && currentState == LOW) {
      btn1State = LOW;
      Serial.println("SO_BT1_LOW");
    }
    
    lastState = currentState;
    delay(10);
  }
}

// 按钮2检测任务
void TaskBTN2code( void * pvParameters ) {
  static bool lastState = LOW;
  
  for(;;) {
    bool currentState = digitalRead(BTN2_PIN);
    
    // 检测上升沿
    if (lastState == LOW && currentState == HIGH) {
      btn2State = HIGH;
      Serial.println("SO_BT2_HIGH");
    } 
    // 检测下降沿
    else if (lastState == HIGH && currentState == LOW) {
      btn2State = LOW;
      Serial.println("SO_BT2_LOW");
    }
    
    lastState = currentState;
    delay(10);
  }
}

// 串口命令处理
void handleSerialCommand() {
  static String command = "";
  
  while (Serial.available()) {
    char c = Serial.read();
    if (c == '\n') {
      // 处理命令
      if (command.startsWith("MO_LED_")) {
        String modeStr = command.substring(7);
        int newMode = modeStr.toInt();
        
        // 控制单颗LED
        if (newMode >= 0 && newMode <= 7) {
          singleLedMode = newMode;
          Serial.print("Single LED set to mode: ");
          Serial.println(newMode);
        } else {
          Serial.println("Invalid single LED mode command");
        }
      } 
      else if (command.startsWith("MO_LEDN_")) {
        String modeStr = command.substring(8);
        int newMode = modeStr.toInt();
        
        // 控制灯带
        if (newMode >= 0 && newMode <= 5) {
          ledMode = newMode;
          
          // 重置火车灯状态
          if (newMode == 4) {
            trainPos = -TRAIN_LENGTH;
            trainPhase = 0;
            rainbowHue = random8();
          }
          
          Serial.print("LED strip set to mode: ");
          Serial.println(newMode);
        } else {
          Serial.println("Invalid LED strip mode command");
        }
      }
      else if (command.startsWith("MO_PWM_")) {
        String dutyStr = command.substring(7);
        int newDuty = dutyStr.toInt();
        
        // 检查PWM百分比
        if (newDuty == 1) {
          pwmDuty = 1023; // 100%
        } else if (newDuty == 0 || newDuty == 20 || newDuty == 40 || newDuty == 60 || newDuty == 80) {
          pwmDuty = (newDuty * 1023) / 100; // 转换为实际占空比
        } else {
          Serial.println("Invalid PWM command");
        }
        
        Serial.print("PWM set to: ");
        Serial.print((pwmDuty * 100) / 1023);
        Serial.println("%");
      }
      
      // 清空命令
      command = "";
    } else {
      command += c;
    }
  }
}

void setup() {
  // 初始化串口
  Serial.begin(115200);
  Serial.println("System starting...");
  
  // 初始化SPI总线
  SPI.begin(RFID_SCK_PIN, RFID_MISO_PIN, RFID_MOSI_PIN, RFID_SS_PIN);
  
  // 初始化RFID
  rfid.PCD_Init();
  Serial.println("RFID initialized.");
  
  // 初始化LED
  FastLED.addLeds<WS2812, LED_PIN_1, GRB>(leds1, LED_COUNT_1);
  FastLED.addLeds<WS2812, LED_PIN_2, GRB>(leds2, LED_COUNT_2);
  FastLED.addLeds<WS2812, LED_PIN_3, GRB>(leds3, LED_COUNT_3); // 新增LED3
  
  // 初始化LED状态
  fill_solid(leds1, LED_COUNT_1, singleLedColors[singleLedMode]);
  fill_solid(leds2, LED_COUNT_2, CRGB::White);
  fill_solid(leds3, LED_COUNT_3, CRGB::Black); // 强制GPIO48的灯珠熄灭
  FastLED.show();
  Serial.println("LED initialized.");
  
  // 初始化PWM
  // 创建LED控制器配置
  ledc_timer_config_t ledc_timer = {
    .speed_mode = LEDC_LOW_SPEED_MODE,
    .duty_resolution = (ledc_timer_bit_t)PWM_RESOLUTION,
    .timer_num = (ledc_timer_t)PWM_CHANNEL,
    .freq_hz = PWM_FREQ,
    .clk_cfg = LEDC_AUTO_CLK
  };
  ledc_timer_config(&ledc_timer);
  
  // 创建LED通道配置
  ledc_channel_config_t ledc_channel = {
    .gpio_num = PWM_PIN,
    .speed_mode = LEDC_LOW_SPEED_MODE,
    .channel = (ledc_channel_t)PWM_CHANNEL,
    .intr_type = LEDC_INTR_DISABLE,
    .timer_sel = (ledc_timer_t)PWM_CHANNEL,
    .duty = 0,
    .hpoint = 0
  };
  ledc_channel_config(&ledc_channel);
  
  // 设置初始占空比
  ledc_set_duty(LEDC_LOW_SPEED_MODE, (ledc_channel_t)PWM_CHANNEL, pwmDuty);
  ledc_update_duty(LEDC_LOW_SPEED_MODE, (ledc_channel_t)PWM_CHANNEL);
  
  Serial.println("PWM initialized.");
  
  // 初始化输入引脚
  pinMode(BTN0_PIN, INPUT_PULLUP);
  pinMode(WAKEUP1_PIN, INPUT);
  pinMode(BTN1_PIN, INPUT);
  pinMode(BTN2_PIN, INPUT);
  Serial.println("Inputs initialized.");
  
  // 创建任务
  xTaskCreatePinnedToCore(
    TaskRFIDcode,   /* 任务函数 */
    "TaskRFID",     /* 任务名称 */
    4096,           /* 任务栈大小 */
    NULL,           /* 传递给任务的参数 */
    1,              /* 任务优先级 */
    &TaskRFID,      /* 任务句柄 */
    1);             /* 运行在核心1上 */
  
  xTaskCreatePinnedToCore(
    TaskLED1code,
    "TaskLED1",
    2048,
    NULL,
    1,
    &TaskLED1,
    1);
  
  xTaskCreatePinnedToCore(
    TaskLED2code,
    "TaskLED2",
    4096,
    NULL,
    1,
    &TaskLED2,
    1);
  
  xTaskCreatePinnedToCore(
    TaskLED3code,
    "TaskLED3",
    2048,
    NULL,
    1,
    &TaskLED3,
    1); // 新增LED3任务
  
  xTaskCreatePinnedToCore(
    TaskPWMcode,
    "TaskPWM",
    1024,
    NULL,
    1,
    &TaskPWM,
    1);
  
  xTaskCreatePinnedToCore(
    TaskBTN0code,
    "TaskBTN0",
    2048,
    NULL,
    1,
    &TaskBTN0,
    0);
  
  xTaskCreatePinnedToCore(
    TaskWAKEUP1code,
    "TaskWAKEUP1",
    2048,
    NULL,
    1,
    &TaskWAKEUP1,
    0);
  
  xTaskCreatePinnedToCore(
    TaskBTN1code,
    "TaskBTN1",
    2048,
    NULL,
    1,
    &TaskBTN1,
    0);
  
  xTaskCreatePinnedToCore(
    TaskBTN2code,
    "TaskBTN2",
    2048,
    NULL,
    1,
    &TaskBTN2,
    0);
  
  Serial.println("Tasks created. System ready.");
}

void loop() {
  // 处理串口命令
  handleSerialCommand();
  
  // 让出CPU时间
  delay(1);
}