// Inisialisasi untuk struct dan fields nya
struct dataStruct
{
  int id;
  int value;
} dataStruct;

// Pembuatan queue, pendefinisian terdapat pada setup()
QueueHandle_t xQueue;

void Sender(void *pvParameters)
{
  // Deklarasi struct untuk mengirim data
  struct dataStruct dataSent;

  // Saat pertama kali dijalankan, nilai id harus 0
  dataSent.id = 0;

  while (1)
  {
    // Pengacakkan nilai dari value yang ingin dikirim
    dataSent.value = random(1, 1000);

    // Mencoba mengirim, jika gagal maka akan mengeluarkan error
    if (xQueueSend(xQueue, (void *)&dataSent, portMAX_DELAY) != pdPASS)
    {
      Serial.println("Failed to send data!");
    }

    // Increment id
    dataSent.id += 1;

    // Delay 1000 ms
    vTaskDelay(1000 / portTICK_PERIOD_MS);
  }
}

void Receiver(void *pvParameters)
{
  // Deklarasi struct untuk menerima data
  struct dataStruct dataReceived;

  while (1)
  {
    // Jika berhasil menerima, maka printout value
    if (xQueueReceive(xQueue, &dataReceived, portMAX_DELAY))
    {
      Serial.print("ID : ");
      Serial.println(dataReceived.id); // Print the received value
      Serial.print("Random Value : ");
      Serial.println(dataReceived.value);
    }
  }
}

void setup()
{
  // Inisialisasi serial monitor
  Serial.begin(115200);

  // Pendeklarasian queue dan tipe data untuk queue
  xQueue = xQueueCreate(1, sizeof(struct dataStruct));

  // Keluarkan error jika queue tidak berhasil dibuat
  if (xQueue == NULL)
  {
    Serial.println("Unable to create queue!");
  }

  // Pembuatan task sesuai dengan kedua fungsionalitas fungsi-fungsi di atas
  xTaskCreatePinnedToCore(Sender, "Sender", 10000, NULL, 1, NULL, 1);
  xTaskCreatePinnedToCore(Receiver, "Receiver", 10000, NULL, 1, NULL, 1);

  // Menghapus task pada setup() untuk membebaskan memori
  vTaskDelete(NULL);
}

void loop()
{
  // Useless lmao
}