#include <avr/io.h>
#include <avr/interrupt.h>
#include <avr/sleep.h>
#include <util/delay.h>
#include <stdlib.h> // for NULL

#include "lights.h"

#define WAKEUP_LIMIT	5	// times 100 ms
#define SHORT_PRESS_MIN	10	// in jiffies (100 Hz ticks)
#define SHORT_PRESS_MAX 50
#define LONG_PRESS_MIN	100
static uint16_t button_start;
static unsigned char prev_state;

void status_led_on_off(unsigned char mode)
{
	if (mode)
		PORTB |= _BV(PORTB0);
	else
		PORTB &= ~_BV(PORTB0);
}

void init_buttons()
{
	DDRB &= ~_BV(DDB1);
	DDRB |= _BV(DDB0);
	PORTB |= _BV(PORTB1); // enable internal pull-up
	PORTB &= ~_BV(PORTB0); // status led off
	GIMSK &= ~_BV(PCIE); // disable pin-change IRQs
	PCMSK = 0; // disable pin-change IRQs on all pins of port B

	button_start = 0;
	prev_state   = 0;
}

void susp_buttons()
{
	DDRB &= ~(_BV(DDB1)); // set as input
	PORTB |= _BV(PORTB1);  // enable internal pull-up
	PORTB &= ~_BV(PORTB0); // set to zero

	GIMSK |= _BV(PCIE);

	PCMSK = _BV(PCINT1);
		// disable pin-change IRQs on all pins except PB1
}

void timer_check_buttons()
{
	unsigned char cur = !(PINB & _BV(PINB1));
	unsigned char prev = prev_state;

	prev_state = cur;

	if (cur && !prev) {                   // --- just pressed ---
		button_start = jiffies;
		// set_status_led(button, NULL);

	} else if (cur && prev) {           // --- is still pressed ---
		uint16_t duration = jiffies - button_start;

		if (duration > LONG_PRESS_MIN) {
			long_press_start();
				// acknowledge long press
		}
	} else if (!cur && prev) {            // --- just released ---
		uint16_t duration = jiffies - button_start;

		if (duration > SHORT_PRESS_MIN && duration < SHORT_PRESS_MAX) {
			short_press();
		} else if (duration > LONG_PRESS_MIN) {
			// set_status_led(button, NULL);
			long_press();
		}
		// ignore other button-press durations
	}
}

#if 0
static void handle_brake(unsigned char cur, unsigned char prev)
{
	if (cur && !prev) {                   // --- just pressed ---
		button_start[2] = jiffies;
	} else if (!cur && prev) {            // --- just released ---
		button_start[2] = jiffies;
	} else {                              // --- no change ---
		uint16_t duration = jiffies - button_start[2];

		if (duration > 6) {
			if (cur) {
				if (button_state.brake_working
					&& !button_state.brake_reported) {
					button_state.brake_reported = 1;
					brake_on();
				}
			} else {
				button_state.brake_working = 1;
				if (button_state.brake_reported) {
					button_state.brake_reported = 0;
					brake_off();
				}
			}
			button_start[2] = jiffies - 7; // avoid overflow
		}
	}
}
#endif

unsigned char buttons_wait_for_release()
{
	uint16_t wake_count = 0;
	unsigned char pin;

	do {
		if (wake_count++ > WAKEUP_LIMIT)
			status_led_on_off(1); // inform the user

		_delay_ms(100);

		pin = PINB & _BV(PINB1);
	} while (!(pin & _BV(PINB1)));

	status_led_on_off(0);

	return wake_count > WAKEUP_LIMIT;
}

ISR(PCINT0_vect)
{
	// empty - let it wake us from sleep, but do nothing else
}

