// Copyright (c) 2019, 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:io' show Directory, File, Platform;
import 'package:_fe_analyzer_shared/src/testing/id.dart' show ActualData, Id;
import 'package:_fe_analyzer_shared/src/testing/features.dart';
import 'package:_fe_analyzer_shared/src/testing/id_testing.dart';
import 'package:front_end/src/api_prototype/compiler_options.dart';
import 'package:front_end/src/api_prototype/language_version.dart' as lv;
import 'package:front_end/src/fasta/messages.dart' show FormattedMessage;
import 'package:front_end/src/fasta/builder/library_builder.dart';
import 'package:front_end/src/fasta/source/source_library_builder.dart';
import 'package:front_end/src/testing/id_testing_helper.dart'
    show
        CfeDataExtractor,
        DataComputer,
        InternalCompilerResult,
        TestConfig,
        TestResultData,
        createUriForFileName,
        onFailure,
        runTestFor;
import 'package:front_end/src/testing/id_testing_utils.dart';

import 'package:kernel/ast.dart' show Component, Library, Version;

Future<void> main(List<String> args) async {
  // Fix default/max major and minor version so we can test it.
  // This config sets it to 2.8.
  TestConfigWithLanguageVersion cfeConfig =
      new TestConfigWithLanguageVersion(cfeMarker, "cfe");

  Directory dataDir = new Directory.fromUri(Platform.script.resolve('data'));
  await runTests<Features>(dataDir,
      args: args,
      createUriForFileName: createUriForFileName,
      onFailure: onFailure,
      runTest: runTestFor(const LanguageVersioningDataComputer(), [cfeConfig]),
      skipList: [
        // Two language versions specified, the last one is ok and is used here.
        "package_default_version_is_wrong_2",
      ]);
}

class TestConfigWithLanguageVersion extends TestConfig {
  TestConfigWithLanguageVersion(String marker, String name)
      : super(marker, name);

  @override
  CompilerOptions customizeCompilerOptions(
      CompilerOptions options, TestData testData) {
    options.currentSdkVersion = "2.8";

    File f = new File.fromUri(testData.testFileUri.resolve("test.options"));
    if (f.existsSync()) {
      List<String> lines = f.readAsStringSync().split("\n");
      for (String line in lines) {
        const String packages = "--packages=";
        if (line == "" || line.startsWith("#")) continue;
        if (line.startsWith(packages)) {
          String value = line.substring(packages.length);
          options.packagesFileUri = testData.entryPoint.resolve(value);
          print("Setting package file uri to ${options.packagesFileUri}");
        } else {
          throw "Unsupported: $line";
        }
      }
    }
    return options;
  }
}

class Tags {
  static const String languageVersion = 'languageVersion';
  static const String packageUri = 'packageUri';
  static const String errors = 'errors';
}

class LanguageVersioningDataComputer extends DataComputer<Features> {
  const LanguageVersioningDataComputer();

  @override
  Future<void> inspectTestResultData(TestResultData testResultData) async {
    CompilerOptions options = testResultData.customData;
    Component component = testResultData.compilerResult.component!;
    for (Library library in component.libraries) {
      if (library.importUri.scheme == "dart") continue;
      Version lvFile =
          (await lv.languageVersionForUri(library.fileUri, options)).version;
      Version lvImportUri =
          (await lv.languageVersionForUri(library.importUri, options)).version;
      if ((lvFile != lvImportUri || lvFile != library.languageVersion)) {
        throw """
Language version disagreement:
Library: ${library.languageVersion}
Language version API (file URI): ${lvFile}
Language version API (import URI): ${lvImportUri}
""";
      }
    }
  }

  @override
  void computeLibraryData(TestResultData testResultData, Library library,
      Map<Id, ActualData<Features>> actualMap,
      {bool? verbose}) {
    new LanguageVersioningDataExtractor(
            testResultData.compilerResult, actualMap)
        .computeForLibrary(library);
  }

  @override
  bool get supportsErrors => true;

  @override
  Features computeErrorData(
      TestResultData testResultData, Id id, List<FormattedMessage> errors) {
    Features features = new Features();
    features[Tags.errors] = errors.map((m) => m.code.name).join(',');
    return features;
  }

  @override
  DataInterpreter<Features> get dataValidator =>
      const FeaturesDataInterpreter();
}

class LanguageVersioningDataExtractor extends CfeDataExtractor<Features> {
  LanguageVersioningDataExtractor(InternalCompilerResult compilerResult,
      Map<Id, ActualData<Features>> actualMap)
      : super(compilerResult, actualMap);

  @override
  Features computeLibraryValue(Id id, Library library) {
    Features features = new Features();
    features[Tags.languageVersion] =
        "${library.languageVersion.major}.${library.languageVersion.minor}";
    LibraryBuilder? libraryBuilder =
        lookupLibraryBuilder(compilerResult, library);
    if (libraryBuilder is SourceLibraryBuilder &&
        libraryBuilder.packageUriForTesting != null) {
      features[Tags.packageUri] =
          libraryBuilder.packageUriForTesting.toString();
    }
    return features;
  }
}
