#include <stdbool.h>
#include <stddef.h>
#include <string.h>
#include <stdio.h>

#include "common.h"
#include "ff.h"
#include "io.h"
#include "console.h"

#define MAX_FAST_FRAGMENTS 16

/* Extend these with a lot more stuff */
#define CLTBL_SIZE ((MAX_FAST_FRAGMENTS+1)*2)

struct drive {
    FIL fp;
    DWORD cltbl[CLTBL_SIZE];
    bool mounted;
};

#define MAX_DRIVES 8		/* Drives per controller */
struct disk_type {
    char name[4];
    struct drive drive[MAX_DRIVES];
};

#define DISK_TYPES 4
static struct disk_type __attribute__((section(".dram.bss"))) disks[DISK_TYPES];
static const char disk_names[][4] = { "hd", "sf", "mf", "mo" };

/*
 * Look for ABC/UFD-DOS disks and open them
 */
void mount_abcdrives(void)
{
    char filename_buf[64];
    unsigned int type;
    unsigned int drive;
    int whichabc = (ABC_STATUS & ABC_STATUS_800) ? 800 : 80;
    FRESULT rv;

    for (type = 0; type < DISK_TYPES; type++) {
	memcpy(disks[type].name, disk_names[type], 4);

	for (drive = 0; drive < MAX_DRIVES; drive++) {
	    struct drive *drv = &disks[type].drive[drive];

	    drv->mounted = false;

	    snprintf(filename_buf, sizeof filename_buf,
		     "/abcdisk.%d/%s%u",
		     whichabc, disks[type].name, drive);

	    rv = f_open(&drv->fp, filename_buf,
			FA_READ|FA_WRITE|FA_OPEN_EXISTING);

	    if (rv != FR_OK) {
		snprintf(filename_buf, sizeof filename_buf,
			 "/abcdisk/%s%u",
			 disks[type].name, drive);

		rv = f_open(&drv->fp, filename_buf,
			    FA_READ|FA_WRITE|FA_OPEN_EXISTING);
	    }

	    if (rv != FR_OK)
		continue;

	    drv->mounted = true;

	    con_printf("%s%u: mounted %s\n", disks[type].name, drive,
		       filename_buf);

	    /* Try to create memoized extent lists */

	    drv->cltbl[0] = CLTBL_SIZE;
	    drv->fp.cltbl = drv->cltbl;

	    rv = f_lseek(&drv->fp, CREATE_LINKMAP);
	    if (rv != FR_OK) {
		con_printf("%s%u: warning: file too fragmented, will be slow\n",
			   disks[type].name, drive);
	    }
	}
    }
}