#include <Arduino_FreeRTOS.h>
#include <queue.h>

// Định nghĩa stack size cho các task
#define STACK_SIZE 250

// Định nghĩa priority cho các task
#define TASK_PRIORITY (tskIDLE_PRIORITY + 1)

// Khai báo handle cho các task
TaskHandle_t HTask1, HTask2;

// Khai báo hàng đợi
QueueHandle_t Queue;

// Định nghĩa các chuỗi cần gửi
const char *messages[] = { "CT05-Hello", "DT04-Hi", "AT17-Welcome" };

// Task1 gửi các chuỗi vào hàng đợi
void Task1(void *pvParameters) {
  // Tạo hàng đợi có thể chứa tối đa 6 phần tử, mỗi phần tử là một chuỗi ký tự 20 ký tự
  Queue = xQueueCreate(6, sizeof(char) * 20);
  if (Queue == NULL) {
    // Nếu không thể tạo hàng đợi, in thông báo lỗi và xóa task
    Serial.println("Không thể tạo hàng đợi.");
    vTaskDelete(NULL);
  }

  // Lần lượt gửi các chuỗi vào hàng đợi
  for (int i = 0; i < 3; i++) {
    if (xQueueSend(Queue, (void *) messages[i], portMAX_DELAY) != pdPASS) {
      // Nếu gửi chuỗi thất bại, in thông báo lỗi
      Serial.println("Gửi chuỗi thất bại.");
    }
  }

  // Xóa task sau khi hoàn thành việc gửi chuỗi
  vTaskDelete(NULL);
}

// Task2 đọc các chuỗi từ hàng đợi và in ra màn hình
void Task2(void *pvParameters) {
  char buffer[20]; // Buffer để lưu trữ chuỗi nhận được từ hàng đợi
  UBaseType_t itemsCount, spacesLeft; // Biến để lưu trữ số phần tử có thể đọc và không gian còn lại trong hàng đợi

  while (1) {
    // Nhận chuỗi từ hàng đợi, chờ đợi vô hạn nếu hàng đợi rỗng
    if (xQueueReceive(Queue, buffer, portMAX_DELAY) == pdPASS) {
      // Đếm số phần tử có thể đọc từ hàng đợi
      itemsCount = uxQueueMessagesWaiting(Queue);
      // Đếm không gian khả dụng còn lại trong hàng đợi
      spacesLeft = uxQueueSpacesAvailable(Queue);

      // In chuỗi nhận được và thông tin về hàng đợi ra màn hình
      Serial.print("Nhận chuỗi: ");
      Serial.println(buffer);
      Serial.print("Số phần tử có thể đọc: ");
      Serial.println(itemsCount);
      Serial.print("Không gian khả dụng còn lại: ");
      Serial.println(spacesLeft);
    }
  }
}

void setup() {
  // Khởi tạo Serial để giao tiếp với máy tính
  Serial.begin(9600);

  // Tạo Task1 với tên "Task1", kích thước stack là 250, độ ưu tiên cao hơn mức nhàn rỗi
  xTaskCreate(Task1, "Task1", STACK_SIZE, NULL, TASK_PRIORITY, &HTask1);
  // Tạo Task2 với tên "Task2", kích thước stack là 250, độ ưu tiên cao hơn mức nhàn rỗi
  xTaskCreate(Task2, "Task2", STACK_SIZE, NULL, TASK_PRIORITY, &HTask2);

  // Khởi động scheduler để bắt đầu thực hiện các task
  vTaskStartScheduler();
}

void loop() {
  // Không cần dùng loop trong FreeRTOS
}