#include "sd.h"
#include "char_lcd.h"
#include "bottom_half.h"

sdmmc_card_t *card;

static const char* mount_point = MOUNT_POINT;
static const char* TAG = "sd";

bool init_sd() {
    ESP_LOGI(TAG, "Initializing SD card");

    esp_err_t ret;

    esp_vfs_fat_sdmmc_mount_config_t mount_config = {
        .format_if_mount_failed = false,
        .max_files = 8,
        .allocation_unit_size = 16 * 1024,
        .disk_status_check_enable = true,
        .use_one_fat = false,
    };

    ESP_LOGI(TAG, "Using SDMMC peripheral");
    sdmmc_host_t host = SDMMC_HOST_DEFAULT();

    sdmmc_slot_config_t slot_config = {
        .clk = SD_PIN_CLK,
        .cmd = SD_PIN_CMD,
        .d0 = SD_PIN_D0,
        .d1 = SD_PIN_D1,
        .d2 = SD_PIN_D2,
        .d3 = SD_PIN_D3,
        .d4 = GPIO_NUM_NC,
        .d5 = GPIO_NUM_NC,
        .d6 = GPIO_NUM_NC,
        .d7 = GPIO_NUM_NC,
        .cd = GPIO_NUM_NC,
        .wp = GPIO_NUM_NC,
        .width = 4,
        .flags = 0
        // .flags = SDMMC_SLOT_FLAG_INTERNAL_PULLUP
    };
    ESP_LOGI(TAG, "Mounting filesystem");
    ret = esp_vfs_fat_sdmmc_mount(mount_point, &host, &slot_config, &mount_config, &card);

    if (ret == ESP_OK) {
        ESP_LOGI(TAG, "Filesystem mounted");
    } else {
        ESP_LOGE(TAG, "Failed to mount sd card: %s.", esp_err_to_name(ret));
        
        lcd_print(0, 0, "SD Mount Failed!");
        lcd_print(0, 1, esp_err_to_name(ret));
        lcd_print(0, 2, "Press Green to retry");
        lcd_print(0, 3, "Press Red to format");

        // TODO: impl buttons

        return false;
    }

    // Card has been initialized, print its properties
    sdmmc_card_print_info(stdout, card);

    ESP_LOGI(TAG, "SD card initialized!");
    return true;
}

void deinit_sd() {
    ESP_ERROR_CHECK_WITHOUT_ABORT(esp_vfs_fat_sdcard_unmount(mount_point, card));
    ESP_LOGI(TAG, "Card unmounted");
}
