// Copyright (c) 2013, 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:math' as math;

import '../args.dart';
import 'utils.dart';

/// Generates a string of usage (i.e. help) text for a list of options.
///
/// Internally, it works like a tabular printer. The output is divided into
/// three horizontal columns, like so:
///
///     -h, --help  Prints the usage information
///     |  |        |                                 |
///
/// It builds the usage text up one column at a time and handles padding with
/// spaces and wrapping to the next line to keep the cells correctly lined up.
///
/// [lineLength] specifies the horizontal character position at which the help
/// text is wrapped. Help that extends past this column will be wrapped at the
/// nearest whitespace (or truncated if there is no available whitespace). If
/// `null` there will not be any wrapping.
String generateUsage(List optionsAndSeparators, {int? lineLength}) =>
    _Usage(optionsAndSeparators, lineLength).generate();

class _Usage {
  /// Abbreviation, long name, help.
  static const _columnCount = 3;

  /// A list of the [Option]s intermingled with [String] separators.
  final List _optionsAndSeparators;

  /// The working buffer for the generated usage text.
  final _buffer = StringBuffer();

  /// The column that the "cursor" is currently on.
  ///
  /// If the next call to [write()] is not for this column, it will correctly
  /// handle advancing to the next column (and possibly the next row).
  int _currentColumn = 0;

  /// The width in characters of each column.
  late final _columnWidths = _calculateColumnWidths();

  /// How many newlines need to be rendered before the next bit of text can be
  /// written.
  ///
  /// We do this lazily so that the last bit of usage doesn't have dangling
  /// newlines. We only write newlines right *before* we write some real
  /// content.
  int _newlinesNeeded = 0;

  /// The horizontal character position at which help text is wrapped.
  ///
  /// Help that extends past this column will be wrapped at the nearest
  /// whitespace (or truncated if there is no available whitespace).
  final int? lineLength;

  _Usage(this._optionsAndSeparators, this.lineLength);

  /// Generates a string displaying usage information for the defined options.
  /// This is basically the help text shown on the command line.
  String generate() {
    for (var optionOrSeparator in _optionsAndSeparators) {
      if (optionOrSeparator is String) {
        _writeSeparator(optionOrSeparator);
        continue;
      }
      var option = optionOrSeparator as Option;
      if (option.hide) continue;
      _writeOption(option);
    }

    return _buffer.toString();
  }

  void _writeSeparator(String separator) {
    // Ensure that there's always a blank line before a separator.
    if (_buffer.isNotEmpty) _buffer.write('\n\n');
    _buffer.write(separator);
    _newlinesNeeded = 1;
  }

  void _writeOption(Option option) {
    _write(0, _abbreviation(option));
    _write(1, '${_longOption(option)}${_mandatoryOption(option)}');

    if (option.help != null) _write(2, option.help!);

    if (option.allowedHelp != null) {
      var allowedNames = option.allowedHelp!.keys.toList();
      allowedNames.sort();
      _newline();
      for (var name in allowedNames) {
        _write(1, _allowedTitle(option, name));
        _write(2, option.allowedHelp![name]!);
      }
      _newline();
    } else if (option.allowed != null) {
      _write(2, _buildAllowedList(option));
    } else if (option.isFlag) {
      if (option.defaultsTo == true) {
        _write(2, '(defaults to on)');
      }
    } else if (option.isMultiple) {
      if (option.defaultsTo != null && option.defaultsTo.isNotEmpty) {
        var defaults =
            (option.defaultsTo as List).map((value) => '"$value"').join(', ');
        _write(2, '(defaults to $defaults)');
      }
    } else if (option.defaultsTo != null) {
      _write(2, '(defaults to "${option.defaultsTo}")');
    }
  }

  String _abbreviation(Option option) =>
      option.abbr == null ? '' : '-${option.abbr}, ';

  String _longOption(Option option) {
    var result;
    if (option.negatable!) {
      result = '--[no-]${option.name}';
    } else {
      result = '--${option.name}';
    }

    if (option.valueHelp != null) result += '=<${option.valueHelp}>';

    return result;
  }

  String _mandatoryOption(Option option) {
    return option.mandatory ? ' (mandatory)' : '';
  }

  String _allowedTitle(Option option, String allowed) {
    var isDefault = option.defaultsTo is List
        ? option.defaultsTo.contains(allowed)
        : option.defaultsTo == allowed;
    return '      [$allowed]' + (isDefault ? ' (default)' : '');
  }

  List<int> _calculateColumnWidths() {
    var abbr = 0;
    var title = 0;
    for (var option in _optionsAndSeparators) {
      if (option is! Option) continue;
      if (option.hide) continue;

      // Make room in the first column if there are abbreviations.
      abbr = math.max(abbr, _abbreviation(option).length);

      // Make room for the option.
      title = math.max(title, _longOption(option).length + _mandatoryOption(option).length);

      // Make room for the allowed help.
      if (option.allowedHelp != null) {
        for (var allowed in option.allowedHelp!.keys) {
          title = math.max(title, _allowedTitle(option, allowed).length);
        }
      }
    }

    // Leave a gutter between the columns.
    title += 4;
    return [abbr, title];
  }

  void _newline() {
    _newlinesNeeded++;
    _currentColumn = 0;
  }

  void _write(int column, String text) {
    var lines = text.split('\n');
    // If we are writing the last column, word wrap it to fit.
    if (column == _columnWidths.length && lineLength != null) {
      var start =
          _columnWidths.take(column).reduce((start, width) => start + width);
      lines = [
        for (var line in lines)
          ...wrapTextAsLines(line, start: start, length: lineLength),
      ];
    }

    // Strip leading and trailing empty lines.
    while (lines.isNotEmpty && lines.first.trim() == '') {
      lines.removeAt(0);
    }
    while (lines.isNotEmpty && lines.last.trim() == '') {
      lines.removeLast();
    }

    for (var line in lines) {
      _writeLine(column, line);
    }
  }

  void _writeLine(int column, String text) {
    // Write any pending newlines.
    while (_newlinesNeeded > 0) {
      _buffer.write('\n');
      _newlinesNeeded--;
    }

    // Advance until we are at the right column (which may mean wrapping around
    // to the next line.
    while (_currentColumn != column) {
      if (_currentColumn < _columnCount - 1) {
        _buffer.write(' ' * _columnWidths[_currentColumn]);
      } else {
        _buffer.write('\n');
      }
      _currentColumn = (_currentColumn + 1) % _columnCount;
    }

    if (column < _columnWidths.length) {
      // Fixed-size column, so pad it.
      _buffer.write(text.padRight(_columnWidths[column]));
    } else {
      // The last column, so just write it.
      _buffer.write(text);
    }

    // Advance to the next column.
    _currentColumn = (_currentColumn + 1) % _columnCount;

    // If we reached the last column, we need to wrap to the next line.
    if (column == _columnCount - 1) _newlinesNeeded++;
  }

  String _buildAllowedList(Option option) {
    var isDefault = option.defaultsTo is List
        ? option.defaultsTo.contains
        : (value) => value == option.defaultsTo;

    var allowedBuffer = StringBuffer();
    allowedBuffer.write('[');
    var first = true;
    for (var allowed in option.allowed!) {
      if (!first) allowedBuffer.write(', ');
      allowedBuffer.write(allowed);
      if (isDefault(allowed)) {
        allowedBuffer.write(' (default)');
      }
      first = false;
    }
    allowedBuffer.write(']');
    return allowedBuffer.toString();
  }
}
