/*
  * Prints the mail help informaton.
  */
 private void showHelp() {
   Terminal.println("Mail Help:");
   Terminal.println("\t ?\t\t\tThis help information");
   Terminal.println("\t i\t\t\tDisplay inbox");
   Terminal.println("\t [n]\t\tRead Message [n]");
   Terminal.println("\t q\t\t\tQuit Mail");
 }
 /*
  * Opens a mail.
  */
 private void openMail(int id) {
   Mail m = mailbox.getMail(id);
   Terminal.println();
   if (m != null) {
     m.open();
     Terminal.println();
   }
 }
    @Override
    protected void run() {
      String input;

      while (isRunning()) {
        // Print prompt
        Terminal.print(getPrompt());

        // Read input from the user
        input = Terminal.readLine();

        // Check if the user typed one of the mail commands
        switch (input) {
          case "i":
            showInbox();
            continue;
          case "q":
            terminate();
            continue;
          case "?":
            showHelp();
            continue;
        }

        String mailIDStr = "";
        char c;

        // Extracts a number from the user-typed string
        for (int i = 0; i < Math.min(4, input.length()); i++) {
          c = input.charAt(i);
          if (c > 0x29 && c < 0x3A) {
            // Append the character if it is a numeric char
            mailIDStr += c;
          } else {
            // Break at the first occurance of a non-numeric char
            break;
          }
        }

        if (mailIDStr.isEmpty()) {
          Terminal.println(DEFAULT_MESSAGE);
          continue;
        }

        // Open the specified mail
        int mailID = Integer.parseInt(mailIDStr);
        openMail(mailID);
      }
    }
  /**
   * Loads user configuration
   *
   * @return the last loaded user account
   */
  public static UserAccount loadUserConfiguration() {
    UserAccount u = null;

    try {
      DATFileReader reader = new DATFileReader(USERS_PATH);
      reader.setCommentChar('#');
      reader.ignoreWhitespaces(true);

      // Read file line by line
      while (reader.loadNextLine()) {
        // Read data from current line
        String systemName = reader.nextField();
        String username = reader.nextField();
        String password = reader.nextField();
        int homeDirID = Integer.parseInt(reader.nextField());
        boolean isUnlisted = Boolean.parseBoolean(reader.nextField());

        Server system = Terminal.getServer(systemName);
        HomeDirectory homeDir =
            (HomeDirectory) system.getFileSystem().getFileSystemObject(homeDirID);
        homeDir.setUnlisted(isUnlisted);
        u = new UserAccount(username, password, homeDir);
        system.addUser(u);

        Logger.info("Loaded user: %s (system: %s)\n", username, systemName);
      }
    } catch (IOException ex) {
      Logger.stackTrace(ex);
      showConfigFileErrorMessage(ex);
    }

    return u;
  }
  /**
   * Loads server configuration.
   *
   * @return the last loaded server
   */
  public static Server loadServerConfiguration() {
    Server s = null;

    try {
      DATFileReader reader = new DATFileReader(SERVERS_PATH);
      reader.setCommentChar('#');
      reader.ignoreWhitespaces(true);

      // Read file line by line
      while (reader.loadNextLine()) {
        // Read data from current line
        String serverName = reader.nextField();
        String loginMessage = reader.nextField();
        s = new Server(serverName, loginMessage);
        Terminal.addServer(s);

        Logger.info("Loaded server: %s\n", serverName);
      }

    } catch (IOException ex) {
      Logger.stackTrace(ex);
      showConfigFileErrorMessage(ex);
    }

    return s;
  }
  /** Loads the mail configuration. */
  public static void loadMailConfiguration() {
    try {
      DATFileReader reader = new DATFileReader(MAIL_PATH);
      reader.setCommentChar('#');
      reader.ignoreWhitespaces(true);

      // Read file line by line
      while (reader.loadNextLine()) {
        // Read data from current line
        String systemName = reader.nextField();
        String userName = reader.nextField();
        String sender = reader.nextField();
        String date = reader.nextField();
        String subject = reader.nextField();
        String resourceName = reader.nextField();

        Server system = Terminal.getServer(systemName);
        UserAccount user = system.getUser(userName);
        Mail m = new Mail(sender, date, subject, resourceName);
        user.getMailbox().addMail(m);

        Logger.info(
            "Loaded mail: subject: %s (user: %s, system: %s%s)\n",
            subject.isEmpty() ? "<no subject>" : subject,
            userName,
            systemName,
            resourceName.isEmpty() ? "" : ", resource: " + resourceName);
      }
    } catch (IOException ex) {
      Logger.stackTrace(ex);
      showConfigFileErrorMessage(ex);
    }
  }
    /*
     * Shows the contents of the inbox.
     */
    private void showInbox() {
      Terminal.println("id\t\t\t from\t\t\t\t\t  " + "date\t\t\t\t\t   subject");

      List<Mail> mail = mailbox.getAllMail();
      Mail m;
      int tabCount;

      for (int i = 0; i < mail.size(); i++) {
        m = mail.get(i);

        // Print number
        if (i < 10) {
          Terminal.print(' ');
        }
        Terminal.print(i + " ");

        // Print sender
        Terminal.print(m.getSender());
        tabCount = 7 - (int) Math.round((double) m.getSender().length() / ScreenBuffer.TAB_LENGTH);
        printTabs(tabCount);

        // Print date
        Terminal.print(m.getDate());
        tabCount = 6 - (int) Math.floor((double) m.getDate().length() / ScreenBuffer.TAB_LENGTH);
        printTabs(tabCount);

        // Print subject
        Terminal.print(m.getSubject());
        Terminal.println();
      }
    }
    @Override
    protected void run() {
      String input;

      // Simple input loop
      while (isRunning()) {
        Terminal.print(getPrompt());
        input = Terminal.readLine();
        if (input.equalsIgnoreCase("quit")) {
          Terminal.println("It's been nice talking with you!  " + "Goodbye!");
          terminate();
        } else {
          /* Alicia gives a random response regardless of what the
             user types. What a great listener!
          */
          Terminal.println(getRandomResponse());
        }
      }
    }
  /** Loads the message of the day (MOTD). This is displayed when the terminal is first opened. */
  public static void loadMOTD() {
    String motd = "";
    String line;

    try {
      BufferedReader fileReader = new BufferedReader(new FileReader(MOTD_PATH));

      while ((line = fileReader.readLine()) != null) {
        motd += line + "\n";
      }

      Terminal.setMOTD(motd);
      Logger.info("Loaded MOTD");
    } catch (IOException ex) {
      Logger.stackTrace(ex);
      showConfigFileErrorMessage(ex);
    }
  }
 /*
  * Prints n tabs to the console.
  */
 private void printTabs(int n) {
   for (int i = 0; i < n; i++) {
     Terminal.print('\t');
   }
 }
 @Override
 public void exec(String[] args) {
   mailbox = Terminal.getActiveLoginShell().getUser().getMailbox();
   MailShell shell = new MailShell();
   shell.exec();
 }
 @Override
 protected void onLaunch() {
   showInbox();
   Terminal.println(DEFAULT_MESSAGE);
 }
 @Override
 protected void onLaunch() {
   Terminal.println("Welcome to Alicia, your virtual therapist.  " + "(type quit to exit)");
 }
  /**
   * Loads the filesystem configuration.
   *
   * @param exes a Map containing classes representing executable files and their corresponding
   *     names
   */
  public static void loadFileSystemConfiguration(
      Map<String, Class<? extends ExecutableFile>> exes) {
    /* Load files into temporary filesystem. The temporary filesytem is used
       to access files while the actual filesystem is being built.
    */
    FileSystem tempFileSystem = loadFiles(exes);

    try {
      DATFileReader reader = new DATFileReader(FILESYSTEM_PATH);
      reader.setCommentChar('#');
      reader.ignoreWhitespaces(true);

      // Read file line by line
      while (reader.loadNextLine()) {
        // Read data from current line
        int id = Integer.parseInt(reader.nextField());
        String systemName = reader.nextField();
        String dirName = reader.nextField();
        int parentID = Integer.parseInt(reader.nextField());
        String files = "";
        if (reader.hasNextField()) {
          files = reader.nextField();
        }

        Server system = Terminal.getServer(systemName);

        Directory dir;
        if (parentID == -1 || (id > 600 && id < 700)) {
          // Load directory, set it as root on the current system
          dir = new Directory(id, dirName);
          system.setFileSystem(new FileSystem(dir));
        } else if (id > 800 && id < 900) {
          // Load directory as as user's home directory
          dir = new HomeDirectory(id, dirName);
        } else {
          // Load generic directory
          dir = new Directory(id, dirName);
        }

        /* Place the directory in the correct location in the filesystem
           tree
        */
        FileSystemObject parent = system.getFileSystem().getFileSystemObject(parentID);
        if (parent != null) {
          parent.addChild(dir);
        }

        // Populate directory with files (if it has any)
        String[] fileIDList = files.split(" ");
        for (String fileIDStr : fileIDList) {
          if (fileIDStr.isEmpty()) {
            continue;
          }
          int fileID = Integer.parseInt(fileIDStr);

          // Get file from temporary filesystem based on file ID
          File file = (File) tempFileSystem.getFileSystemObject(fileID);
          if (file == null) {
            Logger.error(
                "Unresolved file ID: %d " + "(dir: %s, system: %s)\n", fileID, dirName, systemName);
            continue;
          }

          // Place the file in the directory
          dir.addChild(file);
        }

        Logger.info(
            "Loaded directory: %s (system: %s, id: ID)\n",
            dirName.isEmpty() ? "<no name, root?>" : dirName, systemName, id);
      }
    } catch (IOException ex) {
      Logger.stackTrace(ex);
      showConfigFileErrorMessage(ex);
    }
  }