// 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 TestTargetFlags(
                forceLateLoweringsForTesting: LateLowering.all,
                forceLateLoweringSentinelForTesting: false),
            nnbdMode: NnbdMode.Strong),
        const TestConfig(sentinelMarker, 'use sentinel',
            explicitExperimentalFlags: const {
              ExperimentalFlag.nonNullable: true
            },
            targetFlags: const TestTargetFlags(
                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.
  @override
  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;
  }

  @override
  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();
  }

  @override
  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;
  }
}
