// Copyright 2014 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:math' as math;

import 'logger.dart';
import 'platform.dart';
import 'terminal.dart';

const String fire = '🔥';
const int maxLineWidth = 84;

/// Encapsulates the help text construction and printing.
class CommandHelp {
  CommandHelp({
    required Logger logger,
    required AnsiTerminal terminal,
    required Platform platform,
    required OutputPreferences outputPreferences,
  }) : _logger = logger,
       _terminal = terminal,
       _platform = platform,
       _outputPreferences = outputPreferences;

  final Logger _logger;

  final AnsiTerminal _terminal;

  final Platform _platform;

  final OutputPreferences _outputPreferences;

  // COMMANDS IN ALPHABETICAL ORDER.
  // Uppercase first, then lowercase.
  // When updating this, update all the tests in command_help_test.dart accordingly.

  late final CommandHelpOption I = _makeOption(
    'I',
    'Toggle oversized image inversion.',
    'debugInvertOversizedImages',
  );

  late final CommandHelpOption L = _makeOption(
    'L',
    'Dump layer tree to the console.',
    'debugDumpLayerTree',
  );

  late final CommandHelpOption M = _makeOption(
    'M',
    'Write SkSL shaders to a unique file in the project directory.',
  );

  late final CommandHelpOption P = _makeOption(
    'P',
    'Toggle performance overlay.',
    'WidgetsApp.showPerformanceOverlay',
  );

  late final CommandHelpOption R = _makeOption(
    'R',
    'Hot restart.',
  );

  late final CommandHelpOption S = _makeOption(
    'S',
    'Dump accessibility tree in traversal order.',
    'debugDumpSemantics',
  );

  late final CommandHelpOption U = _makeOption(
    'U',
    'Dump accessibility tree in inverse hit test order.',
    'debugDumpSemantics',
  );

  late final CommandHelpOption a = _makeOption(
    'a',
    'Toggle timeline events for all widget build methods.',
    'debugProfileWidgetBuilds',
  );

  late final CommandHelpOption b = _makeOption(
    'b',
    'Toggle platform brightness (dark and light mode).',
    'debugBrightnessOverride',
  );

  late final CommandHelpOption c = _makeOption(
    'c',
    'Clear the screen',
  );

  late final CommandHelpOption d = _makeOption(
    'd',
    'Detach (terminate "flutter run" but leave application running).',
  );

  late final CommandHelpOption g = _makeOption(
    'g',
    'Run source code generators.'
  );

  late final CommandHelpOption hWithDetails = _makeOption(
    'h',
    'Repeat this help message.',
  );

  late final CommandHelpOption hWithoutDetails = _makeOption(
    'h',
    'List all available interactive commands.',
  );

  late final CommandHelpOption i = _makeOption(
    'i',
    'Toggle widget inspector.',
    'WidgetsApp.showWidgetInspectorOverride',
  );

  late final CommandHelpOption j = _makeOption(
    'j',
    'Dump frame raster stats for the current frame. (Unsupported for web)',
  );

  late final CommandHelpOption k = _makeOption(
    'k',
    'Toggle CanvasKit rendering.',
  );

  late final CommandHelpOption o = _makeOption(
    'o',
    'Simulate different operating systems.',
    'defaultTargetPlatform',
  );

  late final CommandHelpOption p = _makeOption(
    'p',
    'Toggle the display of construction lines.',
    'debugPaintSizeEnabled',
  );

  late final CommandHelpOption q = _makeOption(
    'q',
    'Quit (terminate the application on the device).',
  );

  late final CommandHelpOption r = _makeOption(
    'r',
    'Hot reload. $fire$fire$fire',
  );

  late final CommandHelpOption s = _makeOption(
    's',
    'Save a screenshot to flutter.png.',
  );

  late final CommandHelpOption t = _makeOption(
    't',
    'Dump rendering tree to the console.',
    'debugDumpRenderTree',
  );

  late final CommandHelpOption v = _makeOption(
    'v',
    'Open Flutter DevTools.',
  );

  late final CommandHelpOption w = _makeOption(
    'w',
    'Dump widget hierarchy to the console.',
    'debugDumpApp',
  );

  // When updating the list above, see the notes above the list regarding order
  // and tests.

  CommandHelpOption _makeOption(String key, String description, [
    String inParenthesis = '',
  ]) {
    return CommandHelpOption(
      key,
      description,
      inParenthesis: inParenthesis,
      logger: _logger,
      terminal: _terminal,
      platform: _platform,
      outputPreferences: _outputPreferences,
    );
  }
}

/// Encapsulates printing help text for a single option.
class CommandHelpOption {
  CommandHelpOption(
    this.key,
    this.description, {
    this.inParenthesis = '',
    required Logger logger,
    required Terminal terminal,
    required Platform platform,
    required OutputPreferences outputPreferences,
  }) : _logger = logger,
       _terminal = terminal,
       _platform = platform,
       _outputPreferences = outputPreferences;

  final Logger _logger;

  final Terminal _terminal;

  final Platform _platform;

  final OutputPreferences _outputPreferences;

  /// The key associated with this command.
  final String key;
  /// A description of what this command does.
  final String description;
  /// Text shown in parenthesis to give the context.
  final String inParenthesis;

  bool get _hasTextInParenthesis => inParenthesis.isNotEmpty;

  int get _rawMessageLength => key.length + description.length;

  @override
  String toString() {
    final StringBuffer message = StringBuffer();
    message.writeAll(<String>[_terminal.bolden(key), description], ' ');
    if (!_hasTextInParenthesis) {
      return message.toString();
    }

    bool wrap = false;
    final int maxWidth = math.max(
      _outputPreferences.wrapColumn,
      maxLineWidth,
    );
    final int adjustedMessageLength = _platform.stdoutSupportsAnsi
      ? _rawMessageLength + 1
      : message.length;
    int width = maxWidth - adjustedMessageLength;
    final String parentheticalText = '($inParenthesis)';
    if (width < parentheticalText.length) {
      width = maxWidth;
      wrap = true;
    }
    if (wrap) {
      message.write('\n');
    }
    // pad according to the raw text
    message.write(''.padLeft(width - parentheticalText.length));
    message.write(_terminal.color(parentheticalText, TerminalColor.grey));

    // Terminals seem to require this because we have both bolded and colored
    // a line. Otherwise the next line comes out bold until a reset bold.
    if (_terminal.supportsColor) {
      message.write(AnsiTerminal.resetBold);
    }

    return message.toString();
  }

  void print() {
    _logger.printStatus(toString());
  }
}
