/*
 * Copyright (c) 2018 Nordic Semiconductor ASA
 *
 * SPDX-License-Identifier: LicenseRef-Nordic-5-Clause
 * Modded for Mutech KT01 RJW
 */

/** @file
 *  @brief Nordic UART Service Client sample
 */

#include "main.h"
#include <errno.h>
#include <zephyr/kernel.h>
#include <zephyr/device.h>
#include <zephyr/devicetree.h>
#include <zephyr/sys/byteorder.h>
#include <zephyr/sys/printk.h>
#include <zephyr/drivers/gpio.h>

#include "ble.h"
#include "custom_client.h"
#include <bluetooth/gatt_dm.h>
#include <zephyr/settings/settings.h>
#include <zephyr/logging/log.h>
#include "serial.h"
#include "user_flash.h"
#include "system.h"

#define LOG_MODULE_NAME central_uart
LOG_MODULE_REGISTER(LOG_MODULE_NAME);

#define KEY_PASSKEY_ACCEPT DK_BTN1_MSK
#define KEY_PASSKEY_REJECT DK_BTN2_MSK

#define CUSTOM_WRITE_TIMEOUT K_MSEC(150)
#define UART_WAIT_FOR_BUF_DELAY K_MSEC(50)

#define UART_OUT_STACKSIZE 1024
#define LED_STACKSIZE 1024
/* scheduling priority used by each thread */
#define UART_OUT_PRIORITY 7
#define LED_THREAD_PRIORITY 7

#define RUN_STATUS_LED DK_LED1
#define RUN_LED_BLINK_INTERVAL 50 //1000

static void control_led_toggle(enum led_states new_state, enum led_colours led_colour);

/* The devicetree node identifier for the "led0" alias. */
#define LED0_NODE DT_ALIAS(led2)
static const struct gpio_dt_spec red_led = GPIO_DT_SPEC_GET(LED0_NODE, gpios);

//const struct device *green_led_pin;

//#define LED_GREEN_NODE DT_ALIAS(green_led_pin)
//static const struct gpio_dt_spec green_led = GPIO_DT_SPEC_GET(LED_GREEN_NODE, gpios);

#define LED_GREEN_NODE DT_ALIAS(grn_led_pin)
static const struct gpio_dt_spec green_led = GPIO_DT_SPEC_GET(LED_GREEN_NODE, gpios);


#define LED_BLUE_NODE DT_ALIAS(led1)
static const struct gpio_dt_spec blue_led = GPIO_DT_SPEC_GET(LED_BLUE_NODE, gpios);


#define SWITCH_NODE DT_ALIAS(sw0)
static const struct gpio_dt_spec user_switch = GPIO_DT_SPEC_GET(SWITCH_NODE, gpios);

static K_FIFO_DEFINE(fifo_uart_tx_data);
static K_FIFO_DEFINE(fifo_uart_rx_data);

volatile static uint32_t led_flash_count;
volatile static uint32_t current_count;
volatile static bool led_toggle;
volatile static enum led_states led_state;


struct led_ctrl_struct
{
	uint8_t leds_on_ctl;
	uint8_t leds_flash_ctl;
};



volatile static struct led_ctrl_struct led_ctl;


int main(void)
{
	int err;
	int pin_value;
	enum ble_scan_types scan_type;

	led_ctl.leds_flash_ctl = 0;
	led_ctl.leds_on_ctl = 0;



	gpio_pin_configure_dt(&user_switch, GPIO_INPUT);

	pin_value = gpio_pin_get_dt(&user_switch);
	if (1 == pin_value)
	{
		set_flash_length(1000);
		scan_type = SCAN_FOR_NAME;
	}
	else
	{
		set_flash_length(50);
		scan_type = SCAN_FOR_ADDR;
	}

	control_led_toggle(LED_FLASH, GREEN_LED);
	
	initiliase_ble();

	// Absoletely no idea what this is all about
	if (IS_ENABLED(CONFIG_SETTINGS)) 
	{
		settings_load();
	}

	uart_init();


	uint8_t test_write[6] = {0x11, 0x22, 0x33, 0x44, 0x55, 0x66};
	uint8_t test_read[6];
	store_mac_addr(test_write);
	get_mac_addr(test_read);
	erase_mac_page();
	get_mac_addr(test_read);


	err = scan_init(scan_type);
#ifdef LOGGING	
	if (err != 0) 
	{
		LOG_ERR("scan_init failed (err %d)", err);
		return 0;
	}
#endif

	err = bt_scan_start(BT_SCAN_TYPE_SCAN_ACTIVE);
#ifdef LOGGING		
	if (err) 
	{
		LOG_ERR("Scanning failed to start (err %d)", err);
		return 0;
	}
	LOG_INF("Scanning successfully started");
#endif

	for (;;) 
	{		
		serial_thread();
	}
}


// This is a UART *thread*
void uart_out_thread_accessor(void)
{

	uart_out_thread();

}


void set_flash_length(uint32_t timeout)
{

	led_flash_count = (timeout/RUN_LED_BLINK_INTERVAL);
	current_count = 0;
}

static void control_led_toggle(enum led_states new_state, enum led_colours led_colour)
{

	uint8_t led_map;

	led_map = (1 << led_colour);

	if (LED_OFF ==new_state)	
		led_ctl.leds_on_ctl &= ~led_map;
	else if (LED_ON == new_state)
		led_ctl.leds_on_ctl |= led_map;
	else if (LED_FLASH == new_state)
		led_ctl.leds_flash_ctl |= led_map;
	else if (LED_FLASH_OFF == new_state)
		led_ctl.leds_flash_ctl &= ~led_map;

}


void led_thread(void)
{
	
	uint8_t led_number;
	uint8_t toggle_val;
	int led_value;
	gpio_pin_configure_dt(&red_led, GPIO_OUTPUT_ACTIVE);
	gpio_pin_configure_dt(&green_led, GPIO_OUTPUT_ACTIVE);
	gpio_pin_configure_dt(&blue_led, GPIO_OUTPUT_ACTIVE);
	
	led_number = 0;
	toggle_val = 0;
	while (1)
	{
		k_sleep(K_MSEC(RUN_LED_BLINK_INTERVAL));
		if (0 != (led_ctl.leds_flash_ctl & (1 << RED_LED)))
			gpio_pin_toggle_dt(&red_led);
		else 
		{
			led_value = (led_ctl.leds_on_ctl & (1 << RED_LED));
			gpio_pin_set_dt(&red_led, led_value);
		}
		if (0 != (led_ctl.leds_flash_ctl & (1 << GREEN_LED)))
			gpio_pin_toggle_dt(&green_led);
		else 
		{
			led_value = (led_ctl.leds_on_ctl & (1 << GREEN_LED));
			gpio_pin_set_dt(&green_led, led_value);
		}
		if (0 != (led_ctl.leds_flash_ctl & (1 << BLUE_LED)))
			gpio_pin_toggle_dt(&blue_led);
		else 
		{
			led_value = (led_ctl.leds_on_ctl & (1 << BLUE_LED));
			gpio_pin_set_dt(&blue_led, led_value);
		}										
	}

}

K_THREAD_DEFINE(led_thread_id, LED_STACKSIZE, led_thread, NULL, NULL, NULL, LED_THREAD_PRIORITY, 0, 0);
K_THREAD_DEFINE(uart_out_id, UART_OUT_STACKSIZE, uart_out_thread_accessor, NULL, NULL, NULL, UART_OUT_PRIORITY, 0, 0);