// 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 '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 32 KiB.\n'
            'See the detailed explanation of `cold_bytes_filter` in '
            'https://fuchsia.googlesource.com/third_party/bloaty/+/refs/heads/fuchsia/src/bloaty.proto\n'
            '')
    ..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 `DumpNames`, one could write on the command line:

      # Use single-quotes to escape any special characters on the shell.
      fx codesize 'DumpNames(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

# Dumping all symbols with annotation in a binary, also hiding unknown symbols
fx codesize --file-regex appmgr 'DumpSymbol(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');
    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 Exception('--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)));
}

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 Exception('$constructor should end with `)`');
    }
    args = parseQueryConstructorArgs(
        constructor.substring(startOfArgs + 1, constructor.length - 1));
  }
  QueryFactory f;
  if (queries.containsKey(name)) {
    f = queries[name];
  } else {
    throw Exception('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';

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;

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