#include <cstdio>
#include <cstdint>

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

#include "ff.h"
#include "fatfs.h"
#include "main_task.h"
#include "utils.h"
#include "rtc.h"
#include "adc.h"
#include "dts.h"

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

static const char* const TAG = "MAIN";

static constexpr uint16_t delay_ms = 5000U;

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

//UINT ret;

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

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

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

	//DHCP_init(0, dhcp_buffer);
	//reg_dhcp_cbfunc(ip_assigned, ip_updated, ip_conflict);

	//MX_LWIP_Init();

    FRESULT  r = f_mount(&SDFatFS, SDPath, 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);
	}

	r = f_mount(&EEPROMFatFS, EEPROMPath, 1);            // Mount the default drive
	if (r != FR_OK) printf("Cannot mount EEPROM FS!\n");
	else
	{
		printf("EEPROM FS was mounted.\n");

	}

	while(1)
	{
		//DHCP_run();
		//printThreadStackInfo(TAG);
		RTC_TimeTypeDef sTime;
		RTC_DateTypeDef sDate;
		for (auto i = 0U; i < 2; i++)
		{
			HAL_RTC_GetTime(&hrtc, &sTime, RTC_FORMAT_BIN);
			HAL_RTC_GetDate(&hrtc, &sDate, RTC_FORMAT_BIN);
		}
		//printf("%02u:%02u:%02u %02u-%02u-%u\n", sTime.Hours, sTime.Minutes, sTime.Seconds, sDate.Date, sDate.Month, (unsigned)sDate.Year + 2000U);
		int32_t Temp;
		HAL_StatusTypeDef res = HAL_DTS_GetTemperature(&hdts, &Temp);
		if (res != HAL_OK) Temp = -274;
		//printf("Ta = %ld, Td = %d\n", __HAL_ADC_CALC_TEMPERATURE(3000U, ADC3Data.Name.Temp, ADC_RESOLUTION_16B), Temp);

		vTaskDelay(pdMS_TO_TICKS(delay_ms));
	}
}


/* 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;
}