// Copyright (c) 2016, the Dart project authors.  Please see the AUTHORS file
// for details. All rights reserved. Use of this source code is governed by a
// BSD-style license that can be found in the LICENSE file.

import 'dart:io';
import 'dart:math' as math;

import 'package:async/async.dart';
import 'package:pedantic/pedantic.dart';

import '../util/io.dart';

/// An interactive console for taking user commands.
class Console {
  /// The registered commands.
  final _commands = <String, _Command>{};

  /// The pending next line of standard input, if we're waiting on one.
  CancelableOperation _nextLine;

  /// Whether the console is currently running.
  bool _running = false;

  /// The terminal escape for red text, or the empty string if this is Windows
  /// or not outputting to a terminal.
  final String _red;

  /// The terminal escape for bold text, or the empty string if this is
  /// Windows or not outputting to a terminal.
  final String _bold;

  /// The terminal escape for removing test coloring, or the empty string if
  /// this is Windows or not outputting to a terminal.
  final String _noColor;

  /// Creates a new [Console].
  ///
  /// If [color] is true, this uses Unix terminal colors.
  Console({bool color = true})
      : _red = color ? '\u001b[31m' : '',
        _bold = color ? '\u001b[1m' : '',
        _noColor = color ? '\u001b[0m' : '' {
    registerCommand('help', 'Displays this help information.', _displayHelp);
  }

  /// Registers a command to be run whenever the user types [name].
  ///
  /// The [description] should be a one-line description of the command to print
  /// in the help output. The [body] callback will be called when the user types
  /// the command, and may return a [Future].
  void registerCommand(
      String name, String description, dynamic Function() body) {
    if (_commands.containsKey(name)) {
      throw ArgumentError('The console already has a command named "$name".');
    }

    _commands[name] = _Command(name, description, body);
  }

  /// Starts running the console.
  ///
  /// This prints the initial prompt and loops while waiting for user input.
  void start() {
    _running = true;
    unawaited(() async {
      while (_running) {
        stdout.write('> ');
        _nextLine = stdinLines.cancelable((queue) => queue.next);
        var commandName = await _nextLine.value;
        _nextLine = null;

        var command = _commands[commandName];
        if (command == null) {
          stderr.writeln(
              '${_red}Unknown command $_bold$commandName$_noColor$_red.'
              '$_noColor');
        } else {
          await command.body();
        }
      }
    }());
  }

  /// Stops the console running.
  void stop() {
    _running = false;
    if (_nextLine != null) {
      stdout.writeln();
      _nextLine.cancel();
    }
  }

  /// Displays the help info for the console commands.
  void _displayHelp() {
    var maxCommandLength =
        _commands.values.map((command) => command.name.length).reduce(math.max);

    for (var command in _commands.values) {
      var name = command.name.padRight(maxCommandLength + 4);
      print('$_bold$name$_noColor${command.description}');
    }
  }
}

/// An individual console command.
class _Command {
  /// The name of the command.
  final String name;

  /// The single-line description of the command.
  final String description;

  /// The callback to run when the command is invoked.
  final Function body;

  _Command(this.name, this.description, this.body);
}
