/**
  * Creates a new directory with the given name and location
  *
  * @param name The fully qualified name of the new directory.
  * @return MICROBIT_OK on success, MICROBIT_INVALID_PARAMETER if the path is invalid, or MICROBT_NO_RESOURCES if the FileSystem is full.
  */
int MicroBitFileSystem::createDirectory(char const *name)
{
    DirectoryEntry* directory;        // Directory holding this file.
    DirectoryEntry* dirent;            // Entry in the direcoty of this file.

    // Protect against accidental re-initialisation
    if ((status & MBFS_STATUS_INITIALISED) == 0)
        return MICROBIT_NOT_SUPPORTED;

    // Reject invalid filenames.
    if (!isValidFilename(name))
        return MICROBIT_INVALID_PARAMETER;

    // Determine the directory for this file.
    directory = getDirectoryOf(name);

    if (directory == NULL)
        return MICROBIT_INVALID_PARAMETER;

    // Find the DirectoryEntry associated with the given name (if it exists).
    // We don't permit files or directories with the same name.
    dirent = getDirectoryEntry(name, directory);

    if (dirent)
        return MICROBIT_INVALID_PARAMETER;

    dirent = createFile(name, directory, true);
    if (dirent == NULL)
        return MICROBIT_NO_RESOURCES;

    return MICROBIT_OK;
}
 std::string prefixSanityFix(std::string prefix) {
   prefix.erase(std::remove_if(prefix.begin(), prefix.end(), ::isspace), prefix.end());
   prefix.erase(std::remove(prefix.begin(), prefix.end(), '/'), prefix.end());
   prefix.erase(std::remove(prefix.begin(), prefix.end(), '\\'), prefix.end());
   prefix.erase(std::remove(prefix.begin(), prefix.end(), '.'), prefix.end());
   prefix.erase(std::remove(prefix.begin(), prefix.end(), ':'), prefix.end());
   if (!isValidFilename(prefix)) {
     return
     {
     };
   }
   return prefix;
 }
/**
  * Open a new file, and obtain a new file handle (int) to
  * read/write/seek the file. The flags are:
  *  - MB_READ : read from the file.
  *  - MB_WRITE : write to the file.
  *  - MB_CREAT : create a new file, if it doesn't already exist.
  *
  * If a file is opened that doesn't exist, and MB_CREAT isn't passed,
  * an error is returned, otherwise the file is created.
  *
  * @param filename name of the file to open, must contain only printable characters.
  * @param flags One or more of MB_READ, MB_WRITE or MB_CREAT. 
  * @return return the file handle,MICROBIT_NOT_SUPPORTED if the file system has
  *         not been initialised MICROBIT_INVALID_PARAMETER if the filename is
  *         too large, MICROBIT_NO_RESOURCES if the file system is full.
  *
  * @code
  * MicroBitFileSystem f();
  * int fd = f.open("test.txt", MB_WRITE|MB_CREAT);
  * if(fd<0)
  *    print("file open error");
  * @endcode
  */
int MicroBitFileSystem::open(char const * filename, uint32_t flags)
{
    FileDescriptor *file;               // File Descriptor of this file.
    DirectoryEntry* directory;          // Directory holding this file.
    DirectoryEntry* dirent;             // Entry in the direcoty of this file.
    int id;                             // FileDescriptor id to be return to the caller.

    // Protect against accidental re-initialisation
    if ((status & MBFS_STATUS_INITIALISED) == 0)
        return MICROBIT_NOT_SUPPORTED;

    // Reject invalid filenames.
    if(!isValidFilename(filename))
        return MICROBIT_INVALID_PARAMETER;

    // Determine the directory for this file.
    directory = getDirectoryOf(filename);

    if (directory == NULL)
        return MICROBIT_INVALID_PARAMETER;

    // Find the DirectoryEntry assoviate with the given file (if it exists).
    dirent = getDirectoryEntry(filename, directory);

    // Only permit files to be opened once... 
    // also, detemrine a valid ID for this open file as we go.
    file = openFiles;
    id = 0;
    
    while (file && dirent)
    {
        if (file->dirent == dirent)
            return MICROBIT_NOT_SUPPORTED;

        if (file->id == id)
        {
            id++;
            file = openFiles;
            continue;
        }

        file = file->next;
    }

    if (dirent == NULL)
    {
        // If the file doesn't exist, and we haven't been asked to create it, then there's nothing we can do.
        if (!(flags & MB_CREAT))
            return MICROBIT_INVALID_PARAMETER;

        dirent = createFile(filename, directory, false);
        if (dirent == NULL)
            return MICROBIT_NO_RESOURCES;
    }

    // Try to add a new FileDescriptor into this directory.
    file = new FileDescriptor;
    if (file == NULL)
        return MICROBIT_NO_RESOURCES;

    // Populate the FileDescriptor
    file->flags = (flags & ~(MB_CREAT));
    file->id = id;
    file->length = dirent->flags == MBFS_DIRECTORY_ENTRY_NEW ? 0 : dirent->length;
    file->seek = (flags & MB_APPEND) ? file->length : 0;
    file->dirent = dirent;
    file->directory = directory;
    file->cacheLength = 0;

    // Add the file descriptor to the chain of open files.
    file->next = openFiles;
    openFiles = file;

    // Return the FileDescriptor id to the user
    return file->id;
}