#include <Arduino.h>
#include <RCSwitch.h>
#include "Dht.h"
#include "RC.h"
#include "Protocol_1.h"
#include "Protocol_2.h"
#include "output.h"
#include <SerialReader.h>

#define RESET_PIN 10
#define SEND_PIN 11
#define RECEIVE_PIN 2


RCSwitch mySwitch;
SerialReader<200> serialReader;

void setup() {
	digitalWrite(RESET_PIN, HIGH);
	pinMode(LED_BUILTIN, OUTPUT);
	pinMode(RESET_PIN, OUTPUT);

	RC::setup();
	Dht::setup();

	Serial.begin(9600);

	delay(1000);
}

void blink() {
	digitalWrite(LED_BUILTIN, HIGH);
	delay(200);
	digitalWrite(LED_BUILTIN, LOW);
}

Protocol* findProtocol(unsigned int protocol) {
	switch (protocol) {
	case 1:
		return new Protocol_1();
	case 2:
		return new Protocol_2();
	default:
		return new Protocol(protocol);
	}
}

void readRcSwitch() {
	if (mySwitch.available()) {
#if DEBUG_RAW
  if (mySwitch.available()) {
    output(mySwitch.getReceivedValue(), mySwitch.getReceivedBitlength(), mySwitch.getReceivedDelay(), mySwitch.getReceivedRawdata(),mySwitch.getReceivedProtocol());
    mySwitch.resetAvailable();
  }
#else
		unsigned long value = mySwitch.getReceivedValue();
		mySwitch.resetAvailable();

		StaticJsonDocument<128> jsonDoc;
		Protocol* p = findProtocol(mySwitch.getReceivedProtocol());
		p->toJson(value, jsonDoc);
		delete p;
		if (!jsonDoc.isNull()) {
			serializeJson(jsonDoc, Serial);
			Serial.println();
		}
#endif
	}
}

void handleJsonError(DeserializationError err, const char* cmd) {
	StaticJsonDocument<50> jsonError;
	JsonObject error = jsonError.createNestedObject("error");
	error["msg"] = err.c_str();
	error["orig_cmd"] = cmd;
	serializeJson(jsonError, Serial);
	Serial.println();
}

void runJsonCommand(char* cmd) {
	StaticJsonDocument<50> jsonDoc;
	DeserializationError err = deserializeJson(jsonDoc, cmd);
	if (err == DeserializationError::Ok) {
		if (jsonDoc.containsKey("rcSwitch")) {
			JsonObjectConst rcSwitch = jsonDoc["rcSwitch"];
			Protocol* p = findProtocol(rcSwitch["protocol"]);
			p->fromJson(rcSwitch, mySwitch);
			delete p;
			serializeJson(jsonDoc, Serial);
			Serial.println();
		}
	} else {
		handleJsonError(err, cmd);
	}
}

void readCommand() {
	if (serialReader.readLine(Serial) > 0) {
		char* cmd = serialReader.getBuffer();
		if (strcmp("reset", cmd) == 0) {
			Serial.println("resetting...");
			delay(1200);
			digitalWrite(RESET_PIN, LOW);
			Serial.println("resetting failed");
		}
		runJsonCommand(cmd);
	}
}

void loop() {
	readCommand();
	readRcSwitch();
	Dht::read();
}
