#include <zephyr.h>
#include <etn_mesh_fota_blb.h>

#define SERIAL_FLASH_START_ADDRESS      	0x00000
#define SERIAL_FLASH_END_ADDRESS	    	0x800000
#define SERIAL_MIN_ERASE_SIZE				0x1000
#define SERIAL_FLASH_COMPLETE_END_ADDRESS	0x800000

#define SERIAL_FLASH_PARTITION_SIZE			0x80000
#define SERIAL_FLASH_FILE_INFO_ADDR			0x7FC000

#define FLASH_MAX_SEND_IN_BYTES     4096

//#define BLOB_SERVER_ADDRESS  		0x0005
#define CODE_SIZE_TO_TRANSFER_IN_KB	4

#define FW_VER_MAJOR			1
#define FW_VER_MINOR			2
//#define CODE_SIZE_IN_BYTES		2688

#define RX_BUFFER_LENGTH	300
#define TX_BUFFER_LENGTH	10

#define OTA_PROCESS_NONE		0
#define OTA_PROCESS_RUNNING		1
#define OTA_PROCESS_COMPLETED	2

#define UART_READ_FILE_SIZE	1
#define UART_READ_BYTES		2
#define UART_RESET_PROCESS	3
#define UART_RUN_MODE		4

#define UART_ERR_NONE       0
#define UART_ERR_ADDR       1
#define UART_ERR_LEN        2
#define UART_ERR_FILESIZE   3
#define UART_ERR_RESPONSE	4
#define UART_ERR_WRNG_RES	5

#define FLASH_TEST_REGION_OFFSET 0x00000
#define FLASH_SECTOR_SIZE        4096

#define CLIENT_RUN_MODE_TRANSFER	0
#define CLIENT_RUN_MODE_STORAGE		1

enum client_states{
	CLIENT_STATE_NONE=0,
	CLIENT_STATE_RUN_MODE,
	CLIENT_STATE_RUN_STORAGE_START,
	CLIENT_STATE_RUN_STORAGE_READ,
	CLIENT_STATE_RUN_STORAGE_COMPLETE,
	CLIENT_STATE_RUN_TRANSFER_START,
	CLIENT_STATE_RUN_TRANSFER_PROCESS,
	CLIENT_STATE_RUN_TRANSFER_COMPLETE,
	CLIENT_STATE_IDEL
};


struct client_curr_values{
	enum client_states state;
	uint16_t server_id;
	uint16_t miss_chunk;
	uint16_t running_mode;
	uint16_t firmware_index;
	uint64_t firm_start_index;
	uint64_t file_size;
	uint8_t  led_index;
	bool     led_value;
	uint8_t  led_blink;
	uint16_t process_delay_time;
	uint16_t chunk_number;
    uint64_t flash_addr;
    uint64_t flash_length;
	uint8_t  uart_wait_cntr; 
	uint32_t start_time;	
};

struct uart_data{
	uint8_t buf[RX_BUFFER_LENGTH];
	uint8_t tx_buf[TX_BUFFER_LENGTH];
	int rx_counter;
	uint32_t addr;
	int len;
	int rx_cmd;
	int response_code;
	uint8_t tx_cmd;
	bool rx_done;
};

struct flash_file_info{
	uint8_t index;
	uint64_t start_addr;
	uint64_t length;
	uint64_t file_size;
};

void setup_m25q(void);
void clear_serial_flash_storage(uint64_t start_address, uint64_t size);
int store_to_serial_flash(uint64_t address, uint64_t length, const void * data);
void read_from_serial_flash(uint64_t address, uint64_t length, uint8_t type);
void test_serial_flash(uint64_t start_address, uint64_t size);
void setup_gpios(void);
void champ_init_hardware(void);

void setup_uart1(void);
void uart1_write_data(char array[], uint8_t len);
void uart1_cb(const struct device *dev, void *user_data);
void uart1_get_data(struct uart_data *data);
bool uart1_check_if_data_received(struct uart_data *data);

void setup_uart0(void);
void uart0_write_data(char array[], uint8_t len);
void uart0_cb(const struct device *dev, void *user_data);
void uart0_get_data(struct uart_data *data);
bool uart0_check_if_data_received(struct uart_data *data);

void client_led_button_process(void);
void client_led_set_index(uint8_t index);
void client_state_machine_run(void);
void client_state_none(void);
void client_state_run_mode(void);
void client_state_run_storage_start(void);
void client_state_run_storage_read(void);
void client_state_run_storage_completed(void);
void client_state_run_transfer_start(void);
void client_state_run_transfer_process(void);
void client_state_run_transfer_completed(void);
void client_state_idel(void);
void client_state_set(uint8_t state);

void clear_memory_partition( struct flash_file_info *info );
void store_file_info( struct flash_file_info *info );
void read_file_info(struct flash_file_info *info);
void client_store_bytes_to_flash(void);

uint16_t get_server_id(void);
uint16_t get_miss_chunks(void);
uint64_t get_firmware_size(void);
int get_firmware_data_from_external_flash( struct fota_blb_data_flash *flash_data);
