#include "buttons.h"
#include "settings_api.h"
#include "common_config.h"
#include "FreeRTOS.h"
#include "task.h"
#include <string.h>
#include <stdio.h>


BUTTON_NO_FIX_t reset_but;
BUTTON_NO_FIX_t set_but;


//  
void button_init(void) 
{
    gpio_init_type gpio_initstructure;
    
    // key reset
    gpio_initstructure.gpio_pull           = GPIO_PULL_NONE;  
    gpio_initstructure.gpio_mode           = GPIO_MODE_INPUT;  
    gpio_initstructure.gpio_drive_strength = GPIO_DRIVE_STRENGTH_STRONGER;
    gpio_initstructure.gpio_pins           = GPIO_PINS_8;
    gpio_init(GPIOB, &gpio_initstructure);
    
    // key set
    gpio_initstructure.gpio_pins           = GPIO_PINS_5;
    gpio_init(GPIOD, &gpio_initstructure);
  
    reset_but.port              = GPIOB;
    reset_but.pin			    = GPIO_PINS_8;
    reset_but.timeDelay         = 1;
    reset_but.pressHandler      = reset_handler;
    reset_but.unpressHandler    = void_handler_btn;
    reset_but.counterActivation = 0;
    reset_but.timeActivation_1  = 300; // 30 секунд
    reset_but.timeActivation_2  = 600; 
    reset_but.fActivation       = false;
    
    set_but.port                = GPIOD;
    set_but.pin			        = GPIO_PINS_5;
    set_but.timeDelay           = 1;
    set_but.pressHandler        = void_handler;
    set_but.unpressHandler      = set_handler;
    set_but.counterActivation   = 0;
    set_but.timeActivation_1    = 300;   // обычное нажатие
    set_but.timeActivation_2    = 600; // 15 секунд
    set_but.fActivation         = false;
    
    reset_but.stateOld = BUTTON_GetState(&reset_but);
    set_but.stateOld  = BUTTON_GetState(&set_but);
}

// Возвращает сотояние ключа
BUTTON_STATE_t BUTTON_GetState(BUTTON_NO_FIX_t *button)
{
    return (BUTTON_STATE_t)gpio_input_data_bit_read(button->port, button->pin);
}

//
bool button_get_state_int(BUTTON_t button)
{
    switch (button)
    {
        case BUT_RESET :
            return !(bool)gpio_input_data_bit_read(reset_but.port, reset_but.pin);
        break;
    
        case BUT_SET :
            return !(bool)gpio_input_data_bit_read(set_but.port, set_but.pin);
        break;
    
        default : break;
    }
    return false;
}

/**
  * @brief  Обработчик кнопки без фиксации. В обработчике реализована защита
  *         от дребезга с помощью задержки. Защита срабатывает при нажатии 
  *         и при отпускании.
  * @param *button: указатель на структуру типа BUTTON_NO_FIX
  * @retval нет
  */
void BUTTON_NoFixHandler(BUTTON_NO_FIX_t *button)
{
    if (button->stateNew != BUT_NO_DEFINE)
    {  
        // определяем текущее (новое) состояние кнопки        
        button->stateNew = (BUTTON_STATE_t)gpio_input_data_bit_read(button->port, button->pin);
  
        if (button->stateNew != button->stateOld)  // зафиксирован факт нажатия/отжатия
            button->stateNew = BUT_NO_DEFINE;  // переводим кнопку в неопределенное состояние
    }
    else
    {
        button->counterDelay++;             // запускаем счетчик на задержку
    
        if (button->counterDelay > button->timeDelay)  // задержка закончилась
        {
            button->counterDelay = 0;
            button->counterActivation = 0;
            button->stateNew = (BUTTON_STATE_t)gpio_input_data_bit_read(button->port, button->pin);
                
            // определяем текущее (новое) состояние кнопки        
            if (button->stateNew == BUT_ON) {  
                button->unpressHandler(1);
            }  
            else {  
                button->pressHandler();
            }
        }
    }
  
    button->stateOld = button->stateNew;
}


/**
  * @brief  Обработчик кнопки без фиксации. Кнопка срабатывает через определеное
            время нажатия.
  * @param *button: указатель на структуру типа BUTTON_NO_FIX
  * @retval нет
  */
void BUTTON_DellayHandler(BUTTON_NO_FIX_t *button)
{
    /* Кнопка нажата. Ведем отсчет времени удержания */
    //if ((uint8_t)gpio_input_data_bit_read(button->port, button->pin) == 1)  // определяем текущее (новое) состояние кнопки
    if ((uint8_t)gpio_input_data_bit_read(button->port, button->pin) == 0)  // определяем текущее (новое) состояние кнопки
    {  
        button->counterActivation++;
        button->fActivation = false;
	
        /* Кнопка нажата более необходимого времени - начинаем чаще мигать диодом */
        //if (button->counterActivation > button->timeActivation)
        //  LED_SetStatusLedFreq(100);
    }
    /* Кнопку отжата. Если до этого она была нажата нужное время - вызываем хендлер */
    else
    {
        if ((button->counterActivation > button->timeActivation_2) && button->fActivation == false)
        {  
            button->fActivation = true;
            button->unpressHandler(2);
        }
        else if ((button->counterActivation > button->timeActivation_1) && button->fActivation == false)
        {
            button->fActivation = true;
            button->unpressHandler(1);
        }
        else
            button->counterActivation = 0;
    }		
}

// Опрос кнопок
void button_task(void *params) 
{
    for (;;) 
    {
        BUTTON_NoFixHandler(&reset_but);
        BUTTON_NoFixHandler(&set_but);
        vTaskDelay(100);  
    }
}

// Заглушка
void void_handler(void) 
{}

// Заглушка
void void_handler_btn(uint8_t btn) 
{}

// Перезагрузка контроллера
void reset_handler(void)
{
    NVIC_SystemReset();
}

// Сброс настроек ( + запись в лог)
void set_handler(uint8_t btn)
{
    settings_save_with_log();
}


