#include <Arduino.h>
#include "utils.h"
#include "readers.h"
#include "vars.h"

volatile int PN532Reader::irq = 0;
volatile bool PN532Reader::toggleMode = false;
uint8_t PN532Reader::mode = 0;


PN532Reader::PN532Reader(uint8_t ss) {
	pn532 = new Adafruit_PN532(ss, new SPIClass(HSPI));
}

void PN532Reader::begin() {
	timer = millis();
	pn532->begin();
	irq = 0;
	mode = PN532_MIFARE_ISO14443A;
	pn532->startPassiveTargetIDDetection(mode);
}

void PN532Reader::beginKeepMode() {
	pn532->begin();
	irq = 0;
	pn532->startPassiveTargetIDDetection(mode);
}

void PN532Reader::cycleMode() {
	this->end();
	pn532->begin();
	irq = 0;

	if (mode == PN532_MIFARE_ISO14443A) {
		mode = PN532_FELICA_424;
		Serial.println("Mode is now FELICA");
	}
	else {
		mode = PN532_MIFARE_ISO14443A;
		Serial.println("Mode is now NFC-A");
	}

	pn532->startPassiveTargetIDDetection(mode);
}

void PN532Reader::end() {
	pn532->sendCommandCheckAck(new byte[1]{PN532_COMMAND_POWERDOWN}, 1, 1);
}

bool PN532Reader::isNewCardPresent() {
	if (irq > 1)
		return true;

	if (toggleMode) {
		if (millis() - timer > 250) {
			cycleMode();
			timer = millis();
		}

		toggleMode = false;
	}
	return false;
}

String PN532Reader::getCardUid() {
	if (mode == PN532_MIFARE_ISO14443A) {
		Serial.println("Reading NFC-A UID");

		uint16_t atqa;
		uint8_t sak;

		pn532->readDetectedPassiveTargetID(uid, &uidLength, &atqa, &sak);
		/*if (uidLength == 4) {
		    if (atqa == 0x2 && sak == 0x18) {
		        Serial.println("4 byte uid with ATQA 0x2 and SAK 0x18, assuming ov-chipkaart");
		        uidLength = 6;
		        uid[4] = 0x02;
		        uid[5] = 0x18;
		    }
		   }*/
	}
	else {
		Serial.println("Reading FeliCa IDm");
		pn532->readDetectedPassiveTargetIDFeliCa(uid, &uidLength);
	}

	Serial.println(uidLength);
	Serial.println(byteArrayAsHexString(uid, uidLength));
	return byteArrayAsHexString(uid, uidLength);
}

void PN532Reader::reset() {
	this->end();
	this->beginKeepMode();
}

inline bool PN532Reader::canHaveUnstableIdentifier() {
	return true;
}

void PN532Reader::init() {
	pn532->begin();
	uint32_t version = pn532->getFirmwareVersion();
	if (!version) {
		Serial.print("Couldn't find PN53x board");
		while(true);
	}

	Serial.print("Found chip PN5"); Serial.println((version>>24) & 0xFF, HEX);
	Serial.print("Firmware ver. "); Serial.print((version>>16) & 0xFF, DEC);
	Serial.print('.'); Serial.println((version>>8) & 0xFF, DEC);
}

String PN532Reader::getReaderName() {
	return mode == PN532_MIFARE_ISO14443A ? "pn532-iso14443a" : "pn532-felica";
}
