// Copyright (c) 2015, 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.

// @dart = 2.7

/// Visualization of source mappings generated and tested in
/// 'source_mapping_test.dart'.

library source_mapping.test.viewer;

import 'dart:async';
import 'package:_fe_analyzer_shared/src/util/filenames.dart';
import 'package:compiler/src/util/util.dart';
import 'source_mapping_tester.dart';
import '../helpers/sourcemap_helper.dart';
import '../helpers/sourcemap_html_helper.dart';
import '../helpers/sourcemap_html_templates.dart';

const String DEFAULT_OUTPUT_PATH = 'out.js.map.html';

main(List<String> arguments) async {
  bool measure = false;
  bool missingOnly = false;
  String outputPath = DEFAULT_OUTPUT_PATH;
  Set<String> configurations = new Set<String>();
  Map<String, Uri> tests = <String, Uri>{};
  for (String argument in arguments) {
    if (argument.startsWith('-')) {
      if (argument == '-m') {
        // Measure instead of reporting the number of missing code points.
        measure = true;
      } else if (argument.startsWith('--out=')) {
        // Generate visualization for the first configuration.
        outputPath = argument.substring('--out='.length);
      } else if (argument.startsWith('-o')) {
        // Generate visualization for the first configuration.
        outputPath = argument.substring('-o'.length);
      } else if (argument == '--missing') {
        missingOnly = true;
      } else if (argument == '--file' || argument == '--exclude') {
        // Handled by [parseArguments].
      } else {
        print("Unknown option '$argument'.");
        return;
      }
    }
  }

  if (!parseArguments(arguments, configurations, tests, measure: measure)) {
    return;
  }

  OutputConfigurations outputConfigurations =
      new OutputConfigurations(configurations, tests.keys);
  bool generateMultiConfigs = false;
  if (outputPath != null) {
    if (configurations.length > 1 || tests.length > 1) {
      for (String config in configurations) {
        for (String file in tests.keys) {
          String path = '$outputPath.$config.$file';
          Uri uri = Uri.base.resolve(nativeToUriPath(path));
          outputConfigurations.registerPathUri(config, file, path, uri);
        }
      }
      generateMultiConfigs = true;
    } else {
      outputConfigurations.registerPathUri(
          configurations.first,
          tests.keys.first,
          outputPath,
          Uri.base.resolve(nativeToUriPath(outputPath)));
    }
  }

  List<Measurement> measurements = <Measurement>[];
  for (String config in configurations) {
    for (String file in tests.keys) {
      List<String> options = TEST_CONFIGURATIONS[config];
      Measurement measurement = await runTest(
          config, file, tests[file], options,
          outputUri: outputConfigurations.getUri(config, file),
          verbose: !measure,
          missingOnly: missingOnly);
      measurements.add(measurement);
    }
  }
  for (Measurement measurement in measurements) {
    print(measurement);
  }
  if (generateMultiConfigs) {
    outputMultiConfigs(Uri.base.resolve(outputPath), outputConfigurations);
  }
}

class OutputConfigurations implements Configurations {
  @override
  final Iterable<String> configs;
  @override
  final Iterable<String> files;
  final Map<Pair, String> pathMap = {};
  final Map<Pair, Uri> uriMap = {};

  OutputConfigurations(this.configs, this.files);

  void registerPathUri(String config, String file, String path, Uri uri) {
    Pair key = new Pair(config, file);
    pathMap[key] = path;
    uriMap[key] = uri;
  }

  Uri getUri(String config, String file) {
    Pair key = new Pair(config, file);
    return uriMap[key];
  }

  @override
  String getPath(String config, String file) {
    Pair key = new Pair(config, file);
    return pathMap[key];
  }
}

Future<Measurement> runTest(
    String config, String filename, Uri uri, List<String> options,
    {Uri outputUri, bool verbose, bool missingOnly: false}) async {
  TestResult result =
      await runTests(config, filename, uri, options, verbose: verbose);
  if (outputUri != null) {
    if (result.missingCodePointsMap.isNotEmpty) {
      result.printMissingCodePoints();
    }
    if (result.multipleNodesMap.isNotEmpty) {
      result.printMultipleNodes();
    }
    if (result.multipleOffsetsMap.isNotEmpty) {
      result.printMultipleOffsets();
    }
    List<SourceMapInfo> infoList = result.userInfoList;
    if (missingOnly) {
      infoList = infoList
          .where((info) => result.missingCodePointsMap.containsKey(info))
          .toList();
    }
    createTraceSourceMapHtml(outputUri, result.processor, infoList);
  }
  return new Measurement(
      config,
      filename,
      result.missingCodePointsMap.values.fold(0, (s, i) => s + i.length),
      result.userInfoList.fold(0, (s, i) => s + i.codePoints.length));
}

class Measurement {
  final String config;
  final String filename;

  final int missing;
  final int count;

  Measurement(this.config, this.filename, this.missing, this.count);

  @override
  String toString() {
    double percentage = 100 * missing / count;
    return "Config '${config}', file: '${filename}': "
        "$missing of $count ($percentage%) missing";
  }
}
