// 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:core';
import 'package:collection/collection.dart';

import '../common_util.dart';
import '../render/ast.dart';
import '../types.dart';
import 'categories/categories.dart';
import 'index.dart';

/// A code category is a pattern detector that looks for a particular set of
/// interesting symbols e.g. FIDL C++ coding tables. There are many code
/// categories defined, and a symbol must fall into exactly one category,
/// with `uncategorized` being a special fallback category.
abstract class CodeCategory {
  const CodeCategory();

  /// Returns if the (symbol, compileUnit) combination matches this category.
  /// Additionally, the matching is performed in two phases, `match` and
  /// `rematch`. During this `match` phase, implementations may additionally
  /// build up contextual information that will help make the second `rematch`
  /// run more accurate. For example, `HlcppDomainObjectCategory` would infer
  /// the (potentially out-of-tree) FIDL library name if applicable, and use
  /// that to match other more ambiguous HLCPP FIDL symbols.
  bool match(
      String symbol, CompileUnitContext compileUnit, ProgramContext program);

  /// Performs a more extensive match using information gathered from `match`.
  /// See `CodeCategory.match`.
  bool rematch(
      String symbol, CompileUnitContext compileUnit, ProgramContext program) {
    return false;
  }

  /// A human-readable description of what kinds of codes are covered under
  /// this category.
  String get description;

  String get name => maybeRemoveSuffix(runtimeType.toString(), 'Category');

  @override
  String toString() => name;
}

/// The signature of `CodeCategory.match` and `CodeCategory.rematch`.
typedef Matcher = bool Function(String, CompileUnitContext, ProgramContext);

/// Marker interface that all FIDL categories will implement.
class SomeFidlCategory {}

class Uncategorized extends CodeCategory {
  const Uncategorized();

  @override
  String get description => 'Symbols with a potentially indicative name, '
      'but otherwise did not fall under any of the defined code categories';

  @override
  bool match(
      String symbol, CompileUnitContext compileUnit, ProgramContext program) {
    return false;
  }
}

const uncategorized = Uncategorized();

class CodeCategoryQuery extends Query {
  static const String description =
      'Breaks down the symbols by categories and aggregates their size';

  @override
  String getDescription() => description;

  CodeCategoryQuery({this.numProgramsToShow = 5});

  final int numProgramsToShow;

  @override
  void addReport(Report report) {
    for (final compileUnit in report.compileUnits) {
      final symbolCategories = analyzeCompileUnit(compileUnit, report);

      for (final entry in symbolCategories.entries) {
        _addStats(entry.key.sizes, entry.value, report.context.name);
      }
    }
  }

  Map<Symbol, Set<CodeCategory>> analyzeCompileUnit(
      CompileUnit compileUnit, Report report) {
    final symbolCategories = <Symbol, Set<CodeCategory>>{};
    if (compileUnit.symbols == null) return symbolCategories;

    /// Match the symbol against the match functions from all the categories.
    Set<CodeCategory> matchCategories(Symbol symbol, CompileUnit compileUnit,
        Report report, Matcher Function(CodeCategory) toMatchFunction) {
      final matchedCategories = <CodeCategory>{};
      for (final category in _compatibleCategories) {
        if (toMatchFunction(category)(
            symbol.name, compileUnit.context, report.context)) {
          matchedCategories.add(category);
        }
      }

      // Special safeguard for exclusive code category rules: a symbol cannot
      // simultaneously belong to two exclusive code categories. This guards
      // against the categories themselves being too permissive.
      CodeCategory firstExclusiveCategory;
      for (final category in _exclusiveCategories) {
        if (toMatchFunction(category)(
            symbol.name, compileUnit.context, report.context)) {
          if (firstExclusiveCategory != null) {
            throw Exception('More than one exclusive category in '
                '${report.context.name}.\n'
                'Symbol: ${symbol.name}\n'
                'was both $firstExclusiveCategory and $category.\n'
                'Compile unit: ${compileUnit.name}\n');
          }
          firstExclusiveCategory = category;
          matchedCategories.add(category);
        }
      }
      return matchedCategories;
    }

    // First pass
    for (final symbol in compileUnit.symbols) {
      symbolCategories.putIfAbsent(symbol, () => <CodeCategory>{});
      symbolCategories[symbol].addAll(matchCategories(
          symbol, compileUnit, report, (category) => category.match));
    }

    // Second pass.
    // During the second pass, we only allow the category of a symbol to go from
    // "no categories" to some meaningful category, or stay in the same
    // category. Switching categories during `rematch` indicates potentially
    // buggy category matches, hence we noisily fail in that case.
    for (final symbol in compileUnit.symbols) {
      final matchedCategories = symbolCategories[symbol];
      final rematchedCategories = matchCategories(
          symbol, compileUnit, report, (category) => category.rematch);
      if (matchedCategories.isEmpty) {
        symbolCategories[symbol] = rematchedCategories;
      } else if (rematchedCategories.isNotEmpty &&
          !_compareCategories.equals(matchedCategories, rematchedCategories)) {
        throw Exception('${symbol.name} went from $matchedCategories '
            'to $rematchedCategories during rematch');
      }
      if (symbolCategories[symbol].isEmpty) {
        symbolCategories[symbol] = <CodeCategory>{uncategorized};
      }
    }

    return symbolCategories;
  }

  @override
  void mergeWith(Iterable<Query> others) {
    for (final other in others) {
      if (other is CodeCategoryQuery) {
        for (final entry in other._tallies.entries) {
          _tallies[entry.key] += entry.value;
        }
        for (final entry in other._statsByBinary.entries) {
          mergeMapInto(_statsByBinary[entry.key], entry.value);
        }
      } else {
        throw Exception('$other must be $runtimeType');
      }
    }
  }

  void _addStats(
      SizeInfo sizes, Set<CodeCategory> categories, String binaryName) {
    for (final category in categories) {
      _tallies[category]
        ..size += sizes.fileActual
        ..count += 1;
      _statsByBinary[category].putIfAbsent(binaryName, Tally.zero)
        ..size += sizes.fileActual
        ..count += 1;
    }
  }

  /// Code categories that are mutually exclusive with one another.
  /// A symbol may only match up to one of these categories.
  static const List<CodeCategory> _exclusiveCategories = [
    CppCodingTableCategory(),
    HlcppDomainObjectCategory(),
    LlcppDomainObjectCategory(),
    HlcppRuntimeCategory(),
    LlcppRuntimeCategory(),
    CFidlCategory(),
    GoFidlCategory(),
    RustFidlCategory(),
    UntraceableCategory(),
  ];

  /// Code categories that are compatible with one another, and with the
  /// exclusive categories. A symbol may match any number of these categories.
  static const List<CodeCategory> _compatibleCategories = [
    DiagnosticsCategory(),
  ];

  /// List of `CodeCategory`s checked by the query.
  static const List<CodeCategory> _allCategories = [
    ..._exclusiveCategories,
    ..._compatibleCategories
  ];

  final _tallies = Map<CodeCategory, Tally>.fromEntries(
      (_allCategories + [uncategorized]).map((s) => MapEntry(s, Tally.zero())));
  final _statsByBinary = Map<CodeCategory, Map<String, Tally>>.fromEntries(
      (_allCategories + [uncategorized]).map((s) => MapEntry(s, {})));

  static const _compareCategories = SetEquality<CodeCategory>();

  @override
  String toString() {
    final sortedBySize = _tallies.keys.toList()
      ..sort((a, b) => _tallies[a].size.compareTo(_tallies[b].size));
    return sortedBySize.reversed.map((k) => ' - $k: ${_tallies[k]}').join('\n');
  }

  @override
  QueryReport distill() => CodeCategoryReport(_tallies, _statsByBinary,
      numProgramsToShow: numProgramsToShow);
}

class CodeCategoryReport implements QueryReport {
  CodeCategoryReport(this._tallies, this._statsByBinary,
      {this.numProgramsToShow}) {
    _sortedBySize = _tallies.keys.toList()
      ..sort((a, b) => -_tallies[a].size.compareTo(_tallies[b].size));
    for (final k in _sortedBySize) {
      _statistics[k] = Statistics(_statsByBinary[k].values);
      _sortedBinariesPerCategory[k] = sortBinaries(_statsByBinary[k]);
    }

    bool entryIsCppFamilyFidl<T>(MapEntry<CodeCategory, T> entry) =>
        entry.key is CppCodingTableCategory ||
        entry.key is LlcppRuntimeCategory ||
        entry.key is LlcppDomainObjectCategory ||
        entry.key is HlcppRuntimeCategory ||
        entry.key is HlcppDomainObjectCategory ||
        entry.key is CFidlCategory;

    final cppFidlStatsByBinary = _statsByBinary.entries
        .where(entryIsCppFamilyFidl)
        .map((e) => e.value)
        .fold<Map<String, Tally>>({}, mergeMapInto);
    _cppFidlStatistics =
        Statistics(cppFidlStatsByBinary.entries.map((e) => e.value));
    _cppFidlSortedBinaries = sortBinaries(cppFidlStatsByBinary);

    final allFidlStatsByBinary = _statsByBinary.entries
        .where((e) => e.key is SomeFidlCategory)
        .map((e) => e.value)
        .fold<Map<String, Tally>>({}, mergeMapInto);
    _allFidlStatistics =
        Statistics(allFidlStatsByBinary.entries.map((e) => e.value));
    _allFidlSortedBinaries = sortBinaries(allFidlStatsByBinary);
  }

  Node<StyledString> _printCategory(
      Statistics statistics, List<MapEntry<String, Tally>> sortedBinaries) {
    return Node(
        title: StyledString([
          Plain('Detected in ${statistics.count} binaries. '),
          Plain('avg: ${formatSize(statistics.mean.round())} '),
          Plain(
              '(${formatSize(statistics.min)} to ${formatSize(statistics.max)}), '),
          Plain('stdev: ${formatSize(statistics.stdev.round())}.'),
          if (sortedBinaries != null) Plain(' Top appearance:'),
        ]),
        children: sortedBinaries
            .take(numProgramsToShow)
            .map((e) => Node.plain(
                '${stripReportSuffix(e.key)} => ${formatSize(e.value.size)}'))
            .toList());
  }

  @override
  Iterable<AnyNode> export() {
    return <AnyNode>[
      // Print all the code categories first.
      for (final k in _sortedBySize)
        Node(
            title: SizeRecord(
                name: AddColor.green(Plain(k.toString())), tally: _tallies[k]),
            children: [
              Node.plain(k.description),
              if (k != uncategorized)
                _printCategory(_statistics[k], _sortedBinariesPerCategory[k])
            ]),
      // Print some higher-level synthesized information.
      Node(
          title: SizeRecord(
              name: AddColor.white(Plain('Combined C/C++ Family of FIDL code')),
              tally: _cppFidlStatistics.sum),
          children: [
            _printCategory(_cppFidlStatistics, _cppFidlSortedBinaries)
          ]),
      Node(
          title: SizeRecord(
              name: AddColor.white(Plain('Combined all FIDL code')),
              tally: _allFidlStatistics.sum),
          children: [
            _printCategory(_allFidlStatistics, _allFidlSortedBinaries)
          ]),
      Node(
          title: AddColor.white(Plain('Binaries without FIDL code:')),
          children: [
            Node(children: (() {
              final binariesWithFidl =
                  _allFidlSortedBinaries.map((e) => e.key).toSet();
              final binariesWithNonFidl = _sortedBinariesPerCategory.entries
                  .where((e) => e.key is! SomeFidlCategory)
                  .map((e) => e.value.map((e) => e.key).toSet())
                  .fold<Set<String>>({},
                      (previousValue, element) => previousValue.union(element));
              final difference = binariesWithNonFidl
                  .difference(binariesWithFidl)
                  .toList()
                    ..sort();
              return <AnyNode>[
                for (final bin in difference.take(numProgramsToShow))
                  Node.plain(bin),
                if (difference.length > numProgramsToShow)
                  Node.plain('... ${difference.length - 5} more element(s) ...')
              ];
            })())
          ]),
    ];
  }

  final int numProgramsToShow;

  final Map<CodeCategory, Tally> _tallies;
  final Map<CodeCategory, Map<String, Tally>> _statsByBinary;
  final _statistics = <CodeCategory, Statistics>{};
  final _sortedBinariesPerCategory =
      <CodeCategory, List<MapEntry<String, Tally>>>{};
  List<CodeCategory> _sortedBySize;
  Statistics _cppFidlStatistics;
  List<MapEntry<String, Tally>> _cppFidlSortedBinaries;
  Statistics _allFidlStatistics;
  List<MapEntry<String, Tally>> _allFidlSortedBinaries;
}

String stripReportSuffix(String name) {
  if (name.endsWith('.bloaty_report_pb'))
    return name.substring(0, name.length - 18);
  return name;
}
