#include <ArduinoJson.h>
#include <DHT.h>
#include <DHT_U.h>
#include <Wire.h>
#include <Arduino_FreeRTOS.h>
#include <queue.h>

const int DHTTYPE = DHT11; //khai bao loai cam bien

//khai bao
const int motor = 2; //bom
const int led = 3;
const int speaker = 4; // loa
const int fan = 5; // quat

const int pir = 12; // cam bien hong ngoai
const int flame = 11; //cam bien lua
const int hdt = 10; // cam bien nhiet do - do am
const int light = 9; // cam bien anh sang
const int water = A0; //cam bien do am dat

char msg[50];
long lastMsg = 0;
char message;
bool priority_led = false;
bool priority_fan = false;
bool priority_speaker = false;
bool priority_motor = false;

DHT dht(hdt, DHTTYPE);
float h;
float t;
StaticJsonDocument<200> doc;
// queue
QueueHandle_t xQueue_motor;
QueueHandle_t xQueue_led;
QueueHandle_t xQueue_speaker;
QueueHandle_t xQueue_pir;

void setup()
{
  Wire.begin(8);                /* join i2c bus with address 8 */
  Wire.onReceive(receiveEvent); /* register receive event */
  Serial.begin(9600);
  xQueue_motor = xQueueCreate( 5, sizeof( int ) );
  xQueue_led = xQueueCreate( 5, sizeof( int ) );
  xQueue_speaker = xQueueCreate( 5, sizeof( int ) );
  xQueue_pir = xQueueCreate( 5, sizeof( int ) );
  if ( xQueue_led != NULL )
  {
    xTaskCreate( Sensor, "Sender", 240, NULL, 1, NULL ); // tao 2 task
    xTaskCreate( Handle, "Receiver", 240, NULL, 2, NULL );
    vTaskStartScheduler();
  }
  else
  {
    Serial.print("The queue could not be created");
  }

}

void loop()
{
  // empty
}

void Sensor( void * pvParameters )
{
  h = dht.readHumidity(); // do am
  t = dht.readTemperature(); // nhiet do
  for ( ;; )
  {
    int pir = digitalRead(pir);
    int fla = digitalRead(flame);
    int light = digitalRead(light);
    int water = analogRead(water);
    water = map(water, 0, 1023, 100, 0);
    water = (water / 65) * 100;
    xQueueSend( xQueue_led,  &light , portMAX_DELAY == pdPASS);
    xQueueSend( xQueue_motor,  &water , portMAX_DELAY == pdPASS);
    xQueueSend( xQueue_pir,  &pir , portMAX_DELAY == pdPASS);
    xQueueSend( xQueue_speaker,  &fla , portMAX_DELAY == pdPASS);
    Serial.print("Do am dat: ");
    Serial.println(water);
    Serial.print("Do am KK: ");
    Serial.print(h);
    Serial.print("% ");
    Serial.print("Nhiet do: ");
    Serial.print(t);
    Serial.println("*C ");
    Serial.println("--------------------------------");
  }
}


void Handle( void *pvParameters )
{
  int ledValue;
  int motorValue;
  int pirValue;
  int speakerValue;
 int t = dht.readTemperature(); // nhiet do
  for ( ;; )
  {

    if (xQueueReceive( xQueue_led, &ledValue, portMAX_DELAY ) == pdPASS && xQueueReceive( xQueue_pir, &pirValue, portMAX_DELAY ) == pdPASS && !priority_led)
    {
      Serial.print( "Received = ");
      Serial.println(ledValue);
      if (ledValue == 1 && pirValue == 1) {
        Serial.println("Bat den");
        digitalWrite(led, HIGH);
      }
      else {
        Serial.println("Tat den");
        digitalWrite(led, LOW);
      }
    }

    if (xQueueReceive( xQueue_motor, &motorValue, portMAX_DELAY ) == pdPASS && !priority_motor)
    {
      Serial.print( "Motor value = ");
      Serial.println(motorValue);
      if (motorValue < 65) {
        digitalWrite(motor, HIGH);
      }
      else {
        digitalWrite(motor, LOW);
      }
    }
    if (!priority_fan)
    {
      if (t > 28) {
        digitalWrite(fan, HIGH);
      }
      else {
        digitalWrite(fan, LOW);
      }
    }
    if (xQueueReceive( xQueue_speaker, &speakerValue, portMAX_DELAY ) == pdPASS && !priority_speaker)
    {
      Serial.print( "Speaker Value = ");
      Serial.println(ledValue);
      if (speakerValue == 1) {
        digitalWrite(speaker, HIGH);
      }
      else {
        digitalWrite(speaker, LOW);
      }
    }
    taskYIELD();
  }
}

// function that executes when data is received from esp
void receiveEvent(int value) {
  String data = "";
  while (0 < Wire.available()) {
    char c = Wire.read();      /* receive byte as a character */
    data += c;

  }
  Serial.println(data);
  processCall(data);         /* sau khi nhận được toàn bộ data thì vào hàm xử lý */
}

void processCall(String data) {
  DeserializationError error = deserializeJson(doc, data);

  // Test if parsing succeeds.
  if (error) {
    Serial.print(F("deserializeJson() failed: "));
    Serial.println(error.f_str());
    return;
  }

  // Fetch values
  int id = doc["digitalIo"];
  long status = doc["status"];
  bool isAuto = doc["isAuto"];

  // Print values.
  Serial.println(id);
  Serial.println(status);
  Serial.println(isAuto);

  if (id == 1) { // motor
    if (isAuto == 0) { //khi user tắt chế độ auto và bật thiết bị
      if (status == 1) {
        Serial.println("user bat may bom");
        digitalWrite(motor, HIGH);
        priority_motor = true;
      } else {
        Serial.println("user tat may bom");
        digitalWrite(motor, LOW);
        priority_motor = true;
      }
    } else
      priority_motor = false;
  }

  if (id == 2) { // den
    if (isAuto == 0) {
      if (status == 1) {
        digitalWrite(led, HIGH);
        priority_led = true;
      } else {
        digitalWrite(led, LOW);
        priority_led = true;
      }

    } else
      priority_led = false;
  }

  if (id == 3) { // loa
    if (isAuto == 0) {
      if (status == 1) {
        digitalWrite(speaker, HIGH);
        priority_speaker = true;
      } else {
        digitalWrite(speaker, LOW);
        priority_speaker = true;
      }

    } else
      priority_speaker = false;
  }

  if (id == 4) { // quat
    if (isAuto == 0) {
      if (status == 1) {
        digitalWrite(fan, HIGH);
        priority_fan = true;
      } else {
        digitalWrite(fan, LOW);
        priority_fan = true;
      }
    } else
      priority_fan = false;
  }
}