// Copyright 2020 The Fuchsia Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

// @dart = 2.8

import 'dart:io';

import 'package:args/args.dart';

import 'common_util.dart';
import 'crash_handling.dart';
import 'io.dart';
import 'queries/index.dart' as queries;
import 'queries/index.dart';
import 'queries/source_lang.dart';
import 'reflect.dart';
import 'run_queries.dart';

/// Parse command line arguments
ParsedArgs parseArgs(List<String> args) {
  final parser = ArgParser(allowTrailingOptions: true)
    ..addSeparator('Core options:\n')
    ..addFlag('help', help: 'Give this help.', negatable: false)
    // The `--[no-]cache` parameter is a tri-state:
    //
    // fx codesize --cache => Always use cached bloaty reports
    // fx codesize --no-cache => Never use cached bloaty reports
    // fx codesize => If the system image is newer than the report index,
    //                re-run bloaty. Otherwise use cache. This is the default.
    ..addFlag(cache,
        help:
            'Use the cached version of the list of bloaty reports if available',
        defaultsTo: false,
        negatable: false)
    ..addFlag(noCache,
        help: 'Do not use the cache of the list of bloaty reports',
        defaultsTo: false,
        negatable: false)
    ..addOption(buildDir,
        help: 'The build output directory (e.g. out/default).\n'
            'If absent, defaults to the current output directory '
            '(FUCHSIA_BUILD_DIR)',
        defaultsTo: Platform.environment['FUCHSIA_BUILD_DIR'])
    ..addOption(concurrency,
        help: 'The number of worker threads.\n'
            'If absent, defaults to a reasonable number based on the CPU cores',
        abbr: 'j')
    ..addSeparator('Filtering by name and language:\n')
    ..addOption(fileRegex,
        help: 'Optionally specify a regex to only incorporate statistics\n'
            'from binaries whose name match the regex.',
        abbr: 'f',
        defaultsTo: '.*')
    ..addOption(onlyLang,
        help: 'Only incorporate statistics from binaries '
            'of this programming language.',
        abbr: 'l',
        allowed: SourceLang.values.map((e) => e.name))
    ..addSeparator('Filtering by run-time page-in frequency:\n')
    ..addOption(heatmap,
        help: 'Optionally specify a blob access heatmap to only show symbols '
            'that have never been used at run-time.\n'
            'The heatmap is a CSV in [merkle],[[frame index]:[frequency],...] '
            'format, where each frame is 8 KiB by default.\n'
            'See the detailed explanation of `cold_bytes_filter` in '
            'https://fuchsia.googlesource.com/third_party/bloaty/+/refs/heads/fuchsia/src/bloaty.proto\n'
            '')
    ..addOption(heatmapFrameSize,
        help: 'When a heatmap is used, specify the size of a frame in bytes',
        defaultsTo: '8192')
    ..addSeparator('Output controls:\n')
    ..addOption(outputFile,
        help: 'The destination for writing stats. If absent, assumes stdout.',
        abbr: 'o')
    ..addOption(format,
        help: 'Format for the output.',
        allowed: OutputFormat.values.map((e) => e.name),
        allowedHelp: <OutputFormat, String>{
          OutputFormat.terminal:
              'Character-based rendering suitable for terminal',
          OutputFormat.basic: 'Plain-text minimal summary',
          OutputFormat.html: 'Rich HTML formatting',
          OutputFormat.tsv: 'Tab-separated values table',
        }.map((key, value) => MapEntry<String, String>(key.name, value)),
        defaultsTo: OutputFormat.terminal.name);

  final queryHelp = StringBuffer();
  for (final query in queries.allQueries) {
    queryHelp
      ..write('      ${query.name.padRight(24)}')
      ..writeln(query.description);
    if (ReflectQuery.hasCustomArguments(query)) {
      for (final constructor in ReflectQuery.describeQueryConstructors(query)) {
        queryHelp.writeln('      $constructor  <-  optional arguments\n');
      }
    } else {
      queryHelp.writeln();
    }
  }
  queryHelp.write(r'''
The syntax for specifying optional arguments to queries is similar to Dart
function calls and passing arguments by name, with the exception that strings
and string-like argument values are un-quoted. For instance, to specify the
`sortBySize` argument to `BinaryNames`, one could write on the command line:

      # Use single-quotes to escape any special characters on the shell.
      fx codesize 'BinaryNames(sortBySize: true)'

''');

  const defaultQueryConstructors = <String>['CodeCategory', 'SourceLang'];
  final argResults = parser.parse(args);
  if (argResults['help']) {
    final examples =
        // ignore: prefer_interpolation_to_compose_strings
        ('# By default, codesize runs the ${defaultQueryConstructors.join(" and ")} signal\n'
                r'''
fx codesize

# Can run on a subset of binaries, filtered by a regex
# For instance, "(?!\[prebuilt\])" will skip all the prebuilts, which might be helpful
# if changing SDK libraries that won't lead to their update
fx codesize --file-regex '^(?!\[prebuilt\])'

# Another example, only looking at the ELF binaries in Zircon Boot Images
fx codesize --file-regex '^\[zbi: '

# Another example, only running on appmgr...
fx codesize --file-regex appmgr CodeCategory

# Listing all symbols with annotation in a binary, grouped by compile units, also hiding unknown symbols
fx codesize --file-regex appmgr 'Symbols(hideUnknown: true)'

# Look through all C++ symbols alongside their containing programs, sorted by aggregate size
fx codesize --only-lang=cpp 'UniqueSymbol(showCompileUnit: true, showProgram: true, hideUnknown: false)' | less
''')
            .split('\n')
            .map((s) => '      $s')
            .join('\n');
    print('Usage: fx codesize [OPTION]... [QUERY]...\n\n'
        'Looks at all the ELF binaries in the fvm/zbi images in the out dir,\n'
        'computes various bary size queries specified in [QUERY]...\n'
        'If [QUERY] is absent, defaults to CodeCategory and SourceLang\n\n'
        '${parser.usage}\n\n'
        'Supported queries:\n\n$queryHelp'
        'Some examples:\n\n$examples\n\n'
        '''Exit codes:

    0: Success
    1: General unhandled exception (indicates a bug in codesize)
    2: Known errors/unsatisfied preconditions (not a bug in codesize)
''');
    return null;
  }

  // Default query to `SourceLang` if none was set.
  List<String> queryConstructors = argResults.rest ?? [];
  if (queryConstructors.isEmpty) queryConstructors = defaultQueryConstructors;

  final List<QueryThunk> selectedQueries = queryConstructors
      .map((String s) => parseQueryConstructor(queriesByName, s))
      .toList(growable: false);

  // We close the sink in the main function.
  // ignore: close_sinks
  IOSink output = Io.get().out;
  if (argResults[outputFile] != null) {
    output = File(argResults[outputFile]).openWrite();
  }

  CachingBehavior cachingBehavior;
  if (argResults[cache] && argResults[noCache])
    throw KnownFailure('--cache and --no-cache cannot both be specified');
  if (argResults[cache])
    cachingBehavior = CachingBehavior.alwaysUseCache;
  else if (argResults[noCache])
    cachingBehavior = CachingBehavior.neverUseCache;
  else
    cachingBehavior = CachingBehavior.useIfUpToDate;

  return ParsedArgs(
      buildDir: argResults[buildDir],
      fileRegex: RegExp(argResults[fileRegex]),
      output: output,
      cachingBehavior: cachingBehavior,
      // ignore: avoid_as
      concurrency: flatMap(argResults[concurrency] as String, int.parse),
      selectedQueries: List<QueryThunk>.from(selectedQueries),
      format: toOutputFormat(argResults[format]),
      // ignore: avoid_as
      onlyLang: flatMap(argResults[onlyLang] as String, toSourceLang),
      // ignore: avoid_as
      heatmap: flatMap(argResults[heatmap] as String, (x) => File(x)),
      heatmapFrameSize: int.parse(argResults[heatmapFrameSize]));
}

enum OutputFormat { terminal, basic, html, tsv }

extension on OutputFormat {
  String get name => removePrefix(toString(), 'OutputFormat.');
}

OutputFormat toOutputFormat(String name) {
  for (final format in OutputFormat.values) {
    if (format.name == name) return format;
  }
  return null;
}

extension on SourceLang {
  String get name => removePrefix(toString(), 'SourceLang.');
}

SourceLang toSourceLang(String name) {
  for (final lang in SourceLang.values) {
    if (lang.name == name) return lang;
  }
  return null;
}

enum CachingBehavior { alwaysUseCache, neverUseCache, useIfUpToDate }

final queriesByName = Map.fromEntries(
    allQueries.map((s) => MapEntry<String, QueryFactory>(s.name, s)));

/// Turns
///
/// ```
/// "foo: 5, bar: abc"
/// ```
///
/// into
///
/// ```
/// {'foo': '5', 'bar': 'abc'}
/// ```
Map<String, String> parseQueryConstructorArgs(String args) =>
    Map.fromEntries(args.split(',').map((s) {
      final tokens = s.trim().split(':');
      assert(tokens.length == 2);
      final name = tokens[0].trim();
      final value = tokens[1].trim();
      return MapEntry<String, String>(name, value);
    }));

/// Turns a string of the form `MyQuery(foo: 5, bar: 'abc')`
/// into a zero-arg function which when evaluated, produces
/// a new instance of `MyQuery` with those arguments.
QueryThunk parseQueryConstructor(
    Map<String, QueryFactory> queries, String _constructor) {
  final constructor = _constructor.trim();
  final startOfArgs = constructor.indexOf('(');
  String name;
  Map<String, String> args = {};
  if (startOfArgs == -1) {
    name = constructor;
  } else {
    name = constructor.substring(0, startOfArgs);
    if (constructor[constructor.length - 1] != ')') {
      throw KnownFailure('$constructor should end with `)`');
    }
    args = parseQueryConstructorArgs(
        constructor.substring(startOfArgs + 1, constructor.length - 1));
  }
  QueryFactory f;
  if (queries.containsKey(name)) {
    f = queries[name];
  } else {
    if (name == 'DumpNames') {
      throw KnownFailure('DumpNames have been renamed to BinaryNames');
    }
    throw KnownFailure('Query `$name` not found. Pick from: ${queries.keys}');
  }
  return () => ReflectQuery.instantiate(f, args);
}

// Defining command line arguments ---------------------------------------------

const cache = 'cache';
const noCache = 'no-cache';
const buildDir = 'build-dir';
const fileRegex = 'file-regex';
const onlyLang = 'only-lang';
const outputFile = 'output';
const format = 'format';
const concurrency = 'concurrency';
const heatmap = 'heatmap';
const heatmapFrameSize = 'heatmap-frame-size';

class ParsedArgs {
  final CachingBehavior cachingBehavior;
  final String buildDir;
  final RegExp fileRegex;
  final SourceLang onlyLang;
  final IOSink output;
  final OutputFormat format;
  final int concurrency;
  final List<QueryThunk> selectedQueries;
  final File heatmap;
  final int heatmapFrameSize;

  ParsedArgs(
      {this.cachingBehavior,
      this.buildDir,
      this.fileRegex,
      this.onlyLang,
      this.output,
      this.format,
      this.concurrency,
      this.selectedQueries,
      this.heatmap,
      this.heatmapFrameSize});
}
