// Copyright (c) 2017 The Regents of the University of Michigan.
// All Rights Reserved. Licensed according to the terms of the Revised
// BSD License. See LICENSE.txt for details.

const EventEmitter = require("events");

module.exports = function() {
  let internal = {};
  let fsMock = {};

  fsMock.stat = function(filename, callback) {
    if (internal.isValid(filename)) {
      let file = internal.get(filename);

      callback(undefined, {
        "size": file.length,

        "isDirectory": () => {
          return file instanceof Map;
        }
      });
    }

    else
      callback("error");
  };

  fsMock.readdir = fsMock.stat;

  fsMock.createReadStream = function(filename) {
    let stream = new EventEmitter();

    setTimeout(function() {
      if (internal.isValid(filename)) {
        stream.emit("data", internal.getFileData(filename));
        stream.emit("end");
      }

      else
        stream.emit("error");
    }, 30);

    return stream;
  };

  fsMock.set = function(filename, content) {
    let split = internal.split(filename);
    split.assertNotDir();
    split.map.set(split.name, content);
  };

  fsMock.delete = function(filename) {
    internal.files.delete(filename);
  };

  fsMock.mkdir = function(filename) {
    let split = internal.split(filename);
    split.assertNotDir();
    split.map.set(split.name, new Map());
  };

  internal.files = new Map();

  internal.isValid = function(filename) {
    let directories = filename.split("/");
    let localFilename = directories.pop();
    let fileMap = internal.files;

    for (let directory of directories) {
      fileMap = fileMap.get(directory);

      if (! fileMap instanceof Map)
        return false;
    }

    return fileMap.has(localFilename);
  };

  internal.getFileData = function(filename) {
    return internal.files.get(filename);
  };

  internal.split = function(filename) {
    let directories = filename.split("/");
    let localFilename = directories.pop();
    let fileMap = internal.files;

    for (let directory of directories) {
      fileMap = fileMap.get(directory);

      if (! fileMap instanceof Map)
        throw "not a directory: " + directory;
    }

    return {
      "map": fileMap,
      "name": localFilename,
      "assertNotDir": function() {
        if (fileMap.get(localFilename) instanceof Map)
          throw "directory already here: " + filename;
      }
    };
  };

  internal.get = function(filename) {
    let split = internal.split(filename);
    return split.map.get(split.name);
  };

  return fsMock;
};

@@ -1453,297 +1453,163 @@
 let 
-directories = filename.split(%22/%22);%0A    let localFilename = directories.pop(
+split = internal.split(filename
 );%0A    
-let fileMap = internal.files;%0A%0A    for (let directory of directories) %7B%0A      fileMap = fileMap.get(directory);%0A%0A      if (! fileMap instanceof Map)%0A        return false;%0A    %7D%0A%0A    return fileMap.has(localF
+return split.map.has(split.name);%0A  %7D;%0A%0A  internal.getFileData = function(filename) %7B%0A    return internal.files.get(f
 ilen
@@ -1630,32 +1630,24 @@
 internal.get
-FileData
  = function(
@@ -1654,38 +1654,43 @@
 filename) %7B%0A    
-return
+let split =
  internal.files.
@@ -1679,38 +1679,72 @@
  = internal.
-files.get(file
+split(filename);%0A    return split.map.get(split.
 name);%0A  %7D;%0A
@@ -2311,132 +2311,8 @@
 %7D;%0A%0A
-  internal.get = function(filename) %7B%0A    let split = internal.split(filename);%0A    return split.map.get(split.name);%0A  %7D;%0A%0A
   re

Remove duplicate code