/**
   * Constructor. Initializes input from System.in.
   *
   * @param controller The controller to use.
   * @param ui The user interface to send messages to.
   * @param settings The settings to use.
   * @param consoleMessages The messages to use for the console ui.
   * @param coreMessages The messages to use for the core components.
   */
  public ConsoleInput(
      final Controller controller,
      final UserInterface ui,
      final Settings settings,
      final ConsoleMessages consoleMessages,
      final CoreMessages coreMessages) {
    Validate.notNull(controller, "Controller can not be null");
    Validate.notNull(ui, "UserInterface can not be null");
    Validate.notNull(settings, "Settings can not be null");
    Validate.notNull(consoleMessages, "Console messages can not be null");
    Validate.notNull(coreMessages, "Core messages can not be null");

    this.controller = controller;

    setName("ConsoleInputThread");
    msgController = ui.getMessageController();
    stdin = new BufferedReader(new InputStreamReader(System.in));
    cmdParser = new CommandParser(controller, ui, settings, coreMessages);

    shutdownHook =
        new Thread("ConsoleInputShutdownHook") {
          @Override
          public void run() {
            System.out.println(consoleMessages.getMessage("console.quit.message"));
          }
        };
  }
  /**
   * Makes sure the application reacts when the network is unavailable.
   *
   * @param silent If true, wont show the "you lost contact..." message to the user.
   */
  @Override
  public void networkWentDown(final boolean silent) {
    ui.showTopic();

    if (isLoggedOn()) {
      if (!silent) {
        msgController.showSystemMessage("You lost contact with the network");
      }
    } else {
      msgController.showSystemMessage("You logged off");
    }
  }
  /**
   * Constructor. Initializes the controller, but does not log on to the network.
   *
   * @param ui The active user interface object.
   * @param settings The settings to use.
   */
  public Controller(final UserInterface ui, final Settings settings) {
    Validate.notNull(ui, "User interface can not be null");
    Validate.notNull(settings, "Settings can not be null");

    this.ui = ui;
    this.settings = settings;

    Runtime.getRuntime()
        .addShutdownHook(
            new Thread("ControllerShutdownHook") {
              @Override
              public void run() {
                logOff(false);
                shutdown();
              }
            });

    me = settings.getMe();
    userListController = new UserListController(settings);
    chatState = new ChatState();
    tList = new TransferList();
    wList = new WaitingList();
    idleThread = new IdleThread(this, ui, settings);
    networkService = new NetworkService(settings);
    final MessageResponder msgResponder = new DefaultMessageResponder(this, ui, settings);
    final PrivateMessageResponder privmsgResponder =
        new DefaultPrivateMessageResponder(this, ui, settings);
    final MessageParser msgParser = new MessageParser(msgResponder, settings);
    networkService.registerMessageReceiverListener(msgParser);
    final PrivateMessageParser privmsgParser = new PrivateMessageParser(privmsgResponder, settings);
    networkService.registerUDPReceiverListener(privmsgParser);
    messages = new Messages(networkService, settings);
    networkService.registerNetworkConnectionListener(this);
    msgController = ui.getMessageController();

    new DayTimer(ui);
    idleThread.start();

    msgController.showSystemMessage(
        "Welcome to " + Constants.APP_NAME + " v" + Constants.APP_VERSION + "!");
    final String date = Tools.dateToString(null, "EEEE, d MMMM yyyy");
    msgController.showSystemMessage("Today is " + date);
  }
  /**
   * Makes sure the application reacts when the network is available.
   *
   * @param silent If true, wont show the "you are connected..." message to the user.
   */
  @Override
  public void networkCameUp(final boolean silent) {
    // Network came up after a logon
    if (!isLoggedOn()) {
      runDelayedLogon();
      sendLogOn();
    }

    // Network came up after a timeout
    else {
      ui.showTopic();

      if (!silent) {
        msgController.showSystemMessage("You are connected to the network again");
      }

      messages.sendTopicRequestedMessage(getTopic());
      messages.sendExposingMessage();
      messages.sendGetTopicMessage();
      messages.sendExposeMessage();
      messages.sendIdleMessage();
    }
  }