#include <stdlib.h>
#include <stdio.h>
#include <string.h>

#include "pico/stdlib.h"
#include "pico/multicore.h"
#include "pico/bootrom.h"

#include "pio_usb.h"
#include "tusb.h"
#include "usb_descriptors.h"
#include "hyperx_elite2.h"

#include "main_host.h"

static bool enabled=false;
static uint8_t kb_addr=0;

// main process for core 1 to handle USB host events
void core1_main() {
	sleep_ms(10);

	// configure PIO USB for use as TinyUSB host
	pio_usb_configuration_t pio_cfg = PIO_USB_DEFAULT_CONFIG;
	pio_cfg.alarm_pool = (void*) alarm_pool_create(2,1);
	tuh_configure(1, TUH_CFGID_RPI_PIO_USB_CONFIGURATION, &pio_cfg);
	tuh_init(1);


	while (true) {
		if (enabled) {
			// keyboard is plugged in, so send RGB states on regular intervals
			rgb_task(kb_addr, HYPERX_ITF_KEYBOARD, REPORT_ID_KEYBOARD);
		}
		tuh_task(); // tinyusb host task
	}
}

// Invoked when device with hid interface is mounted
void tuh_hid_mount_cb(uint8_t dev_addr, uint8_t instance, uint8_t const* desc_report, uint16_t desc_len)
{
	(void)desc_report;
	(void)desc_len;

	uint16_t vid, pid;
	tuh_vid_pid_get(dev_addr, &vid, &pid);
	const char* protocol_str[] = { "None", "Keyboard", "Mouse" };
	uint8_t const itf_protocol = tuh_hid_interface_protocol(dev_addr, instance);

	// send device vid:pid information to CDC for debugging
	char tempbuf[128];
	size_t count = sprintf(tempbuf, "[%04x:%04x][%u] HID Interface %u, Protocol = %s \n", vid, pid, dev_addr, instance, protocol_str[itf_protocol]);
	tud_cdc_write(tempbuf, count);
	tud_cdc_write_flush();

	// request to receive report if mounted device matches HyperX Alloy Elite 2
	if (vid==HYPERX_KEYBOARD_VID && pid==HYPERX_ELITE2_PID)
	{
		enabled = true;
		kb_addr = dev_addr;
		reset_keyboard();
		if ( !tuh_hid_receive_report(dev_addr, instance) )
		{
			//tud_cdc_write_str("Error: cannot request report\r\n");
		}
	}

}

// Invoked when device with hid interface is un-mounted
void tuh_hid_umount_cb(uint8_t dev_addr, uint8_t instance)
{
	(void) instance;

	if(dev_addr==kb_addr){
		kb_addr=0;
		enabled=false;
	}
}

// Invoked when received report from device via interrupt endpoint
void tuh_hid_report_received_cb(uint8_t dev_addr, uint8_t instance, uint8_t const* report, uint16_t len)
{
	char tempbuf[64];
	size_t count;
	if(len>0) {
		// echo HID report to CDC for debugging
		count = sprintf(tempbuf, "\n[%u] Received message on interface %u (%u)\n", dev_addr, instance, len);
		tud_cdc_write(tempbuf, count);
		for(int i=0;i<len;i++){
			count=sprintf(tempbuf,"%02X ",report[i]);
			tud_cdc_write(tempbuf,count);
		}
		count = sprintf(tempbuf, "\n");
		tud_cdc_write(tempbuf,count);
		tud_cdc_write_flush();


		// send report for processing to send to host
		if (enabled && kb_addr == dev_addr) {
			process_report(instance, report, len);
		}
	}

	// continue to request to receive report
	if ( !tuh_hid_receive_report(dev_addr, instance) )
	{
		//tud_cdc_write_str("Error: cannot request report\r\n");
	}
}

void set_indicator(uint8_t const* buffer, uint16_t len) {
	// received new keyboard indicator LED status from host - pass to 
	// keyboard device so indicators can be updated
	tuh_hid_set_report(kb_addr, HYPERX_ITF_KEYBOARD, REPORT_ID_KEYBOARD, HID_REPORT_TYPE_OUTPUT, buffer, len);
}
