// Copyright (c) 2020, 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';
import 'dart:collection';
import 'dart:convert';
import 'dart:io';

import 'package:args/args.dart';
import 'package:collection/collection.dart';
import 'package:path/path.dart' as p;

import '../tool/expected_output.dart';
import 'stats_lib.dart';

final _configs = List<Config>.unmodifiable([
  Config.commonMarkConfig,
  Config.gfmConfig,
]);

Future<void> main(List<String> args) async {
  final parser = ArgParser()
    ..addOption(
      'section',
      help: 'Restrict tests to one section, provided after the option.',
    )
    ..addFlag('raw', help: 'raw JSON format', negatable: false)
    ..addFlag(
      'update-files',
      help: 'Update stats files in $toolDir',
      negatable: false,
    )
    ..addFlag(
      'verbose',
      help: 'Print details for failures and errors.',
      negatable: false,
    )
    ..addFlag(
      'verbose-loose',
      help: 'Print details for "loose" matches.',
      negatable: false,
    )
    ..addOption('flavor', allowed: _configs.map((c) => c.prefix))
    ..addFlag('help', negatable: false);

  ArgResults options;

  try {
    options = parser.parse(args);
  } on FormatException catch (e) {
    stderr.writeln(e);
    print(parser.usage);
    exitCode = 64; // unix standard improper usage
    return;
  }

  if (options['help'] as bool) {
    print(parser.usage);
    return;
  }

  final specifiedSection = options['section'] as String?;
  final raw = options['raw'] as bool;
  final verbose = options['verbose'] as bool;
  final verboseLooseMatch = options['verbose-loose'] as bool;
  final updateFiles = options['update-files'] as bool;

  if (updateFiles && (raw || verbose || (specifiedSection != null))) {
    stderr.writeln('The `update-files` flag must be used by itself');
    print(parser.usage);
    exitCode = 64; // unix standard improper usage
    return;
  }

  var testPrefix = options['flavor'] as String?;
  if (!updateFiles) {
    testPrefix = _configs.first.prefix;
  }

  final testPrefixes = testPrefix == null
      ? _configs.map((c) => c.prefix)
      : <String>[testPrefix];

  for (final testPrefix in testPrefixes) {
    await _processConfig(
      testPrefix,
      raw,
      updateFiles,
      verbose,
      specifiedSection,
      verboseLooseMatch,
    );
  }
}

final _sectionNameReplace = RegExp(r'[ \)\(]+');

String _unitOutput(Iterable<DataCase> cases) => cases
    .map(
      (dataCase) =>
          '''
>>> ${dataCase.front_matter}
${dataCase.input}<<<
${dataCase.expectedOutput}''',
    )
    .join();

/// Set this to `true` and rerun `--update-files` to ease finding easy strict
/// fixes.
const _improveStrict = false;

Future<void> _processConfig(
  String testPrefix,
  bool raw,
  bool updateFiles,
  bool verbose,
  String? specifiedSection,
  bool verboseLooseMatch,
) async {
  final config = _configs.singleWhere((c) => c.prefix == testPrefix);

  final sections = loadCommonMarkSections(testPrefix);

  final scores = SplayTreeMap<String, SplayTreeMap<int, CompareLevel>>(
    compareAsciiLowerCaseNatural,
  );

  for (final entry in sections.entries) {
    if (specifiedSection != null && entry.key != specifiedSection) {
      continue;
    }

    final units = <DataCase>[];

    for (final e in entry.value) {
      final result = compareResult(
        config,
        e,
        verboseFail: verbose,
        verboseLooseMatch: verboseLooseMatch,
        extensions: e.extensions,
      );

      units.add(
        DataCase(
          front_matter: result.testCase.toString(),
          input: result.testCase.markdown,
          expectedOutput:
              (_improveStrict && result.compareLevel == CompareLevel.loose)
              ? result.testCase.html
              : result.result!,
        ),
      );

      final nestedMap = scores.putIfAbsent(
        entry.key,
        SplayTreeMap<int, CompareLevel>.new,
      );
      nestedMap[e.example] = result.compareLevel;
    }

    if (updateFiles && units.isNotEmpty) {
      var fileName = entry.key.toLowerCase().replaceAll(
        _sectionNameReplace,
        '_',
      );
      while (fileName.endsWith('_')) {
        fileName = fileName.substring(0, fileName.length - 1);
      }
      fileName = '$fileName.unit';
      File(p.join('test', testPrefix, fileName))
        ..createSync(recursive: true)
        ..writeAsStringSync(_unitOutput(units));
    }
  }

  if (raw || updateFiles) {
    await _printRaw(testPrefix, scores, updateFiles);
  }

  if (!raw || updateFiles) {
    await _printFriendly(testPrefix, scores, updateFiles);
  }
}

Object? _convert(Object? obj) {
  if (obj is CompareLevel) {
    return obj.name;
  }
  if (obj is Map) {
    return obj.map<String, Object?>(
      (key, value) => MapEntry(key.toString(), value),
    );
  }
  return obj;
}

Future<void> _printRaw(
  String testPrefix,
  Map<String, Map<int, CompareLevel>> scores,
  bool updateFiles,
) async {
  IOSink sink;
  if (updateFiles) {
    final file = getStatsFile(testPrefix);
    print('Updating ${file.path}');
    sink = file.openWrite();
  } else {
    sink = stdout;
  }

  const encoder = JsonEncoder.withIndent(' ', _convert);
  try {
    sink.writeln(encoder.convert(scores));
    // ignore: avoid_catching_errors
  } on JsonUnsupportedObjectError catch (e) {
    stderr.writeln(e.cause);
    stderr.writeln(e.unsupportedObject.runtimeType);
    rethrow;
  }

  await sink.flush();
  await sink.close();
}

String _pct(int value, int total, String section) =>
    '${value.toString().padLeft(4)} '
    'of ${total.toString().padLeft(4)} '
    '– ${(100 * value / total).toStringAsFixed(1).padLeft(5)}%  $section';

Future<void> _printFriendly(
  String testPrefix,
  SplayTreeMap<String, SplayTreeMap<int, CompareLevel>> scores,
  bool updateFiles,
) async {
  var totalValid = 0;
  var totalStrict = 0;
  var totalExamples = 0;

  IOSink sink;
  if (updateFiles) {
    final path = p.join(toolDir, '${testPrefix}_stats.txt');
    print('Updating $path');
    final file = File(path);
    sink = file.openWrite();
  } else {
    sink = stdout;
  }

  scores.forEach((section, Map<int, CompareLevel> map) {
    final total = map.values.length;
    totalExamples += total;

    final sectionStrictCount = map.values
        .where((val) => val == CompareLevel.strict)
        .length;

    final sectionLooseCount = map.values
        .where((val) => val == CompareLevel.loose)
        .length;

    final sectionValidCount = sectionStrictCount + sectionLooseCount;

    totalStrict += sectionStrictCount;
    totalValid += sectionValidCount;

    sink.writeln(_pct(sectionValidCount, total, section));
  });

  sink.writeln(_pct(totalValid, totalExamples, 'TOTAL'));
  sink.writeln(_pct(totalStrict, totalValid, 'TOTAL Strict'));

  await sink.flush();
  await sink.close();
}
