// 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.

// @dart = 2.9

import 'dart:io' show Directory, Platform;
import 'package:_fe_analyzer_shared/src/testing/id.dart';
import 'package:_fe_analyzer_shared/src/testing/id_testing.dart'
    show DataInterpreter, runTests;
import 'package:_fe_analyzer_shared/src/testing/id_testing.dart';
import 'package:_fe_analyzer_shared/src/testing/features.dart';
import 'package:front_end/src/api_prototype/experimental_flags.dart';
import 'package:front_end/src/base/nnbd_mode.dart';
import 'package:front_end/src/testing/id_extractor.dart';
import 'package:front_end/src/testing/id_testing_helper.dart';
import 'package:front_end/src/testing/id_testing_utils.dart';
import 'package:front_end/src/api_prototype/lowering_predicates.dart';
import 'package:kernel/ast.dart';
import 'package:kernel/src/printer.dart';
import 'package:kernel/target/targets.dart';

const String isNullMarker = 'is-null';
const String sentinelMarker = 'sentinel';

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 PredicateDataComputer(), [
        const TestConfig(isNullMarker, 'use is-null',
            explicitExperimentalFlags: const {
              ExperimentalFlag.nonNullable: true
            },
            targetFlags: const TargetFlags(
                forceLateLoweringsForTesting: LateLowering.all,
                forceLateLoweringSentinelForTesting: false),
            nnbdMode: NnbdMode.Strong),
        const TestConfig(sentinelMarker, 'use sentinel',
            explicitExperimentalFlags: const {
              ExperimentalFlag.nonNullable: true
            },
            targetFlags: const TargetFlags(
                forceLateLoweringsForTesting: LateLowering.all,
                forceLateLoweringSentinelForTesting: true),
            nnbdMode: NnbdMode.Strong)
      ]));
}

class Tags {
  static const String lateField = 'lateField';
  static const String lateFieldName = 'lateFieldName';
  static const String lateIsSetField = 'lateIsSetField';
  static const String lateFieldGetter = 'lateFieldGetter';
  static const String lateFieldSetter = 'lateFieldSetter';
  static const String lateFieldTarget = 'lateFieldTarget';
  static const String lateFieldInitializer = 'lateFieldInitializer';

  static const String lateLocal = 'lateLocal';
  static const String lateIsSetLocal = 'lateIsSetLocal';
  static const String lateLocalGetter = 'lateLocalGetter';
  static const String lateLocalSetter = 'lateLocalSetter';

  static const String extensionThis = 'extensionThis';
}

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

  /// Function that computes a data mapping for [library].
  ///
  /// Fills [actualMap] with the data.
  void computeLibraryData(
      TestConfig config,
      InternalCompilerResult compilerResult,
      Library library,
      Map<Id, ActualData<Features>> actualMap,
      {bool verbose}) {
    new PredicateDataExtractor(compilerResult, actualMap)
        .computeForLibrary(library);
  }

  @override
  void computeMemberData(
      TestConfig config,
      InternalCompilerResult compilerResult,
      Member member,
      Map<Id, ActualData<Features>> actualMap,
      {bool verbose}) {
    member.accept(new PredicateDataExtractor(compilerResult, actualMap));
  }

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

class PredicateDataExtractor extends CfeDataExtractor<Features> {
  Map<String, Features> featureMap = {};
  Map<String, NodeId> nodeIdMap = {};

  PredicateDataExtractor(InternalCompilerResult compilerResult,
      Map<Id, ActualData<Features>> actualMap)
      : super(compilerResult, actualMap);

  @override
  Features computeLibraryValue(Id id, Library node) {
    return null;
  }

  @override
  Features computeMemberValue(Id id, Member node) {
    if (node is Field) {
      Features features = new Features();
      if (isLateLoweredField(node)) {
        features.add(Tags.lateField);
        features[Tags.lateFieldName] =
            extractFieldNameFromLateLoweredField(node).text;
      }
      if (isLateLoweredIsSetField(node)) {
        features.add(Tags.lateIsSetField);
        features[Tags.lateFieldName] =
            extractFieldNameFromLateLoweredIsSetField(node).text;
      }
      Field target = getLateFieldTarget(node);
      if (target != null) {
        features[Tags.lateFieldTarget] = getQualifiedMemberName(target);
      }
      Expression initializer = getLateFieldInitializer(node);
      if (initializer != null) {
        features[Tags.lateFieldInitializer] =
            initializer.toText(astTextStrategyForTesting);
      }
      return features;
    } else if (node is Procedure) {
      Features features = new Features();
      if (isLateLoweredFieldGetter(node)) {
        features.add(Tags.lateFieldGetter);
        features[Tags.lateFieldName] =
            extractFieldNameFromLateLoweredFieldGetter(node).text;
      }
      if (isLateLoweredFieldSetter(node)) {
        features.add(Tags.lateFieldSetter);
        features[Tags.lateFieldName] =
            extractFieldNameFromLateLoweredFieldSetter(node).text;
      }
      Field target = getLateFieldTarget(node);
      if (target != null) {
        features[Tags.lateFieldTarget] = getQualifiedMemberName(target);
      }
      Expression initializer = getLateFieldInitializer(node);
      if (initializer != null) {
        features[Tags.lateFieldInitializer] =
            initializer.toText(astTextStrategyForTesting);
      }
      return features;
    }
    return null;
  }

  void visitProcedure(Procedure node) {
    super.visitProcedure(node);
    nodeIdMap.forEach((String name, NodeId id) {
      Features features = featureMap[name];
      if (features != null) {
        TreeNode nodeWithOffset = computeTreeNodeWithOffset(node);
        registerValue(
            nodeWithOffset.location.file, id.value, id, features, name);
      }
    });
    nodeIdMap.clear();
    featureMap.clear();
  }

  void visitVariableDeclaration(VariableDeclaration node) {
    String name;
    String tag;
    if (isLateLoweredLocal(node)) {
      name = extractLocalNameFromLateLoweredLocal(node.name);
      tag = Tags.lateLocal;
    } else if (isLateLoweredIsSetLocal(node)) {
      name = extractLocalNameFromLateLoweredIsSet(node.name);
      tag = Tags.lateIsSetLocal;
    } else if (isLateLoweredLocalGetter(node)) {
      name = extractLocalNameFromLateLoweredGetter(node.name);
      tag = Tags.lateLocalGetter;
    } else if (isLateLoweredLocalSetter(node)) {
      name = extractLocalNameFromLateLoweredSetter(node.name);
      tag = Tags.lateLocalSetter;
    } else if (isExtensionThis(node)) {
      name = extractLocalNameForExtensionThis(node.name);
      tag = Tags.extensionThis;
    } else if (node.name != null) {
      name = node.name;
    }
    if (name != null) {
      if (node.fileOffset != TreeNode.noOffset) {
        nodeIdMap[name] ??= new NodeId(node.fileOffset, IdKind.node);
      }
      if (tag != null) {
        Features features = featureMap[name] ??= new Features();
        features.add(tag);
      }
    }
    super.visitVariableDeclaration(node);
  }

  @override
  ActualData<Features> mergeData(
      ActualData<Features> value1, ActualData<Features> value2) {
    if ('${value1.value}' == '${value2.value}') {
      // The extension this parameter is seen twice in the extension method
      // and the corresponding tearoff. The features are identical, though, so
      // we just use the first.
      return value1;
    }
    return null;
  }
}
