#include <cstdio>
#include <cstdint>

#include "FreeRTOS.h"
#include "task.h"

#include "ff.h"
#include "fatfs.h"
#include "main_task.h"
#include "utils.h"

#include "dhcp.h"


static const char* const TAG = "MAIN";

static constexpr uint16_t delay_ms = 5000;
static constexpr unsigned MAX_CHARS_IN_VOLUME_NAME = 12U;
static uint8_t volumeName[MAX_CHARS_IN_VOLUME_NAME];

//UINT ret;

static FATFS fs;// __attribute__((section(".DTCM_RAM")));     // Filesystem object
static uint8_t dhcp_buffer[256];

FRESULT scan_files (TCHAR* path);
FRESULT list_dir (const char* path);

//------------------------------------------------------------------------------

[[noreturn]] void mainTaskStart(void *argument)
{
	(void)argument;

	HAL_GPIO_WritePin(ETH_SPI_PWR_GPIO_Port, ETH_SPI_PWR_Pin, GPIO_PIN_RESET);
	vTaskDelay(pdMS_TO_TICKS(100U));
	HAL_GPIO_WritePin(ETH_SPI_RST_GPIO_Port, ETH_SPI_RST_Pin, GPIO_PIN_SET);
	vTaskDelay(pdMS_TO_TICKS(65U));	  // Min 60.3ms

	DHCP_init(0, dhcp_buffer);

	//MX_LWIP_Init();

    FRESULT  r = f_mount(&fs, (const TCHAR*)"", 1);            // Mount the default drive
	if (r != FR_OK) printf("Cannot mount SD-card!\n");
	else
	{
		printf("SD-card was mounted.\n");

		static TCHAR buff[256];
		strcpy (buff, "/");
		list_dir(buff);
	}

	while(1)
	{
		vTaskDelay(pdMS_TO_TICKS(delay_ms));

		//printThreadStackInfo(TAG);
	}
}

//------------------------------------------------------------------------------

/* List contents of a directory */

FRESULT list_dir (const TCHAR *path)
{
    FRESULT res;
    DIR dir;
    FILINFO fno;
    int nfile, ndir;


    res = f_opendir(&dir, path);                       /* Open the directory */
    if (res == FR_OK) {
        nfile = ndir = 0;
        for (;;) {
            res = f_readdir(&dir, &fno);                   /* Read a directory item */
            if (res != FR_OK || fno.fname[0] == 0) break;  /* Error or end of dir */
            if (fno.fattrib & AM_DIR) {            /* Directory */
                printf("   <DIR>   %s\n", fno.fname);
                ndir++;
            } else {                               /* File */
                printf("%10u %s\n", fno.fsize, fno.fname);
                nfile++;
            }
        }
        f_closedir(&dir);
        printf("%d dirs, %d files.\n", ndir, nfile);
    } else {
        printf("Failed to open \"%s\". (%u)\n", path, res);
    }
    return res;
}

//------------------------------------------------------------------------------

/* Recursive scan of all items in the directory */

FRESULT scan_files (
    TCHAR* path        /* Start node to be scanned (***also used as work area***) */
)
{
    FRESULT res;
    DIR dir;
    UINT i;
    static FILINFO fno;


    res = f_opendir(&dir, path);                       /* Open the directory */
    if (res == FR_OK) {
        for (;;) {
            res = f_readdir(&dir, &fno);                   /* Read a directory item */
            if (res != FR_OK || fno.fname[0] == 0) break;  /* Break on error or end of dir */
            if (fno.fattrib & AM_DIR) {                    /* It is a directory */
                i = strlen(path);
                sprintf(&path[i], "/%s", fno.fname);
                res = scan_files(path);                    /* Enter the directory */
                if (res != FR_OK) break;
                path[i] = 0;
            } else {                                       /* It is a file. */
                printf("%s/%s\n", path, fno.fname);
            }
        }
        f_closedir(&dir);
    }

    return res;
}