/*
 * Commands prepared for FAT file system on the SD card.
 */
#include <t_services.h>
#include <string.h>
#include "ff.h"
#include "diskio.h"
#include "kernel_id.h"

FATFS	F_Object;
static FILINFO finfo;

#if _USE_LFN
static char lfn[_DF1S ? (_MAX_LFN * 2 + 1):(_MAX_LFN+1)];
#endif

/*
 * Simple directory listing command. Only shows root directory.
 */
void fat_command(int argc, char **argv)
{
    FRESULT result;
    int nb;
    char *fn;
    char time_str[20];
    DIR Dir_Object;

    result = f_mount(0, &F_Object);
    if (result != FR_OK) {
        cons_printf("f_mount: %d\n", result);
        return;
    }
    result = f_opendir(&Dir_Object, "/");
    if (result != FR_OK) {
        cons_printf("f_opendir --> RESULT = %d\n", result);
        return;
    }

#if _USE_LFN
    finfo.lfname = lfn;
    finfo.lfsize = sizeof(lfn);
#endif
    cons_printf("\nshows directory list...\n");
    cons_printf("---------------------\n");
    while ((f_readdir(&Dir_Object, &finfo) == FR_OK) &&
        finfo.fname[0]) {
#if _USE_LFN
        fn = *finfo.lfname? finfo.lfname : finfo.fname;
#else
        fn = finfo.fname;
#endif
        str_printf(time_str, "%02d/%02d/%02d %02d:%02d:%02d",
            (finfo.fdate >> 9) + 1980, (finfo.fdate >> 5) & 0x0f,
            (finfo.fdate & 0x1f), (finfo.ftime >> 11) & 0x1f,
            (finfo.ftime >> 5) & 0x3f, finfo.ftime & 0x3f);
        cons_printf("%8d %s %s", finfo.fsize, time_str, fn);
        if (finfo.fattrib & AM_DIR)
            cons_printf("/");
        cons_printf("\n");
    }
    cons_printf("---------------------\n");
}

#ifdef DEBUG_COMMAND
void do_mount()
{
    FRESULT result;

    result = f_mount(0, &F_Object);
    if (result != FR_OK) {
        cons_printf("f_mount: %d\n", result);
    }
}

char *find_mp3file(char *cp)
{
    FRESULT result;
    int nb;
    char *fn;
    DIR Dir_Object;

    result = f_opendir(&Dir_Object, "/");
    if (result != FR_OK) {
        cons_printf("f_opendir --> RESULT = %d\n", result);
        return;
    }

#ifdef USE_LFN
    finfo.lfname = lfn;
    finfo.lfsize = sizeof(lfn);
#endif
    while ((f_readdir(&Dir_Object, &finfo) == FR_OK) &&
                finfo.fname[0]) {
#ifdef USE_LFN
        fn = *finfo.lfname? finfo.lfname : finfo.fname;
#else
        fn = finfo.fname;
#endif
        if (strstr(fn, ".mp3") == NULL && strstr(fn, ".MP3") == NULL)
            continue;
        if (strncmp(fn, cp, strlen(cp)) == 0)
            return fn;
    }
    return NULL;
}

char *find_aacfile(char *cp)
{
    FRESULT result;
    int nb;
    char *fn;
    DIR Dir_Object;

    result = f_opendir(&Dir_Object, "/");
    if (result != FR_OK) {
        cons_printf("f_opendir --> RESULT = %d\n", result);
        return;
    }

#ifdef USE_LFN
    finfo.lfname = lfn;
    finfo.lfsize = sizeof(lfn);
#endif
    while ((f_readdir(&Dir_Object, &finfo) == FR_OK) &&
                finfo.fname[0]) {
#ifdef USE_LFN
        fn = *finfo.lfname? finfo.lfname : finfo.fname;
#else
        fn = finfo.fname;
#endif
        if (strstr(fn, ".m4a") == NULL && strstr(fn, ".M4A") == NULL)
            continue;
        if (strncmp(fn, cp, strlen(cp)) == 0)
            return fn;
    }
    return NULL;
}
#endif

static FIL f_font;
extern UB nand_buffer[];
static UB f_buffer[512];

static void copyFont(char *fname, int pstart)
{
    FRESULT result;
    int pageno, b_read;

    result = f_mount(0, &F_Object);
    if (result != FR_OK) {
        cons_printf("f_mount: %d\n", result);
        return;
    }
    result = f_open(&f_font, fname, FA_OPEN_EXISTING|FA_READ);
    if (result != FR_OK) {
        syslog(LOG_NOTICE, "f_open --> RESULT = %d", result);
        return;
    }
    pageno = pstart;
    while (1) {
        result = f_read(&f_font, nand_buffer, 512, &b_read);
        if (result != FR_OK) {
            syslog(LOG_NOTICE, "f_read failed with %d", result);
            break;
        }
        if (b_read <= 0) {
            syslog(LOG_NOTICE, "page: %d, bread = %d", pageno, b_read);
            break;
        }
        nandProgramPage(pageno >> 5, pageno & 31, 0, nand_buffer);
        pageno++;
    }
    f_close(&f_font);
}

/*
 * Copy file onto Flash memory.
 *
 * Syntax: copy fname start_page
 *        fname: Name of source file on the SD card.
 *        start_page: Destination start page # on the flash.
 */
void copy_command(int argc, char **argv)
{
    int page = 32;
    char *fname;

    if (argc > 1) {
        fname = argv[1];
        if (argc > 2) {
            page = atoi(argv[2]);
        }
        copyFont(fname, page);
    } else {
        copyFont("romdat10.fnt", 32);
    }
}

static void verifyFont(char *fname, int pstart)
{
    FRESULT result;
    int pageno, b_read;
    int i;

    result = f_mount(0, &F_Object);
    if (result != FR_OK) {
        cons_printf("f_mount: %d\n", result);
        return;
    }
    result = f_open(&f_font, fname, FA_OPEN_EXISTING|FA_READ);
    if (result != FR_OK) {
        syslog(LOG_NOTICE, "f_open --> RESULT = %d", result);
        return;
    }
    pageno = pstart;
    while (1) {
        result = f_read(&f_font, f_buffer, 512, &b_read);
        if (result != FR_OK) {
            syslog(LOG_NOTICE, "f_read failed with %d", result);
            break;
        }
        if (b_read <= 0) {
            syslog(LOG_NOTICE, "page: %d, bread = %d", pageno, b_read);
            break;
        }
        nandReadPage(pageno >> 5, pageno & 31, 0, nand_buffer);
        for (i = 0; i < 512; i++) {
            if (f_buffer[i] != nand_buffer[i]) {
                syslog(LOG_NOTICE, "page %d, %i", pageno, i);
                break;
            }
        }
        pageno++;
    }
    f_close(&f_font);
}

void verify_command(int argc, char **argv)
{
    int page = 32;
    char *fname;

    if (argc > 1) {
        fname = argv[1];
        if (argc > 2) {
            page = atoi(argv[2]);
        }
        verifyFont(fname, page);
    } else {
        verifyFont("romdat10.fnt", 32);
    }
}
