#include <Arduino.h>
#include "abc800_usb.h"
#include "port.h"
#include "keyboardpipe.h"
#include "abc800_hidboot.h"
#include "abc800_config.h"
#include "abc800_gpio.h"
extern USBHostKeyboard port;
extern TimerHandle_t repeat_delay_timer_out;
extern TimerHandle_t repeat_timer_out;
extern KeyboardReportParser keyparse;
extern TaskHandle_t Keyboard_Task_Out;
extern TaskHandle_t Keyboard_ABC800_Task_In;
extern QueueHandle_t abc800_key_queue_out;
uint8_t old_key = 0x00;
key800queue key800queueold; 

void  onRepeatTimer_out(TimerHandle_t xTimer) {
  if (xQueueSend(abc800_key_queue_out, (void *)&key800queueold, 0) != pdTRUE) {
    ESP_LOGE(TAG,"Queue full");
  }
   xTimerStart(repeat_timer_out, portMAX_DELAY);
}
void ctrl_pipe_cb(ext_pipe_event_msg_t event, usb_irp_t *irp)
{
  ESP_LOGI(TAG,"CTRL EVENT: 0x%x\n", event);
  if (event == 0xA206)
  {
    port.getProductString();
    delay(100);
    port.getManufacturerString();
    delay(100);
    port.inpipe->inData();
    
  }
}
void onProductString(char *str)
{
  ESP_LOGI(TAG,"%s",str);
}

void onManufacturerString(char *str)
{
   ESP_LOGI(TAG,"%s",str);
}
void usbh_keyboard_device_ready()
{
  port.setIdle();
  port.getHidReportMap();
  ESP_LOGI(TAG,"Keyboard ready");

}

static void hid_dataout_cb(ext_pipe_event_msg_t event, usb_irp_t *irp)
{
      ESP_LOGI(TAG,"DATA out return");
}

static void hid_datain_cb(ext_pipe_event_msg_t event, usb_irp_t *irp)
{
    switch (event)
    {
    case HCD_PIPE_EVENT_IRP_DONE:
        ESP_LOGD(TAG, "modi: %i", (int8_t)irp->data_buffer[0]);
        ESP_LOGD(TAG, "Key1: %i", (int8_t)irp->data_buffer[2]);
        ESP_LOGD(TAG, "Key2: %i", (int8_t)irp->data_buffer[3]);
        ESP_LOGD(TAG, "Key3: %i", (int8_t)irp->data_buffer[4]);
        ESP_LOGD(TAG, "Key4: %i", (int8_t)irp->data_buffer[5]);
        ESP_LOGD(TAG, "Key5: %i", (int8_t)irp->data_buffer[6]);
        ESP_LOGD(TAG, "Key6: %i", (int8_t)irp->data_buffer[7]);
        if (!(int8_t)irp->data_buffer[2]){
          xTimerStop(repeat_delay_timer_out, portMAX_DELAY);
          xTimerStop(repeat_timer_out, portMAX_DELAY);
        }
        uint8_t key =irp->data_buffer[2];
        uint8_t mod =irp->data_buffer[0];
        keyparse.Parse(irp->num_bytes,irp->data_buffer,&port);
        if (key!=0){
          digitalWrite(2,1);
          ESP_LOGD(TAG,"Key number0x%02x\r\n",(char)irp->data_buffer[2]);
          key800queue key800queue ;
          key800queue.ascii = keyparse.OemToAscii(mod,key);
          key800queue.special = 0x00;
          key800queue.modifier = mod;
          if (key800queue.ascii== 0x00 && key!=0x00){
            key800queue.special = key;
          }
          if (key!=0x00 || key800queue.special!=0x00){
            
            if (old_key!=key)
            {
              // RESET
              if (key800queue.modifier==0x05 && key ==0x4c) 
              {
                if (!xTaskNotifyFromISR(Keyboard_ABC800_Task_In, ABC800_KEY_RESET, eSetValueWithoutOverwrite,NULL))
                {
                    ESP_LOGE(TAG,"Could not notify task");
                }
              }
              else
              {
                if (xQueueSend(abc800_key_queue_out, (void *)&key800queue, 0) != pdTRUE) {
                  ESP_LOGE(TAG,"Queue full");
                }
                key800queueold=key800queue;
                xTimerStart(repeat_delay_timer_out, portMAX_DELAY);
              }
            }
            
          }
 
        }else{
          digitalWrite(KEY800_LED,LOW);
        }
        old_key=key;

    }
}

void usb_port_cb(port_event_msg_t msg, USBHostPort *port)
{
  ESP_LOGI(TAG,"PORT EVENT: 0x%x\n", msg.port_event);
}
void abc800_port_init(){
        port.onPortEvent(usb_port_cb);
    port.onControlEvent(ctrl_pipe_cb);
    port.onDataIn(hid_datain_cb);
    port.onDataOut(hid_dataout_cb);
    repeat_timer_out = xTimerCreate(
                      "Repeat Timer",        // Name of timer
                      ABC800_KEY_REPEAT_TIME / portTICK_PERIOD_MS,  // Period of timer (in ticks)
                      pdFALSE,                     // Auto-reload
                      (void *)0,                  // Timer ID
                      onRepeatTimer_out); 
    repeat_delay_timer_out = xTimerCreate(
                      "Repeat Delay Timer",           // Name of timer
                      ABC800_KEY_REPEAT_TIME_DELAY/ portTICK_PERIOD_MS,  // Period of timer (in ticks)
                      pdFALSE,                    // Auto-reload
                      (void *)1,                  // Timer ID
                      onRepeatTimer_out); 
                      
}
