#ifndef SOLDERDOODLE_VOLTAGE_TEST_H
#define SOLDERDOODLE_VOLTAGE_TEST_H

#include <stdbool.h>
#include <stdint.h>
#include "const.h"

#define POWER_SUPPLY         (8.4f)
#define VCC                  (5.0f)
#define VOLTAGE_DIVIDER      (0.5f)

#define LOW_BATTERY_WARNING  (6.3f)
#define NOT_ENOUGH_POWER     (6.2f)

// Different between open and closed circuits is ~1.25f,
// plus a fudge factor to help reduce analog read noise.
#if (DEV_ARDUINO)
#define OPEN_CIRCUIT_DIFF  (0.2f)
#else
#define OPEN_CIRCUIT_DIFF  (1.25f + 0.1f)
#endif

#define CHARGE_ABOVE_LOW_BATTERY   (LOW_BATTERY_WARNING + OPEN_CIRCUIT_DIFF)
#define CHARGE_ABOVE_NO_POWER   (NOT_ENOUGH_POWER + OPEN_CIRCUIT_DIFF)

#define VOLTAGE_TO_ANALOGREAD_RESULT(v)    (int16_t)((((v) * VOLTAGE_DIVIDER) / VCC) * 1024.0f)

// Closed-circuit voltage readings (Heat is switched on)
const int16_t LOW_BATTERY_RESULT = VOLTAGE_TO_ANALOGREAD_RESULT(LOW_BATTERY_WARNING);

const int16_t NOT_ENOUGH_POWER_RESULT = VOLTAGE_TO_ANALOGREAD_RESULT(NOT_ENOUGH_POWER);

// Open-circuit voltage readings (Heat is off)
const int16_t ABOVE_LOW_BATTERY_RESULT = VOLTAGE_TO_ANALOGREAD_RESULT(CHARGE_ABOVE_LOW_BATTERY);

const int16_t ABOVE_NO_POWER_RESULT = VOLTAGE_TO_ANALOGREAD_RESULT(CHARGE_ABOVE_NO_POWER);


typedef enum {
	k_voltage_not_checked = 0,
	k_voltage_ok = 1,
	k_voltage_battery_low = 2,
	k_voltage_battery_critical = 3
} VoltageStatus;

void voltage_test_init()
{
	pinMode(BATTERY_VOLTAGE, INPUT);
}

VoltageStatus voltage_test(bool isHeatOn)
{
	int16_t result = analogRead(BATTERY_VOLTAGE);

#	if (DEV_PRINT_VOLTAGE)
		Serial.print("V ");
		Serial.print(isHeatOn ? "heat_ON  " : "heat_OFF ");
		Serial.println(result);

		Serial.print("  testing against: ");
		Serial.print(isHeatOn ? LOW_BATTERY_RESULT : ABOVE_LOW_BATTERY_RESULT);
		Serial.print(", ");
		Serial.println(isHeatOn ? NOT_ENOUGH_POWER_RESULT : ABOVE_NO_POWER_RESULT);
#	endif

	if (isHeatOn) {
		if (result < NOT_ENOUGH_POWER_RESULT) {
			return k_voltage_battery_critical;
		} else if (result < LOW_BATTERY_RESULT) {
			return k_voltage_battery_low;
		}

	} else {
		if (result < ABOVE_NO_POWER_RESULT) {
			return k_voltage_battery_critical;
		} else if (result < ABOVE_LOW_BATTERY_RESULT) {
			return k_voltage_battery_low;
		}
	}

	return k_voltage_ok;
}

#endif
