#pragma once

#include "Arduino.h"
#include <avr/sleep.h>
#include <avr/power.h>
#include <avr/wdt.h>

// Utility macros
#define adc_disable() (ADCSRA &= ~_BV(ADEN)) // disable ADC (before power-off)
#define adc_enable()  (ADCSRA |= _BV(ADEN)) // re-enable ADC
#define enable_pin_interrupts()  (GIMSK |= _BV(PCIE))  // Enable Pin Change Interrupts

class TinyPower {

public:
	static void setup() {
		set_sleep_mode(SLEEP_MODE_PWR_DOWN);
		enable_pin_interrupts();
	}

	static void sleep(byte pin = -1) {
		if (pin >= 0) PCMSK |= _BV(pin);            	     	// Use PB0 as interrupt pin
		adc_disable();

		sleep_enable();                         // Sets the Sleep Enable bit in the MCUCR Register (SE BIT)
		sleep_bod_disable();
		sei();                                  // Enable interrupts

		sleep_cpu();                            // sleep

		sleep_disable();                        // Clear SE bit
		cli();                                  // Disable interrupts
		if (pin >= 0) PCMSK &= ~_BV(pin);                     // Turn off PB0 as interrupt pin
		adc_enable();

		sei();                                  // Enable interrupts
	}

	static void enableWdt(byte time) {
		cli();
		MCUSR = 0x00;
		WDTCR |= _BV(WDCE) | _BV(WDE);
		WDTCR = _BV(WDIE) | (time & 0x08 ? _WD_PS3_MASK : 0x00) | (time & 0x07);
		sei();
	}

	static void disableWdt() {
		cli();
		MCUSR = 0x00;
		WDTCR |= _BV(WDCE) | _BV(WDE);
		WDTCR = 0x00;
		sei();
	}
};
