// Copyright 2013 The Flutter Authors. 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:core' as core show RegExp;
import 'dart:core' hide RegExp;
import 'dart:io';

class RegExp implements core.RegExp {
  RegExp(
    String source, {
    bool multiLine = false,
    bool caseSensitive = true,
    bool unicode = false,
    bool dotAll = false,
    this.expectNoMatch = false,
  }) : _pattern = core.RegExp(source, multiLine: multiLine, caseSensitive: caseSensitive, unicode: unicode, dotAll: dotAll),
       source = _stripFrameNumber(StackTrace.current.toString().split('\n').skip(1).take(1).single) {
    _allPatterns.add(this);
  }

  static String _stripFrameNumber(String frame) {
    return frame.substring(frame.indexOf(' ')).trim();
  }

  final core.RegExp _pattern;
  final String source;

  static final List<RegExp> _allPatterns = <RegExp>[];

  final bool expectNoMatch;

  int _matchCount = 0;
  int get matchCount => _matchCount;

  int _testCount = 0;
  int get testCount => _testCount;

  final Stopwatch _stopwatch = Stopwatch();

  static void printDiagnostics() {
    final List<RegExp> patterns = _allPatterns.toList();
    stderr.writeln('Top ten patterns:');
    patterns.sort((RegExp a, RegExp b) => b._stopwatch.elapsed.compareTo(a._stopwatch.elapsed));
    for (final RegExp pattern in patterns.take(10)) {
      stderr.writeln('${pattern._stopwatch.elapsedMicroseconds.toString().padLeft(10)}μs tests -- /${pattern.pattern}/ (${pattern.testCount} tests, ${pattern.matchCount} matches, ${pattern.source})');
    }
    stderr.writeln();
    stderr.writeln('Unmatched patterns:');
    patterns.sort((RegExp a, RegExp b) => a.pattern.compareTo(b.pattern));
    for (final RegExp pattern in patterns) {
      if (pattern.matchCount == 0 && !pattern.expectNoMatch && pattern.testCount > 0) {
        stderr.writeln('/${pattern.pattern}/ (${pattern.testCount} tests, ${pattern.matchCount} matches, ${pattern.source})');
      }
    }
    stderr.writeln();
    stderr.writeln('Unexpectedly matched patterns:');
    for (final RegExp pattern in patterns) {
      if (pattern.matchCount > 0 && pattern.expectNoMatch) {
        stderr.writeln('/${pattern.pattern}/ (${pattern.testCount} tests, ${pattern.matchCount} matches, ${pattern.source})');
      }
    }
    stderr.writeln();
    stderr.writeln('Unused patterns:');
    for (final RegExp pattern in patterns) {
      if (pattern.testCount == 0) {
        stderr.writeln('/${pattern.pattern}/ (${pattern.testCount} tests, ${pattern.matchCount} matches, ${pattern.source})');
      }
    }
  }

  @override
  bool get isCaseSensitive => _pattern.isCaseSensitive;

  @override
  bool get isDotAll => _pattern.isDotAll;

  @override
  bool get isMultiLine => _pattern.isMultiLine;

  @override
  bool get isUnicode => _pattern.isUnicode;

  @override
  String get pattern => _pattern.pattern;

  @override
  Iterable<RegExpMatch> allMatches(String input, [int start = 0]) {
    _stopwatch.start();
    final List<RegExpMatch> result = _pattern.allMatches(input, start).toList();
    _stopwatch.stop();
    _testCount += 1;
    if (result.isNotEmpty) {
      _matchCount += 1;
    }
    return result;
  }

  @override
  RegExpMatch? firstMatch(String input) {
    _stopwatch.start();
    final RegExpMatch? result = _pattern.firstMatch(input);
    _stopwatch.stop();
    _testCount += 1;
    if (result != null) {
      _matchCount += 1;
    }
    return result;
  }

  @override
  bool hasMatch(String input) {
    _stopwatch.start();
    final bool result = _pattern.hasMatch(input);
    _stopwatch.stop();
    _stopwatch.stop();
    _testCount += 1;
    if (result) {
      _matchCount += 1;
    }
    return result;
  }

  @override
  Match? matchAsPrefix(String string, [int start = 0]) {
    _stopwatch.start();
    final Match? result = _pattern.matchAsPrefix(string, start);
    _stopwatch.stop();
    _testCount += 1;
    if (result != null) {
      _matchCount += 1;
    }
    return result;
  }

  @override
  String? stringMatch(String input) {
    _stopwatch.start();
    final String? result = _pattern.stringMatch(input);
    _stopwatch.stop();
    _testCount += 1;
    if (result != null) {
      _matchCount += 1;
    }
    return result;
  }

  @override
  String toString() => _pattern.toString();
}
