// 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

/// The queries library, containing size analytics modules for bloaty reports.
library queries;

import 'dart:core';
import 'dart:core' as core;
import 'dart:math' as math;

import '../common_util.dart';
import '../render/ast.dart';
import '../types.dart';
import 'binary_names.dart';
import 'categories/categories.dart';
import 'code_category.dart';
import 'crates.dart';
import 'source_lang.dart';
import 'symbols.dart';
import 'unique_symbol.dart';

/// A context object that allows queries to temporarily stow information
/// related to a particular compile unit, at the same time ensuring separation
/// of concerns.
///
/// This is accomplished by having query implementations define their
/// domain-specific mixins, which are combined together in this class.
///
/// The mixins themselves typically define lazily evaluated computations for
/// fields that are costly to compute. For example, many queries may make use of
/// the source langauge information of a compile unit, and that information is
/// defined and evaluated at most once, in `SourceLangCompileContextMixin`.
///
/// ## Lifecycle of a context
///
/// When running codesize on reports, the `CompileUnitContext` is created once
/// for each compile unit that appears in a bloaty report, and then re-used for
/// all queries. Afterwards, it is discarded and any information stored related
/// to this compile unit are lost.
class CompileUnitContext
    with
        SourceLangCompileContextMixin,
        CppCodingTableContextMixin,
        CppDomainObjectContextMixin,
        CppRuntimeContextMixin,
        CFidlContextMixin,
        GoFidlContextMixin,
        RustFidlContextMixin,
        DiagnosticsContextMixin,
        UntraceableContextMixin {
  CompileUnitContext(this.name);

  /// Name of the compile unit.
  final String name;
}

class ProgramContext with SourceLangContextMixin {
  ProgramContext(this.name, Report report) {
    initSourceLangContextMixin(report);
  }
  final String name;
}

/// The total `size` and `count` information of some entity being aggregated:
/// symbols, compile units, binaries, etc.
/// This is a simple data class that supports addition and comparison.
class Tally implements Comparable {
  Tally(this.size, this.count);

  /// How many bytes in total was occupied by the entity.
  int size;

  /// How many times was this entity observed.
  int count;

  /// Tear-off accessor for the `size` field.
  static int toSize(Tally t) => t.size;

  /// Tear-off accessor for `count` field.
  static int toCount(Tally t) => t.count;

  // Static methods could be used as a tear-off.
  // ignore: prefer_constructors_over_static_methods
  static Tally zero() => Tally(0, 0);

  @override
  int compareTo(dynamic other) {
    if (other is Tally) {
      final compSize = size.compareTo(other.size);
      if (compSize != 0) {
        return compSize;
      }
      return count.compareTo(other.count);
    } else {
      throw ArgumentError('$other cannot be compared');
    }
  }

  Tally operator +(Tally other) {
    return Tally(size + other.size, count + other.count);
  }

  @override
  bool operator ==(Object other) =>
      other is Tally && other.size == size && other.count == count;

  @override
  int get hashCode => size.hashCode ^ count.hashCode;

  Tally mergeWith(Tally other) {
    size += other.size;
    count += other.count;
    return this;
  }

  @override
  String toString() => '${formatSize(size)} ($size), count: $count';
}

/// Merge the contents of `b` into `a`.
Map<T, Tally> mergeMapInto<T>(Map<T, Tally> a, Map<T, Tally> b) {
  for (final entry in b.entries) {
    a.putIfAbsent(entry.key, Tally.zero).mergeWith(entry.value);
  }
  return a;
}

String printMapSorted<K>(Map<K, Tally> map) {
  final sortedBySize = map.keys.toList()
    ..sort((a, b) => map[a].size.compareTo(map[b].size));
  return sortedBySize.reversed.map((k) {
    return ' - $k: ${map[k]}';
  }).join('\n');
}

/// Sorts a map of binary names to their size, breaking ties by first sorting
/// by size, then sorting by name lexicographically.
List<MapEntry<String, Tally>> sortBinaries(Map<String, Tally> tallyByBinary) =>
    tallyByBinary.entries.toList()
      ..sort((a, b) => ((int sizeComp) => sizeComp != 0
          ? sizeComp
          : a.key.compareTo(b.key))(-a.value.size.compareTo(b.value.size)));

/// Utility class for calculating various statistics on a set of tallies.
class Statistics {
  Statistics(Iterable<Tally> elements) {
    if (elements.isEmpty) {
      sum = Tally.zero();
      count = 0;
      mean = 0;
      stdev = 0;
      min = 0;
      max = 0;
      return;
    }
    Iterable<int> sizes = elements.map(Tally.toSize);
    sum = elements.reduce((value, element) => value + element);
    count = sizes.length;
    mean = sum.size / count.toDouble();
    stdev = math.sqrt(sizes
            .map((e) => math.pow(e.toDouble() - mean, 2))
            .reduce((value, element) => value + element) /
        sizes.length.toDouble());
    min = sizes.reduce(math.min);
    max = sizes.reduce(math.max);
  }

  Tally sum;
  int count;
  double mean;
  double stdev;
  int min;
  int max;
}

/// A `Query` is some analysis that can run over all bloaty reports.
/// Queries may aggregate some statistics over the symbols in the binaries.
abstract class Query {
  /// Record the statistics from a `Report` created from a binary.
  void addReport(Report report);

  /// Combine the aggregate statistics with another instance of the same query.
  void mergeWith(Iterable<Query> others);

  /// Perform any expensive calculation and store the result in a `QueryReport`.
  /// Simple query implementations may inherit from both `Query` and
  /// `QueryReport` in the same class, in which case this method can simply
  /// return `this`.
  QueryReport distill();

  /// The name of this query.
  /// Every implementation must end with the suffix "Query", e.g. `FooBarQuery`.
  /// The name would then be `FooBar`, stripping the suffix.
  String get name => stripQuerySuffix(runtimeType.toString());

  /// Human-readable description of what this query measures.
  String getDescription();

  static String stripQuerySuffix(String typeName) =>
      maybeRemoveSuffix(typeName, 'Query');
}

/// Indicates this query should get the unfiltered bloaty report even when a
/// heatmap filter is specified.
///
/// When generating bloaty reports containing symbols and compile units, a
/// frame-based filter may be specified to only output symbols within a certain
/// byte range of the binary. This allows for example only analyzing symbols
/// that were not paged-in at runtime. However, certain queries may still wish
/// to receive the unfiltered set of symbols and compile units, because their
/// definition is independent from the access frequency e.g. [SourceLangQuery].
/// In that case, the query should implement this marker interface.
class IgnorePageInHeatmapFilter {}

/// A `QueryReport` contains the distilled results from running a query,
/// ready to be exported into some output format.
///
// We may add more methods in the future.
// ignore: one_member_abstracts
abstract class QueryReport {
  Iterable<AnyNode> export();
}

class Lazy<T, Context> {
  Lazy(this.func);
  T Function(Context self) func;
  T result;
  T call(dynamic self) {
    if (result != null) return result;
    return result = func(self);
  }
}

bool matchRegexEnsureAtMostOne(String name, List<RegExp> regex) {
  var matched = false;
  for (final regex in regex) {
    if (regex.hasMatch(name)) {
      if (matched) {
        throw Exception('Multiple matches on $name');
      }
      matched = true;
    }
  }

  return matched;
}

bool matchRegexAny(String name, List<RegExp> regex) {
  for (final regex in regex) {
    if (regex.hasMatch(name)) {
      return true;
    }
  }

  return false;
}

/// A `Renderer` is something that takes a list of queries, and prints their
/// results in a suitable format.
///
// TODO(fxbug.dev/57436): It is cleaner for renderers to take an iterable of
// `QueryReport`s, rather than `Query`s.
//
// We may add more methods in the future.
// ignore: one_member_abstracts
abstract class Renderer {
  void render(StringSink output, Iterable<Query> queries);
}

class BasicRenderer extends Renderer {
  @override
  void render(StringSink output, Iterable<Query> queries) {
    for (final query in queries) {
      output..writeln('${query.name}:')..writeln(query.toString());
    }
  }
}

/// `QueryFactory` encapsulates a query type and its description.
/// We may instantiate a query from its factory at run-time via reflection,
/// see `ReflectQuery.instantiate`.
class QueryFactory {
  const QueryFactory(this.type, this.description);
  final Type type;
  final String description;

  String get name => Query.stripQuerySuffix(type.toString());
}

/// List of all queries supported by codesize.
/// Add new queries to this list.
const List<QueryFactory> allQueries = [
  QueryFactory(CodeCategoryQuery, CodeCategoryQuery.description),
  QueryFactory(SourceLangQuery, SourceLangQuery.description),
  QueryFactory(BinaryNamesQuery, BinaryNamesQuery.description),
  QueryFactory(SymbolsQuery, SymbolsQuery.description),
  QueryFactory(CratesQuery, CratesQuery.description),
  QueryFactory(UniqueSymbolQuery, UniqueSymbolQuery.description),
];
