// Copyright (c) 2014, the Dart project authors.  Please see the AUTHORS file
// for details. 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:async' show EventSink;
import 'dart:collection';
import 'dart:convert';

import 'package:kernel/text/indentation.dart' show Indentation;

import '../../compiler.dart';
import '../common.dart';
import '../compiler.dart' show Compiler;
import '../util/util.dart';

// Helper methods for statistics.

/// Current stats collector. Use [enableStatsOutput] to enable recording of
/// stats.
Stats get stats {
  enableDebugMode();
  if (_stats == null) {
    _stats = const Stats();
  }
  return _stats;
}

Stats _stats;

/// Enable recording of stats. Use [Stats.dumpStats] to output the record stats.
///
/// Pass the [outputProvider] of [Compiler] to generate stats into a separate
/// file using [name] and [extension] for the filename. If omitted, stats are
/// printed on standard out.
///
/// If [xml] is `true`, stats output is formatted as XML with a default
/// extension of 'xml', otherwise the output is indented text with a default
/// extension of 'log'.
void enableStatsOutput(
    {CompilerOutputProvider outputProvider,
    bool xml: true,
    String name: 'stats',
    String extension,
    int examples: 10}) {
  if (_stats != null) {
    throw new StateError('Stats have already been initialized.');
  }
  enableDebugMode();

  StatsOutput output;
  if (outputProvider != null) {
    if (extension == null) {
      extension = xml ? 'xml' : 'log';
    }
    output = new SinkOutput(outputProvider(name, extension));
  } else {
    output = const DebugOutput();
  }
  StatsPrinter printer;
  if (xml) {
    printer = new XMLPrinter(output: output, examples: examples);
  } else {
    printer = new ConsolePrinter(output: output, examples: examples);
  }
  _stats = new ActiveStats(printer);
}

/// Interface for gathering and display of statistical information.
/// This class serves as the noop collector.
class Stats {
  const Stats();

  /// Registers [key], [value] pair in the map [id]. If [fromExisting] is
  /// non-null and [key] already exists, the value associated with [key] will
  /// be the return value of [fromExisting] when called with the existing value.
  ///
  /// The recorded information is not dumped automatically.
  void recordMap(id, key, value, {fromExisting(value)}) {}

  /// Returns the map [id] recorded with [recordMap].
  Map getMap(id) => const {};

  /// Registers [element] as an element of the list [id]. If provided, [data]
  /// provides additional data for [element].
  ///
  /// The recorded information is dumped automatically on call to [dumpStats].
  ///
  /// Example:
  ///   Calling [recordElement] like this:
  ///     recordElement('foo', 'a', data: 'first-a-data');
  ///     recordElement('foo', 'a', data: 'second-a-data');
  ///     recordElement('foo', 'b');
  ///     recordElement('bar', 'a', data: 'third-a-data');
  ///     recordElement('bar', 'c');
  ///   will result in a dump like this:
  ///     foo: 2
  ///      value=a data=second-a-data
  ///      b
  ///     bar: 2
  ///      value=a data=third-a-data
  ///      c
  ///
  void recordElement(id, element, {data}) {}

  /// Returns the list [id] recorded with [recordElement].
  Iterable getList(String id) => const [];

  /// Registers [value] as an occurrence of [id]. If passed, [example] provides
  /// an example data of the occurrence of [value].
  ///
  /// The recorded information is dumped automatically on call to [dumpStats].
  ///
  /// Example:
  ///   Calling [recordFrequency] like this:
  ///     recordFrequency('foo', 'a', 'first-a-data');
  ///     recordFrequency('foo', 'a', 'second-a-data');
  ///     recordFrequency('bar', 'b', 'first-b-data');
  ///     recordFrequency('foo', 'c');
  ///     recordFrequency('bar', 'b');
  ///   will result in a dump like this:
  ///     foo:
  ///      a: 2
  ///       first-a-data
  ///       second-a-data
  ///      c: 1
  ///     bar:
  ///      b: 2
  ///       first-b-data
  ///
  void recordFrequency(id, value, [example]) {}

  /// For each key/value pair in [map] the elements in the value are registered
  /// as examples of occurrences of the key in [id].
  void recordFrequencies(id, Map<dynamic, Iterable> map) {}

  /// Returns the examples given for the occurrence of [value] for [id].
  Iterable recordedFrequencies(id, value) => const [];

  /// Increases the counter [id] by 1. If provided, [example] is used as an
  /// example of the count and [data] provides additional information for
  /// [example].
  ///
  /// The recorded information is dumped automatically on call to [dumpStats].
  ///
  /// Example:
  ///   Calling [recordCounter] like this:
  ///     recordCounter('foo', 'a');
  ///     recordCounter('foo', 'a');
  ///     recordCounter('foo', 'b');
  ///     recordCounter('bar', 'c', 'first-c-data');
  ///     recordCounter('bar', 'c', 'second-c-data');
  ///     recordCounter('bar', 'd');
  ///     recordCounter('bar', 'd');
  ///     recordCounter('baz');
  ///     recordCounter('baz');
  ///   will result in a dump like this:
  ///     foo: 3
  ///      count=2 example=a
  ///      count=1 example=b
  ///     bar: 4
  ///      count=2 examples=2
  ///       c:
  ///        first-c-data
  ///        second-c-data
  ///       d
  ///     baz: 2
  ///
  void recordCounter(id, [example, data]) {}

  /// Records the current stack trace under the key [id]. Only every
  /// [sampleFrequency] call with the same id is recorded, and if omitted
  /// [stackTraceSampleFrequency] is used.
  void recordTrace(id, {int sampleFrequency}) {}

  /// The default sample frequency used for recording stack traces.
  int get stackTraceSampleFrequency => 0;

  /// Set the default sample frequency used for recording stack traces.
  void set stackTraceSampleFrequency(int value) {}

  /// Dumps the stats for the recorded frequencies, sets, and counters. If
  /// provided [beforeClose] is called before closing the dump output. This
  /// can be used to include correlations on the collected data through
  /// [dumpCorrelation].
  void dumpStats({void beforeClose()}) {}

  /// Prints the correlation between the elements of [a] and [b].
  ///
  /// Three sets are output using [idA] and [idB] as labels for the elements
  /// [a] and [b]:
  ///
  ///   'idA && idB' lists the elements both in [a] and [b],
  ///   '!idA && idB' lists the elements not in [a] but in [b], and
  ///   'idA && !idB' lists the elements in [a] but not in [b].
  ///
  /// If [dataA] and/or [dataB] are provided, additional information on the
  /// elements are looked up in [dataA] or [dataB] using [dataA] as the primary
  /// source.
  void dumpCorrelation(idA, Iterable a, idB, Iterable b,
      {Map dataA, Map dataB}) {}
}

/// Interface for printing output data.
///
/// This class serves as the disabled output.
class StatsOutput {
  const StatsOutput();

  /// Print [text] as on a separate line.
  void println(String text) {}
}

/// Output to the [debugPrint] method.
class DebugOutput implements StatsOutput {
  const DebugOutput();

  @override
  void println(String text) => debugPrint(text);
}

/// Output to an [EventSink]. Used to output to a file through the
/// [CompilerOutputProvider].
class SinkOutput implements StatsOutput {
  EventSink<String> sink;

  SinkOutput(this.sink);

  @override
  void println(String text) {
    sink.add(text);
    sink.add('\n');
  }
}

/// Interface for printing stats collected in [Stats].
abstract class StatsPrinter {
  /// The number of examples printer. If `null` all examples are printed.
  int get examples => 0;

  /// Start a group [id].
  void start(String id) {}

  /// Create a group [id] with content created by [createGroupContent].
  void group(String id, void createGroupContent()) {
    start(id);
    createGroupContent();
    end(id);
  }

  /// End a group [id].
  void end(String id) {}

  /// Start a stat entry for [id] with additional [data].
  void open(String id,
      [Map<String, dynamic> data = const <String, dynamic>{}]) {}

  /// Create a stat entry for [id] with additional [data] and content created by
  /// [createChildContent].
  void child(String id,
      [Map<String, dynamic> data = const <String, dynamic>{},
      void createChildContent()]) {
    open(id, data);
    if (createChildContent != null) createChildContent();
    close(id);
  }

  /// End a stat entry for [id].
  void close(String id) {}

  /// Starts a group of additional information.
  void beginExtra() {}

  /// Starts a group of additional information.
  void endExtra() {}
}

/// Abstract base class for [ConsolePrinter] and [XMLPrinter].
abstract class BasePrinter extends StatsPrinter with Indentation {
  @override
  final int examples;
  final StatsOutput output;

  BasePrinter({this.output: const DebugOutput(), this.examples: 10}) {
    indentationUnit = " ";
  }
}

/// [StatsPrinter] that displays stats in console lines.
class ConsolePrinter extends BasePrinter {
  int extraLevel = 0;

  ConsolePrinter({StatsOutput output: const DebugOutput(), int examples: 10})
      : super(output: output, examples: examples);

  @override
  void open(String id,
      [Map<String, dynamic> data = const <String, dynamic>{}]) {
    if (extraLevel > 0) return;

    StringBuffer sb = new StringBuffer();
    sb.write(indentation);
    String space = '';
    if (data['title'] != null) {
      sb.write('${data['title']}:');
      space = ' ';
      data.remove('title');
    } else if (data['name'] != null) {
      sb.write('${data['name']}');
      space = ' ';
      data.remove('name');
    }
    Iterable nonNullValues = data.values.where((v) => v != null);
    if (nonNullValues.length == 1) {
      sb.write('$space${nonNullValues.first}');
    } else {
      data.forEach((key, value) {
        sb.write('$space$key=$value');
        space = ' ';
      });
    }
    output.println(sb.toString());
    indentMore();
  }

  @override
  void close(String id) {
    if (extraLevel > 0) return;

    indentLess();
  }

  @override
  void beginExtra() {
    if (extraLevel == 0) output.println('$indentation...');
    extraLevel++;
  }

  @override
  void endExtra() {
    extraLevel--;
  }
}

/// [StatsPrinter] that displays stats in XML format.
class XMLPrinter extends BasePrinter {
  static const HtmlEscape escape = const HtmlEscape();
  bool opened = false;

  XMLPrinter({output: const DebugOutput(), int examples: 10})
      : super(output: output, examples: examples);

  @override
  void start(String id) {
    if (!opened) {
      output.println('<?xml version="1.0" encoding="UTF-8"?>');
      opened = true;
    }
    open(id);
  }

  @override
  void end(String id) {
    close(id);
  }

  @override
  void open(String id,
      [Map<String, dynamic> data = const <String, dynamic>{}]) {
    StringBuffer sb = new StringBuffer();
    sb.write(indentation);
    sb.write('<$id');
    data.forEach((key, value) {
      if (value != null) {
        sb.write(' $key="${escape.convert('$value')}"');
      }
    });
    sb.write('>');
    output.println(sb.toString());
    indentMore();
  }

  @override
  void close(String id) {
    indentLess();
    output.println('${indentation}</$id>');
  }

  @override
  void beginExtra() {
    open('extra');
  }

  @override
  void endExtra() {
    close('extra');
  }
}

/// A node in a stack trace tree used to store and organize stack traces by
/// common prefixes.
class _StackTraceNode implements Comparable<_StackTraceNode> {
  int count;
  List<StackTraceLine> commonPrefix;
  List<_StackTraceNode> subtraces;

  _StackTraceNode(this.commonPrefix, this.count, this.subtraces);

  _StackTraceNode.root() : this([], 0, []);

  _StackTraceNode.leaf(StackTraceLines stackTrace)
      : this(stackTrace.lines, 1, const []);

  _StackTraceNode.node(List<StackTraceLine> commonPrefix, _StackTraceNode first,
      _StackTraceNode second)
      : this(commonPrefix, first.count + second.count, [first, second]);

  void add(StackTraceLines stackTrace) {
    count++;
    if (!stackTrace.lines.isEmpty) {
      addSubtrace(stackTrace);
    }
  }

  void addSubtrace(StackTraceLines stackTrace) {
    List<StackTraceLine> lines = stackTrace.lines;
    for (_StackTraceNode subtrace in subtraces) {
      int commonPrefixLength =
          longestCommonPrefixLength(subtrace.commonPrefix, lines);
      if (commonPrefixLength > 0) {
        stackTrace = stackTrace.subtrace(commonPrefixLength);
        if (commonPrefixLength == subtrace.commonPrefix.length) {
          subtrace.add(stackTrace);
        } else {
          subtrace.commonPrefix =
              subtrace.commonPrefix.sublist(commonPrefixLength);
          subtraces.remove(subtrace);
          subtraces.add(new _StackTraceNode.node(
              lines.sublist(0, commonPrefixLength),
              subtrace,
              new _StackTraceNode.leaf(stackTrace)));
        }
        return;
      }
    }
    subtraces.add(new _StackTraceNode.leaf(stackTrace));
  }

  void dumpTraces(StatsPrinter printer) {
    printer.open('trace', {'count': count, 'line': commonPrefix.first});
    if (commonPrefix.length > 1) {
      for (StackTraceLine line in commonPrefix.skip(1)) {
        printer.child('trace', {'line': line});
      }
    }
    dumpSubtraces(printer);
    printer.close('trace');
  }

  void dumpSubtraces(StatsPrinter printer) {
    if (!subtraces.isEmpty) {
      subtraces.sort();
      for (_StackTraceNode step in subtraces) {
        step.dumpTraces(printer);
      }
    }
  }

  @override
  int compareTo(_StackTraceNode other) {
    // Sorts in decreasing count order.
    return other.count - count;
  }

  void printOn(StringBuffer sb, String indentation) {
    String countText = '$indentation$count  ';
    sb.write(countText);
    sb.write('\n');
    indentation = ''.padLeft(countText.length, ' ');
    if (commonPrefix != null) {
      int index = 0;
      for (StackTraceLine line in commonPrefix) {
        sb.write(indentation);
        if (index > 1) {
          sb.write('...\n');
          break;
        }
        sb.write(line);
        sb.write('\n');
        index++;
      }
    }
    subtraces.sort();
    for (_StackTraceNode subtrace in subtraces) {
      subtrace.printOn(sb, indentation);
    }
  }

  @override
  String toString() {
    StringBuffer sb = new StringBuffer();
    printOn(sb, '');
    return sb.toString();
  }
}

class _StackTraceTree extends _StackTraceNode {
  final id;
  int totalCount = 0;
  final int sampleFrequency;

  _StackTraceTree(this.id, this.sampleFrequency) : super.root();

  @override
  void dumpTraces(StatsPrinter printer) {
    printer.open('trace', {
      'id': id,
      'totalCount': totalCount,
      'sampleFrequency': sampleFrequency
    });
    dumpSubtraces(printer);
    printer.close('trace');
  }

  void sample() {
    if (totalCount++ % sampleFrequency == 0) {
      add(stackTrace(offset: 3));
    }
  }
}

/// Actual implementation of [Stats].
class ActiveStats implements Stats {
  final StatsPrinter printer;
  Map<dynamic, Map> maps = {};
  Map<dynamic, Map<dynamic, List>> frequencyMaps = {};
  Map<dynamic, Map> setsMap = {};
  Map<dynamic, Map<dynamic, List>> countersMap =
      <dynamic, Map<dynamic, List>>{};
  Map<dynamic, _StackTraceTree> traceMap = {};
  @override
  int stackTraceSampleFrequency = 1;

  ActiveStats(StatsPrinter this.printer);

  @override
  void recordMap(id, key, value, {fromExisting(value)}) {
    Map map = maps.putIfAbsent(id, () => {});
    if (fromExisting != null && map.containsKey(key)) {
      map[key] = fromExisting(map[key]);
    } else {
      map[key] = value;
    }
  }

  @override
  Map getMap(key) {
    return maps[key];
  }

  @override
  void recordFrequency(id, value, [example]) {
    Map<dynamic, List> map = frequencyMaps.putIfAbsent(id, () => {});
    map.putIfAbsent(value, () => []);
    map[value].add(example);
  }

  @override
  void recordFrequencies(id, Map<dynamic, Iterable> frequencyMap) {
    Map<dynamic, List> map = frequencyMaps.putIfAbsent(id, () => {});
    frequencyMap.forEach((value, examples) {
      map.putIfAbsent(value, () => []);
      map[value].addAll(examples);
    });
  }

  @override
  Iterable recordedFrequencies(id, value) {
    Map<dynamic, List> map = frequencyMaps[id];
    if (map == null) return const [];
    List list = map[value];
    if (list == null) return const [];
    return list;
  }

  @override
  void recordCounter(id, [reason, example]) {
    Map<dynamic, List> map = countersMap.putIfAbsent(id, () => {});
    map.putIfAbsent(reason, () => []).add(example);
  }

  @override
  void recordElement(key, element, {data}) {
    setsMap.putIfAbsent(key, () => new Map())[element] = data;
  }

  @override
  void recordTrace(key, {int sampleFrequency}) {
    if (sampleFrequency == null) {
      sampleFrequency = stackTraceSampleFrequency;
    }
    traceMap
        .putIfAbsent(key, () => new _StackTraceTree(key, sampleFrequency))
        .sample();
  }

  @override
  Iterable getList(String key) {
    Map map = setsMap[key];
    if (map == null) return const [];
    return map.keys;
  }

  @override
  void dumpStats({void beforeClose()}) {
    printer.start('stats');
    dumpFrequencies();
    dumpSets();
    dumpCounters();
    dumpTraces();
    if (beforeClose != null) {
      beforeClose();
    }
    printer.end('stats');
  }

  void dumpSets() {
    printer.group('sets', () {
      setsMap.forEach((k, set) {
        dumpIterable('examples', '$k', set.keys,
            limit: printer.examples, dataMap: set);
      });
    });
  }

  void dumpFrequencies() {
    printer.group('frequencies', () {
      frequencyMaps.forEach((key, Map<dynamic, List> map) {
        printer.child('frequency', {'title': '$key'}, () {
          dumpFrequency(map);
        });
      });
    });
  }

  void dumpFrequency(Map<dynamic, Iterable> map) {
    Map sortedMap = trySortMap(map);
    sortedMap.forEach((k, list) {
      dumpIterable('examples', '$k', list, limit: printer.examples);
    });
  }

  void dumpCounters() {
    printer.group('counters', () {
      countersMap.keys.forEach(dumpCounter);
    });
  }

  void dumpCounter(id) {
    Map<dynamic, List> map = countersMap[id];
    bool hasData(example) {
      if (map == null) return false;
      List list = map[example];
      if (list == null) return false;
      return list.any((data) => data != null);
    }

    int count = 0;
    Map<dynamic, int> frequencyMap = {};
    map.forEach((var category, List examples) {
      if (category != null) {
        frequencyMap.putIfAbsent(category, () => 0);
        frequencyMap[category] += examples.length;
      }
      count += examples.length;
    });
    Map<int, Set> result = sortMap(inverseMap(frequencyMap), (a, b) => b - a);
    int examplesLimit = null;
    if (printer.examples != null && result.length >= printer.examples) {
      examplesLimit = 0;
    }
    int counter = 0;
    bool hasMore = false;
    printer.open('counter', {'title': '$id', 'count': count});
    result.forEach((int count, Set examples) {
      if (counter == printer.examples) {
        printer.beginExtra();
        hasMore = true;
      }
      if (examples.length == 1 &&
          (examplesLimit == 0 || !hasData(examples.first))) {
        printer.child('examples', {'count': count, 'example': examples.first});
      } else {
        printer.child('examples', {'count': count, 'examples': examples.length},
            () {
          examples.forEach((example) {
            dumpIterable('examples', '$example', map[example],
                limit: examplesLimit, includeCount: false);
          });
        });
      }
      counter++;
    });
    if (hasMore) {
      printer.endExtra();
    }
    printer.close('counter');
  }

  void dumpTraces() {
    printer.group('traces', () {
      traceMap.keys.forEach(dumpTrace);
    });
  }

  void dumpTrace(key) {
    _StackTraceTree tree = traceMap[key];
    tree.dumpTraces(printer);
  }

  @override
  void dumpCorrelation(keyA, Iterable a, keyB, Iterable b,
      {Map dataA, Map dataB}) {
    printer.child('correlations', {'title': '$keyA vs $keyB'}, () {
      List aAndB = a.where((e) => e != null && b.contains(e)).toList();
      List aAndNotB = a.where((e) => e != null && !b.contains(e)).toList();
      List notAandB = b.where((e) => e != null && !a.contains(e)).toList();
      dumpIterable('correlation', '$keyA && $keyB', aAndB,
          dataMap: dataA, limit: printer.examples);
      dumpIterable('correlation', '$keyA && !$keyB', aAndNotB,
          dataMap: dataA, limit: printer.examples);
      dumpIterable('correlation', '!$keyA && $keyB', notAandB,
          dataMap: dataB, limit: printer.examples);
    });
  }

  void dumpIterable(String tag, String title, Iterable iterable,
      {int limit, Map dataMap, bool includeCount: true}) {
    if (limit == 0) return;

    Map<String, dynamic> childData = {};
    Iterable nonNullIterable = iterable.where((e) => e != null);
    if (nonNullIterable.isEmpty && !includeCount) {
      childData['name'] = title;
    } else {
      childData['title'] = title;
    }
    if (includeCount) {
      childData['count'] = iterable.length;
    }
    printer.child(tag, childData, () {
      bool hasMore = false;
      int counter = 0;
      nonNullIterable.forEach((element) {
        if (counter == limit) {
          printer.beginExtra();
          hasMore = true;
        }
        var data = dataMap != null ? dataMap[element] : null;
        if (data != null) {
          printer.child('example', {'value': element, 'data': data});
        } else {
          printer.child('example', {'value': element});
        }
        counter++;
      });
      if (hasMore) {
        printer.endExtra();
      }
    });
  }
}

/// Returns a map that is an inversion of [map], where the keys are the values
/// of [map] and the values are the set of keys in [map] that share values.
///
/// If [equals] and [hashCode] are provided, these are used to determine
/// equality among the values of [map].
///
/// If [isValidKey] is provided, this is used to determine with a value of [map]
/// is a potential key of the inversion map.
Map<V, Set<K>> inverseMap<K, V>(Map<K, V> map,
    {bool equals(V key1, V key2),
    int hashCode(V key),
    bool isValidKey(V potentialKey)}) {
  Map<V, Set<K>> result = new LinkedHashMap<V, Set<K>>(
      equals: equals, hashCode: hashCode, isValidKey: isValidKey);
  map.forEach((k, v) {
    if (isValidKey == null || isValidKey(v)) {
      result.putIfAbsent(v, () => new Set()).add(k);
    }
  });
  return result;
}

/// Return a new map heuristically sorted by the keys of [map]. If the first
/// key of [map] is [Comparable], the keys are sorted using [sortMap] under
/// the assumption that all keys are [Comparable].
/// Otherwise, the keys are sorted as string using their `toString`
/// representation.
Map<K, V> trySortMap<K, V>(Map<K, V> map) {
  Iterable<K> iterable = map.keys.where((K k) => k != null);
  if (iterable.isEmpty) return map;
  var key = iterable.first;
  if (key is Comparable<K>) {
    return sortMap(map);
  }
  return sortMap(map, (a, b) => '$a'.compareTo('$b'));
}

/// Returns a new map in which the keys of [map] are sorted using [compare].
/// If [compare] is null, the keys must be [Comparable].
Map<K, V> sortMap<K, V>(Map<K, V> map, [int compare(K a, K b)]) {
  List<K> keys = map.keys.toList();
  keys.sort(compare);
  Map<K, V> sortedMap = new Map<K, V>();
  keys.forEach((K k) => sortedMap[k] = map[k]);
  return sortedMap;
}
