#include <rtthread.h>
#include <rtdevice.h>
#include "board.h"
#include <wavplayer.h>
#include <multi_button.h>
#include <mfrc522.h>
#include <fingerprint.h>

#define DBG_TAG              "door"
//#define DBG_LVL              DBG_INFO
#define DBG_LVL              DBG_LOG
#include <rtdbg.h>


static struct button key1_btn;
static struct button key2_btn;
//static struct button key3_btn;

#define KEY1_BUTTON_PIN     22//"PF1"
#define KEY2_BUTTON_PIN     21//"PF0"
//#define KEY3_BUTTON_PIN     2//"PA2"

#define WAV_FP_PRESS_FILE       "/Door/fppress.wav"
#define WAV_DOOR_OPEN_FILE      "/Door/dooropen.wav"
#define WAV_FP_LEAVE_FILE       "/Door/fpleave.wav"
#define WAV_FP_ERROR_FILE       "/Door/fperror.wav"
#define WAV_FP_RECORD_FILE      "/Door/fprecord.wav"

struct rt_semaphore door_open_sem;
struct rt_semaphore add_finger_sem;

#define DORR_LDE_R      "PE.1"
#define DORR_LDE_G      "PA.1"
#define DORR_LDE_B      "PE.4"

static uint8_t key1_button_read_pin(void)
{
    return rt_pin_read(KEY1_BUTTON_PIN);
}

static void key1_button_callback(void *btn)
{
    uint32_t btn_event_val;

    btn_event_val = get_button_event((struct button *)btn);

    switch(btn_event_val)
    {
    case PRESS_DOWN:
        rt_kprintf("button press down\n");
    break;

    case PRESS_UP:
        rt_kprintf("button press up\n");
    break;

    case PRESS_REPEAT:
        rt_kprintf("button press repeat\n");
    break;

    case SINGLE_CLICK:
        rt_sem_release(&door_open_sem);
        LOG_D("key1 door open!\n");
    break;

    case DOUBLE_CLICK:
        rt_sem_release(&add_finger_sem);
        rt_kprintf("button double click\n");
    break;

    case LONG_PRESS_START:
        fp_empty();
        rt_kprintf("button long press start\n");
    break;

    case LONG_PRESS_HOLD:
        rt_kprintf("button long press hold\n");
    break;
    }
}



static uint8_t key2_button_read_pin(void)
{
    return rt_pin_read(KEY2_BUTTON_PIN);
}

static void key2_button_callback(void *btn)
{
    uint32_t btn_event_val;

    btn_event_val = get_button_event((struct button *)btn);

    switch(btn_event_val)
    {
    case PRESS_DOWN:
        rt_kprintf("button2 press down\n");
    break;

    case PRESS_UP:
        rt_kprintf("button2 press up\n");
    break;

    case PRESS_REPEAT:
        rt_kprintf("button2 press repeat\n");
    break;

    case SINGLE_CLICK:
        rt_sem_release(&door_open_sem);
        rt_kprintf("button2 single click\n");
    break;

    case DOUBLE_CLICK:
        rt_kprintf("button2 double click\n");
    break;

    case LONG_PRESS_START:
        rt_sem_release(&door_open_sem);
        rt_kprintf("button2 long press start\n");
    break;

    case LONG_PRESS_HOLD:
        rt_kprintf("button2 long press hold\n");
    break;
    }
}


static void button_thread_entry(void)
{
   /* low level drive */
   rt_pin_mode  (KEY1_BUTTON_PIN, PIN_MODE_INPUT_PULLUP);
   button_init  (&key1_btn, key1_button_read_pin, PIN_LOW);
   button_attach(&key1_btn, PRESS_DOWN,       key1_button_callback);
   button_attach(&key1_btn, PRESS_UP,         key1_button_callback);
   button_attach(&key1_btn, PRESS_REPEAT,     key1_button_callback);
   button_attach(&key1_btn, SINGLE_CLICK,     key1_button_callback);
   button_attach(&key1_btn, DOUBLE_CLICK,     key1_button_callback);
   button_attach(&key1_btn, LONG_PRESS_START, key1_button_callback);
   button_attach(&key1_btn, LONG_PRESS_HOLD,  key1_button_callback);
   button_start (&key1_btn);

   /* low level drive */
   rt_pin_mode  (KEY2_BUTTON_PIN, PIN_MODE_INPUT_PULLDOWN);
   button_init  (&key2_btn, key2_button_read_pin, PIN_HIGH);
   button_attach(&key2_btn, PRESS_DOWN,       key2_button_callback);
   button_attach(&key2_btn, PRESS_UP,         key2_button_callback);
   button_attach(&key2_btn, PRESS_REPEAT,     key2_button_callback);
   button_attach(&key2_btn, SINGLE_CLICK,     key2_button_callback);
   button_attach(&key2_btn, DOUBLE_CLICK,     key2_button_callback);
   button_attach(&key2_btn, LONG_PRESS_START, key2_button_callback);
   button_attach(&key2_btn, LONG_PRESS_HOLD,  key2_button_callback);
   button_start (&key2_btn);

    while(1)
    {
        /* 5ms */
        rt_thread_delay(RT_TICK_PER_SECOND/200);
        button_ticks();
    }
}


static void nfc_thread_entry(void)
{
    MFRC522(MFRC522_SS_PIN, MFRC522_RST_PIN);
   PCD_Init();     // Init MFRC522
   rt_thread_mdelay(4);
   PCD_DumpVersionToSerial();

   //uid = get_uid();

   while (1)
   {
     rt_thread_mdelay(250);

     if ( ! PICC_IsNewCardPresent() )
     {
         continue;
     }
     else
     {
         rt_sem_release(&door_open_sem);
         LOG_D("nfc card sucess0\r\n");
         if ( PICC_IsNewCardPresent() )
         {
             rt_sem_release(&door_open_sem);
             LOG_D("nfc card sucess1\r\n");
         }
     }

   }

   PCD_End();
}



static void fingerprint_thread_entry(void)
{
   SearchResult p;
   fp_ack_type_t code;
   int i;

   rt_sem_control(&add_finger_sem, RT_IPC_CMD_RESET, RT_NULL);

   while(1)
   {
       fp_init(FINGERPRINT_UART_NAME);
       rt_thread_mdelay(1000);
       if( ( 1 == flag_init )&&( 1 == flag_vfy ) )
       {
          LOG_D("fp_init sucess\r\n");

          while(1)
          {

              if( RT_EOK == rt_sem_take(&add_finger_sem, RT_WAITING_NO) )//add finger
              {
                  fp_add_fp();
              }
              else//verify finger
              {
                    code = fp_auto_identify(&p);

                    if( 0x05 == code )
                    {
                        rt_sem_release(&door_open_sem);
                        LOG_D("fingerprint sucess\r\n");
                        rt_thread_mdelay(500);
                        continue; //
                    }
                    else if( ( 0x01 == code )||( 0x07 == code ) )
                    {
                       continue; //
                    }
                    else if ( 0xfe == code )
                    {
                        wavplayer_stop();
                        wavplayer_play(WAV_FP_ERROR_FILE);
                        rt_thread_mdelay(500);
                        continue; //
                    }
                    //rt_kprintf("Find the fingerprint! code =%d page_id=%lx, mat_score=%lx", code, p.pageID, p.mathscore);

                   rt_thread_mdelay(200);
              }

          }

       }else {
           LOG_D("fp_init failed\r\n");
       }

       if( i > 10 )
       {
           break;
       }
   }
}

/* 开门线程 */
static void door_open_entry(void)
{

    uint8_t led_r_pin = rt_pin_get(DORR_LDE_R);
    uint8_t led_g_pin = rt_pin_get(DORR_LDE_G);
    uint8_t led_b_pin = rt_pin_get(DORR_LDE_B);

    rt_pin_mode(led_r_pin, PIN_MODE_OUTPUT);
    rt_pin_write(led_r_pin, PIN_LOW);

    rt_pin_mode(led_g_pin, PIN_MODE_OUTPUT);
    rt_pin_write(led_g_pin, PIN_HIGH);

    rt_pin_mode(led_b_pin, PIN_MODE_OUTPUT);
    rt_pin_write(led_b_pin, PIN_HIGH);

    while(1)
    {
        rt_sem_control(&door_open_sem, RT_IPC_CMD_RESET, RT_NULL);
        rt_sem_take(&door_open_sem, RT_WAITING_FOREVER);

        rt_pin_write(led_r_pin, PIN_HIGH);
        rt_pin_write(led_g_pin, PIN_LOW);
        LOG_D("door open!\n");
        wavplayer_stop();
        wavplayer_play(WAV_DOOR_OPEN_FILE);
        rt_thread_mdelay(1000);

        for(int i = 0; i < 50; i++)
        {
            rt_thread_mdelay(100);
        }

        LOG_D("door closed!\n");
        rt_pin_write(led_r_pin, PIN_LOW);
        rt_pin_write(led_g_pin, PIN_HIGH);
    }
}


/* 初始化 */
rt_err_t door_control_init(void)
{
    rt_err_t ret = RT_EOK;
    rt_thread_t thread = RT_NULL;

    /* 初始化信号量 */
    rt_sem_init(&door_open_sem, "open_sem", 0, RT_IPC_FLAG_FIFO);
    rt_sem_init(&add_finger_sem, "addfinger_sem", 0, RT_IPC_FLAG_FIFO);

     /* 创建开门线程 */
    thread = rt_thread_create("door", (void (*)(void *parameter))door_open_entry, RT_NULL, 1024, 10, 10);  //stack_size 512
    if (thread != RT_NULL)
    {
        rt_thread_startup(thread);
    }
    else
    {
        ret = RT_ERROR;
        goto _error;
    }

    /* 创建按键线程 */
    thread = rt_thread_create("btn", button_thread_entry, RT_NULL, 1024, 10, 10);
    if (thread != RT_NULL)
    {
       rt_thread_startup(thread);
    }
    else
    {
       ret = RT_ERROR;
       goto _error;
    }

    /* 创建NFC线程 */
    thread = rt_thread_create("nfc", nfc_thread_entry, RT_NULL, 1024, 10, 10);
    if (thread != RT_NULL)
    {
       rt_thread_startup(thread);
    }
    else
    {
       ret = RT_ERROR;
       goto _error;
    }

    /* 创建指纹线程 */
    thread = rt_thread_create("finger", fingerprint_thread_entry, RT_NULL, 2*1024, 20, 10);
    if (thread != RT_NULL)
    {
      rt_thread_startup(thread);
    }
    else
    {
      ret = RT_ERROR;
      goto _error;
    }

_error:
    return ret;
}

