// Copyright 2013 The Flutter Authors. 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:convert';
import 'dart:io';

import 'common.dart';
import 'io.dart' as io;
import 'logger.dart';

enum TerminalColor {
  red,
  green,
  blue,
  cyan,
  yellow,
  magenta,
  grey,
}

/// A class that contains the context settings for command text output to the
/// console.
class OutputPreferences {
  OutputPreferences({
    bool? wrapText,
    int? wrapColumn,
    bool? showColor,
    io.Stdio? stdio,
  })  : _stdio = stdio,
        wrapText = wrapText ?? stdio?.hasTerminal ?? false,
        _overrideWrapColumn = wrapColumn,
        showColor = showColor ?? false;

  /// A version of this class for use in tests.
  OutputPreferences.test(
      {this.wrapText = false,
      int wrapColumn = kDefaultTerminalColumns,
      this.showColor = false})
      : _overrideWrapColumn = wrapColumn,
        _stdio = null;

  final io.Stdio? _stdio;

  /// If [wrapText] is true, then any text sent to the context's [Logger]
  /// instance (e.g. from the [printError] or [printStatus] functions) will be
  /// wrapped (newlines added between words) to be no longer than the
  /// [wrapColumn] specifies. Defaults to true if there is a terminal. To
  /// determine if there's a terminal, [OutputPreferences] asks the context's
  /// stdio.
  final bool wrapText;

  /// The terminal width used by the [wrapText] function if there is no terminal
  /// attached to [io.Stdio], --wrap is on, and --wrap-columns was not specified.
  static const int kDefaultTerminalColumns = 100;

  /// The column at which output sent to the context's [Logger] instance
  /// (e.g. from the [printError] or [printStatus] functions) will be wrapped.
  /// Ignored if [wrapText] is false. Defaults to the width of the output
  /// terminal, or to [kDefaultTerminalColumns] if not writing to a terminal.
  final int? _overrideWrapColumn;
  int get wrapColumn {
    return _overrideWrapColumn ??
        _stdio?.terminalColumns ??
        kDefaultTerminalColumns;
  }

  /// Whether or not to output ANSI color codes when writing to the output
  /// terminal. Defaults to whatever [platform.stdoutSupportsAnsi] says if
  /// writing to a terminal, and false otherwise.
  final bool showColor;

  @override
  String toString() {
    return 'OutputPreferences[wrapText: $wrapText, wrapColumn: $wrapColumn, showColor: $showColor]';
  }
}

/// The command line terminal, if available.
abstract class Terminal {
  /// Create a new test [Terminal].
  ///
  /// If not specified, [supportsColor] defaults to `false`.
  factory Terminal.test({bool supportsColor, bool supportsEmoji}) =
      _TestTerminal;

  /// Whether the current terminal supports color escape codes.
  bool get supportsColor;

  /// Whether the current terminal can display emoji.
  bool get supportsEmoji;

  /// When we have a choice of styles (e.g. animated spinners), this selects the
  /// style to use.
  int get preferredStyle;

  /// Whether we are interacting with the flutter tool via the terminal.
  ///
  /// If not set, defaults to false.
  bool get usesTerminalUi;
  set usesTerminalUi(bool value);

  /// Whether there is a terminal attached to stdin.
  ///
  /// If true, this usually indicates that a user is using the CLI as
  /// opposed to using an IDE. This can be used to determine
  /// whether it is appropriate to show a terminal prompt,
  /// or whether an automatic selection should be made instead.
  bool get stdinHasTerminal;

  /// Warning mark to use in stdout or stderr.
  String get warningMark;

  /// Success mark to use in stdout.
  String get successMark;

  String bolden(String message);

  String color(String message, TerminalColor color);

  String clearScreen();

  bool get singleCharMode;
  set singleCharMode(bool value);

  /// Return keystrokes from the console.
  ///
  /// This is a single-subscription stream. This stream may be closed before
  /// the application exits.
  ///
  /// Useful when the console is in [singleCharMode].
  Stream<String> get keystrokes;

  /// Prompts the user to input a character within a given list. Re-prompts if
  /// entered character is not in the list.
  ///
  /// The `prompt`, if non-null, is the text displayed prior to waiting for user
  /// input each time. If `prompt` is non-null and `displayAcceptedCharacters`
  /// is true, the accepted keys are printed next to the `prompt`.
  ///
  /// The returned value is the user's input; if `defaultChoiceIndex` is not
  /// null, and the user presses enter without any other input, the return value
  /// will be the character in `acceptedCharacters` at the index given by
  /// `defaultChoiceIndex`.
  ///
  /// The accepted characters must be a String with a length of 1, excluding any
  /// whitespace characters such as `\t`, `\n`, or ` `.
  ///
  /// If [usesTerminalUi] is false, throws a [StateError].
  Future<String> promptForCharInput(
    List<String> acceptedCharacters, {
    required Logger logger,
    String? prompt,
    int? defaultChoiceIndex,
    bool displayAcceptedCharacters = true,
  });
}

class AnsiTerminal implements Terminal {
  AnsiTerminal({
    required io.Stdio stdio,
    DateTime?
        now, // Time used to determine preferredStyle. Defaults to 0001-01-01 00:00.
    bool? supportsColor,
  })  : _stdio = stdio,
        _now = now ?? DateTime(1),
        _supportsColor = supportsColor;

  final io.Stdio _stdio;
  final DateTime _now;

  static const String bold = '\u001B[1m';
  static const String resetAll = '\u001B[0m';
  static const String resetColor = '\u001B[39m';
  static const String resetBold = '\u001B[22m';
  static const String clear = '\u001B[2J\u001B[H';

  static const String red = '\u001b[31m';
  static const String green = '\u001b[32m';
  static const String blue = '\u001b[34m';
  static const String cyan = '\u001b[36m';
  static const String magenta = '\u001b[35m';
  static const String yellow = '\u001b[33m';
  static const String grey = '\u001b[90m';

  static const Map<TerminalColor, String> _colorMap = <TerminalColor, String>{
    TerminalColor.red: red,
    TerminalColor.green: green,
    TerminalColor.blue: blue,
    TerminalColor.cyan: cyan,
    TerminalColor.magenta: magenta,
    TerminalColor.yellow: yellow,
    TerminalColor.grey: grey,
  };

  static String colorCode(TerminalColor color) => _colorMap[color]!;

  @override
  bool get supportsColor => _supportsColor ?? stdout.supportsAnsiEscapes;
  final bool? _supportsColor;

  // Assume unicode emojis are supported when not on Windows.
  // If we are on Windows, unicode emojis are supported in Windows Terminal,
  // which sets the WT_SESSION environment variable. See:
  // https://github.com/microsoft/terminal/blob/master/doc/user-docs/index.md#tips-and-tricks
  @override
  bool get supportsEmoji =>
      !isWindows || Platform.environment.containsKey('WT_SESSION');

  @override
  int get preferredStyle {
    const int workdays = DateTime.friday;
    if (_now.weekday <= workdays) {
      return _now.weekday - 1;
    }
    return _now.hour + workdays;
  }

  final RegExp _boldControls = RegExp(
    '(${RegExp.escape(resetBold)}|${RegExp.escape(bold)})',
  );

  @override
  bool usesTerminalUi = false;

  @override
  String get warningMark {
    return bolden(color('[!]', TerminalColor.red));
  }

  @override
  String get successMark {
    return bolden(color('✓', TerminalColor.green));
  }

  @override
  String bolden(String message) {
    assert(message != null);
    if (!supportsColor || message.isEmpty) {
      return message;
    }
    final StringBuffer buffer = StringBuffer();
    for (String line in message.split('\n')) {
      // If there were bolds or resetBolds in the string before, then nuke them:
      // they're redundant. This prevents previously embedded resets from
      // stopping the boldness.
      line = line.replaceAll(_boldControls, '');
      buffer.writeln('$bold$line$resetBold');
    }
    final String result = buffer.toString();
    // avoid introducing a new newline to the emboldened text
    return (!message.endsWith('\n') && result.endsWith('\n'))
        ? result.substring(0, result.length - 1)
        : result;
  }

  @override
  String color(String message, TerminalColor color) {
    assert(message != null);
    if (!supportsColor || color == null || message.isEmpty) {
      return message;
    }
    final StringBuffer buffer = StringBuffer();
    final String colorCodes = _colorMap[color]!;
    for (String line in message.split('\n')) {
      // If there were resets in the string before, then keep them, but
      // restart the color right after. This prevents embedded resets from
      // stopping the colors, and allows nesting of colors.
      line = line.replaceAll(resetColor, '$resetColor$colorCodes');
      buffer.writeln('$colorCodes$line$resetColor');
    }
    final String result = buffer.toString();
    // avoid introducing a new newline to the colored text
    return (!message.endsWith('\n') && result.endsWith('\n'))
        ? result.substring(0, result.length - 1)
        : result;
  }

  @override
  String clearScreen() => supportsColor ? clear : '\n\n';

  @override
  bool get singleCharMode {
    if (!_stdio.stdinHasTerminal) {
      return false;
    }
    final io.Stdin stdin = _stdio.stdin as io.Stdin;
    return stdin.lineMode && stdin.echoMode;
  }

  @override
  set singleCharMode(bool value) {
    if (!_stdio.stdinHasTerminal) {
      return;
    }
    final io.Stdin stdin = _stdio.stdin as io.Stdin;
    // The order of setting lineMode and echoMode is important on Windows.
    if (value) {
      stdin.echoMode = false;
      stdin.lineMode = false;
    } else {
      stdin.lineMode = true;
      stdin.echoMode = true;
    }
  }

  @override
  bool get stdinHasTerminal => _stdio.stdinHasTerminal;

  Stream<String>? _broadcastStdInString;

  @override
  Stream<String> get keystrokes {
    return _broadcastStdInString ??= _stdio.stdin
        .transform<String>(const AsciiDecoder(allowInvalid: true))
        .asBroadcastStream();
  }

  @override
  Future<String> promptForCharInput(
    List<String> acceptedCharacters, {
    required Logger logger,
    String? prompt,
    int? defaultChoiceIndex,
    bool displayAcceptedCharacters = true,
  }) async {
    assert(acceptedCharacters.isNotEmpty);
    assert(prompt == null || prompt.isNotEmpty);
    if (!usesTerminalUi) {
      throw StateError('cannot prompt without a terminal ui');
    }
    List<String> charactersToDisplay = acceptedCharacters;
    if (defaultChoiceIndex != null) {
      assert(defaultChoiceIndex >= 0 &&
          defaultChoiceIndex < acceptedCharacters.length);
      charactersToDisplay = List<String>.of(charactersToDisplay);
      charactersToDisplay[defaultChoiceIndex] =
          bolden(charactersToDisplay[defaultChoiceIndex]);
      acceptedCharacters.add('');
    }
    String? choice;
    singleCharMode = true;
    while (choice == null ||
        choice.length > 1 ||
        !acceptedCharacters.contains(choice)) {
      if (prompt != null) {
        logger.printStatus(prompt, emphasis: true, newline: false);
        if (displayAcceptedCharacters) {
          logger.printStatus(' [${charactersToDisplay.join("|")}]',
              newline: false);
        }
        // prompt ends with ': '
        logger.printStatus(': ', emphasis: true, newline: false);
      }
      choice = (await keystrokes.first).trim();
      logger.printStatus(choice);
    }
    singleCharMode = false;
    if (defaultChoiceIndex != null && choice == '') {
      choice = acceptedCharacters[defaultChoiceIndex];
    }
    return choice;
  }
}

class _TestTerminal implements Terminal {
  _TestTerminal({this.supportsColor = false, this.supportsEmoji = false});

  @override
  bool usesTerminalUi = false;

  @override
  String bolden(String message) => message;

  @override
  String clearScreen() => '\n\n';

  @override
  String color(String message, TerminalColor color) => message;

  @override
  Stream<String> get keystrokes => const Stream<String>.empty();

  @override
  Future<String> promptForCharInput(
    List<String> acceptedCharacters, {
    required Logger logger,
    String? prompt,
    int? defaultChoiceIndex,
    bool displayAcceptedCharacters = true,
  }) {
    throw UnsupportedError(
        'promptForCharInput not supported in the test terminal.');
  }

  @override
  bool get singleCharMode => false;
  @override
  set singleCharMode(bool value) {}

  @override
  final bool supportsColor;

  @override
  final bool supportsEmoji;

  @override
  int get preferredStyle => 0;

  @override
  bool get stdinHasTerminal => false;

  @override
  String get successMark => '✓';

  @override
  String get warningMark => '[!]';
}
