#include "FreeRTOS.h"
#include "board.h"
#include "clock_config.h"
#include "ff.h"
#include "diskio.h"
#include "fsl_debug_console.h"
#include "fsl_sd.h"
#include "fsl_sd_disk.h"
#include "pin_mux.h"
#include "sdmmc_config.h"
#include "semphr.h"
#include "task.h"
#include <stdio.h>
#include <string.h>

#include "fsl_common.h"

static volatile bool s_cardInserted = false;
static volatile bool s_cardInsertStatus = false;

static SemaphoreHandle_t s_fileAccessSemaphore = NULL;
static SemaphoreHandle_t s_CardDetectSemaphore = NULL;

static FATFS g_fileSystem;

static void SDCARD_DetectCallBack(bool isInserted, void *userData) {
    s_cardInsertStatus = isInserted;
    xSemaphoreGiveFromISR(s_CardDetectSemaphore, NULL);
}

static status_t DEMO_MakeFileSystem(void) {
    FRESULT error;
    const TCHAR driverNumberBuffer[4U] = {'S', 'D', ':', '/'};

    if(f_mount(&g_fileSystem, driverNumberBuffer, 0U)) {
        PRINTF("Mount volume failed.\r\n");
        return kStatus_Fail;
    }

#if(FF_FS_RPATH >= 2U)
    error = f_chdrive((char const *)&driverNumberBuffer[0U]);
    if(error) {
        PRINTF("Change drive failed.\r\n");
        return kStatus_Fail;
    }
#endif

    PRINTF("\r\nCreate directory......\r\n");
    error = f_mkdir(_T("/images"));
    if(error) {
        if(error == FR_EXIST) {
            PRINTF("Directory exists.\r\n");
        } else {
            PRINTF("Make directory failed.\r\n");
            return kStatus_Fail;
        }
    }
    return kStatus_Success;
}

void CardDetectTask(void *pvParameters) {
    s_fileAccessSemaphore = xSemaphoreCreateBinary();
    s_CardDetectSemaphore = xSemaphoreCreateBinary();

    BOARD_SD_Config(&g_sd, SDCARD_DetectCallBack,
                    BOARD_SDMMC_SD_HOST_IRQ_PRIORITY, NULL);

    /* SD host init function */
    if(SD_HostInit(&g_sd) == kStatus_Success) {
        while(true) {
            /* take card detect semaphore */
            if(xSemaphoreTake(s_CardDetectSemaphore, portMAX_DELAY) == pdTRUE) {
                if(s_cardInserted != s_cardInsertStatus) {
                    s_cardInserted = s_cardInsertStatus;

                    if(s_cardInserted) {
                        PRINTF("\r\nCard inserted.\r\n");
                        /* power off card */
                        SD_SetCardPower(&g_sd, false);
                        /* power on the card */
                        SD_SetCardPower(&g_sd, true);
                        if(DEMO_MakeFileSystem() != kStatus_Success) {
                            continue;
                        }

                        xSemaphoreGive(s_fileAccessSemaphore);
                    }
                }

                if(!s_cardInserted) {
                    PRINTF("\r\nPlease insert a card into board.\r\n");
                }
            }
        }
    } else {
        PRINTF("\r\nSD host init fail\r\n");
    }

    vTaskSuspend(NULL);
}
