// 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, Platform;

import 'package:_fe_analyzer_shared/src/testing/features.dart';
import 'package:_fe_analyzer_shared/src/testing/id.dart' show ActualData, Id;
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/experimental_flags.dart';
import 'package:front_end/src/fasta/builder/builder.dart';
import 'package:front_end/src/fasta/builder/member_builder.dart';
import 'package:front_end/src/fasta/source/source_class_builder.dart';
import 'package:front_end/src/fasta/source/source_constructor_builder.dart';
import 'package:front_end/src/fasta/source/source_factory_builder.dart';
import 'package:front_end/src/fasta/source/source_member_builder.dart';
import 'package:front_end/src/fasta/source/source_procedure_builder.dart';
import 'package:front_end/src/fasta/scope.dart';
import 'package:front_end/src/testing/id_testing_helper.dart';
import 'package:front_end/src/testing/id_testing_utils.dart';
import 'package:kernel/ast.dart';

Future<void> main(List<String> args) async {
  Directory dataDir = new Directory.fromUri(Platform.script.resolve('data'));
  await runTests<Features>(dataDir,
      args: args,
      createUriForFileName: createUriForFileName,
      onFailure: onFailure,
      runTest: runTestFor(const PatchingDataComputer(), [
        new TestConfigWithLanguageVersion(
            cfeMarker, 'cfe with libraries specification',
            librariesSpecificationUri: createUriForFileName('libraries.json'),
            experimentalFlags: {ExperimentalFlag.nonNullable: false},
            allowedExperimentalFlags: const AllowedExperimentalFlags()),
        new TestConfigWithLanguageVersion(cfeWithNnbdMarker,
            'cfe with libraries specification and non-nullable',
            librariesSpecificationUri: createUriForFileName('libraries.json'),
            experimentalFlags: {ExperimentalFlag.nonNullable: true},
            allowedExperimentalFlags: const AllowedExperimentalFlags())
      ]),
      skipMap: {
        cfeMarker: [
          'opt_in',
          'opt_in_patch',
          'opt_out',
          'opt_out_patch',
        ]
      });
}

class TestConfigWithLanguageVersion extends TestConfig {
  TestConfigWithLanguageVersion(String marker, String name,
      {Uri? librariesSpecificationUri,
      Map<ExperimentalFlag, bool> experimentalFlags = const {},
      AllowedExperimentalFlags? allowedExperimentalFlags})
      : super(marker, name,
            librariesSpecificationUri: librariesSpecificationUri,
            explicitExperimentalFlags: experimentalFlags,
            allowedExperimentalFlags: allowedExperimentalFlags);

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

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

  @override
  void computeMemberData(TestResultData testResultData, Member member,
      Map<Id, ActualData<Features>> actualMap,
      {bool? verbose}) {
    member.accept(
        new PatchingDataExtractor(testResultData.compilerResult, actualMap));
  }

  @override
  void computeClassData(TestResultData testResultData, Class cls,
      Map<Id, ActualData<Features>> actualMap,
      {bool? verbose}) {
    new PatchingDataExtractor(testResultData.compilerResult, actualMap)
        .computeForClass(cls);
  }

  @override
  void computeLibraryData(TestResultData testResultData, Library library,
      Map<Id, ActualData<Features>> actualMap,
      {bool? verbose}) {
    new PatchingDataExtractor(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.error] = errorsToText(errors);
    return features;
  }

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

class Tags {
  static const String scope = 'scope';
  static const String kernelMembers = 'kernel-members';
  static const String initializers = 'initializers';
  static const String error = 'message';
  static const String isNonNullableByDefault = 'nnbd';
  static const String patch = 'patch';
  static const String isAbstract = 'isAbstract';
}

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

  @override
  Features computeLibraryValue(Id id, Library library) {
    Features features = new Features();
    features[Tags.isNonNullableByDefault] = '${library.isNonNullableByDefault}';
    return features;
  }

  @override
  Features computeClassValue(Id id, Class cls) {
    SourceClassBuilder clsBuilder =
        lookupClassBuilder(compilerResult, cls) as SourceClassBuilder;

    Features features = new Features();
    if (cls.isAbstract) {
      features.add(Tags.isAbstract);
    }
    clsBuilder.scope
        .filteredNameIterator(
            includeDuplicates: false, includeAugmentations: false)
        .forEach((String name, Builder builder) {
      features.addElement(Tags.scope, name);
    });

    for (Member m in clsBuilder.actualCls.members) {
      if (m is Procedure &&
          (m.isMemberSignature ||
              (m.isForwardingStub && !m.isForwardingSemiStub))) {
        // Don't include member signatures.
        continue;
      }
      String name = m.name.text;
      if (m is Constructor) {
        name = '${m.enclosingClass.name}.${name}';
      }
      features.addElement(Tags.kernelMembers, name);
    }

    return features;
  }

  @override
  Features computeMemberValue(Id id, Member member) {
    Features features = new Features();
    if (member is Constructor) {
      for (Initializer initializer in member.initializers) {
        String desc = initializer.runtimeType.toString();
        if (initializer is FieldInitializer) {
          desc = 'FieldInitializer(${getMemberName(initializer.field)})';
        }
        features.addElement(Tags.initializers, desc);
      }
    }
    SourceMemberBuilder? memberBuilder =
        lookupMemberBuilder(compilerResult, member, required: false)
            as SourceMemberBuilder?;
    List<MemberBuilder>? patchMembers;
    if (memberBuilder is SourceProcedureBuilder) {
      patchMembers = memberBuilder.patchesForTesting;
    }
    if (memberBuilder is DeclaredSourceConstructorBuilder) {
      patchMembers = memberBuilder.patchesForTesting;
    }
    if (memberBuilder is SourceFactoryBuilder) {
      patchMembers = memberBuilder.patchesForTesting;
    }
    if (patchMembers != null) {
      features.add(Tags.patch);
    }

    return features;
  }
}
