#include <ArduinoJson.h>
#include <JsonLogic.h>

using json_logic::Json;
using json_logic::JsonLogic;

void setup()
{
  Serial.begin(115200);
  delay(1000);

  // MessagePack input string.
  uint8_t input[] = {131, 166, 115, 101, 110, 115, 111, 114, 163, 103, 112, 115,
                     164, 116, 105, 109, 101, 206, 80,  147, 50,  248, 164, 100,
                     97,  116, 97,  146, 203, 64,  72,  96,  199, 58,  188, 148,
                     112, 203, 64,  2,   106, 146, 230, 33,  49,  169};
  // This MessagePack document contains:
  // {
  //   "sensor": "gps",
  //   "time": 1351824120,
  //   "data": [48.75608, 2.302038]
  // }

  Json data;
  const DeserializationError inputError =
      deserializeMsgPack(data, input, sizeof(input));
  if (inputError)
  {
    Serial.print("MessagePack deserialization failed: ");
    Serial.println(inputError.c_str());
    return;
  }

  // Match GPS readings after the cutoff inside a small geographic bounding box.
  Json rule;
  const DeserializationError ruleError = deserializeJson(
      rule,
      R"({"and":[{"===":[{"var":"sensor"},"gps"]},{">=":[{"var":"time"},1351824000]},{"<":[48.7,{"var":"data.0"},48.8]},{"<":[2.2,{"var":"data.1"},2.4]}]})");
  if (ruleError)
  {
    Serial.print("Rule deserialization failed: ");
    Serial.println(ruleError.c_str());
    return;
  }

  JsonLogic* engine = JsonLogic::GetInstance();
  const Json result = engine->Apply(rule, data);
  if (engine->HasError())
  {
    Serial.print("Rule evaluation failed: ");
    Serial.println(engine->GetLastError().c_str());
    return;
  }

  Serial.print("Rule matched: ");
  Serial.println(result.as<bool>() ? "true" : "false");

  uint8_t output[1] = {};
  const size_t outputSize = serializeMsgPack(result, output, sizeof(output));
  Serial.print("MessagePack result: 0x");
  if (output[0] < 0x10) Serial.print('0');
  Serial.println(output[0], HEX);
  Serial.print("Bytes written: ");
  Serial.println(outputSize);
}

void loop()
{
}
