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

import 'dart:io' hide Link;
import 'package:_fe_analyzer_shared/src/testing/features.dart';
import 'package:async_helper/async_helper.dart';
import 'package:compiler/src/closure.dart';
import 'package:compiler/src/common.dart';
import 'package:compiler/src/compiler.dart';
import 'package:compiler/src/deferred_load.dart';
import 'package:compiler/src/elements/entities.dart';
import 'package:compiler/src/ir/util.dart';
import 'package:compiler/src/js_model/element_map.dart';
import 'package:compiler/src/js_model/js_world.dart';
import 'package:compiler/src/js_emitter/startup_emitter/fragment_merger.dart';
import 'package:compiler/src/kernel/kernel_strategy.dart';
import 'package:expect/expect.dart';
import '../equivalence/id_equivalence.dart';
import '../equivalence/id_equivalence_helper.dart';
import 'package:compiler/src/constants/values.dart';

import 'package:kernel/ast.dart' as ir;

///  Add in options to pass to the compiler like
/// `Flags.disableTypeInference` or `Flags.disableInlining`
const List<String> compilerOptions = const [];

/// Compute the [OutputUnit]s for all source files involved in the test, and
/// ensure that the compiler is correctly calculating what is used and what is
/// not. We expect all test entry points to be in the `data` directory and any
/// or all supporting libraries to be in the `libs` folder, starting with the
/// same name as the original file in `data`.
main(List<String> args) {
  asyncTest(() async {
    Directory dataDir = Directory.fromUri(Platform.script.resolve('data'));
    await checkTests(dataDir, const OutputUnitDataComputer(),
        options: compilerOptions, args: args, setUpFunction: () {
      importPrefixes.clear();
    },
        testedConfigs: allSpecConfigs +
            [twoDeferredFragmentConfig, threeDeferredFragmentConfig]);
  });
}

// For ease of testing and making our tests easier to read, we impose an
// artificial constraint of requiring every deferred import use a different
// named prefix per test. We enforce this constraint here by checking that no
// prefix name responds to two different libraries.
Map<String, Uri> importPrefixes = {};

String importPrefixString(OutputUnit unit) {
  StringBuffer sb = StringBuffer();
  bool first = true;
  for (ImportEntity import in unit.imports) {
    if (!first) sb.write(', ');
    sb.write('${import.name}');
    first = false;
    Expect.isTrue(import.isDeferred);

    if (importPrefixes.containsKey(import.name)) {
      var existing = importPrefixes[import.name];
      var current = import.enclosingLibraryUri;
      Expect.equals(
          existing,
          current,
          '\n    Duplicate prefix \'${import.name}\' used in both:\n'
          '     - $existing and\n'
          '     - $current.\n'
          '    We require using unique prefixes on these tests to make '
          'the expectations more readable.');
    }
    importPrefixes[import.name] = import.enclosingLibraryUri;
  }
  return sb.toString();
}

/// Create a consistent string representation of [OutputUnit]s for both
/// KImportEntities and ImportElements.
String outputUnitString(OutputUnit unit) {
  if (unit == null) return 'none';
  String sb = importPrefixString(unit);
  return '${unit.name}{$sb}';
}

Map<String, List<PreFragment>> buildPreFragmentMap(
    Map<String, List<FinalizedFragment>> fragmentsToLoad,
    List<PreFragment> preDeferredFragments) {
  Map<FinalizedFragment, PreFragment> fragmentMap = {};
  for (var preFragment in preDeferredFragments) {
    fragmentMap[preFragment.finalizedFragment] = preFragment;
  }
  Map<String, List<PreFragment>> preFragmentMap = {};
  fragmentsToLoad.forEach((loadId, fragments) {
    List<PreFragment> preFragments = [];
    for (var fragment in fragments) {
      preFragments.add(fragmentMap[fragment]);
    }
    preFragmentMap[loadId] = preFragments.toList();
  });
  return preFragmentMap;
}

class Tags {
  static const String cls = 'class_unit';
  static const String member = 'member_unit';
  static const String closure = 'closure_unit';
  static const String constants = 'constants';
  static const String type = 'type_unit';
  // The below tags appear in a single block comment in the main file.
  // To keep them appearing in sequential order we prefix characters.
  static const String preFragments = 'a_pre_fragments';
  static const String finalizedFragments = 'b_finalized_fragments';
  static const String steps = 'c_steps';
}

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

  /// OutputData for [member] as a kernel based element.
  ///
  /// At this point the compiler has already been run, so it is holding the
  /// relevant OutputUnits, we just need to extract that information from it. We
  /// fill [actualMap] with the data computed about what the resulting OutputUnit
  /// is.
  @override
  void computeMemberData(Compiler compiler, MemberEntity member,
      Map<Id, ActualData<Features>> actualMap,
      {bool verbose: false}) {
    JsClosedWorld closedWorld = compiler.backendClosedWorldForTesting;
    JsToElementMap elementMap = closedWorld.elementMap;
    MemberDefinition definition = elementMap.getMemberDefinition(member);
    OutputUnitIrComputer(compiler.reporter, actualMap, elementMap,
            closedWorld.outputUnitData, closedWorld.closureDataLookup)
        .run(definition.node);
  }

  @override
  void computeClassData(Compiler compiler, ClassEntity cls,
      Map<Id, ActualData<Features>> actualMap,
      {bool verbose: false}) {
    JsClosedWorld closedWorld = compiler.backendClosedWorldForTesting;
    JsToElementMap elementMap = closedWorld.elementMap;
    ClassDefinition definition = elementMap.getClassDefinition(cls);
    OutputUnitIrComputer(compiler.reporter, actualMap, elementMap,
            closedWorld.outputUnitData, closedWorld.closureDataLookup)
        .computeForClass(definition.node);
  }

  @override
  void computeLibraryData(Compiler compiler, LibraryEntity library,
      Map<Id, ActualData<Features>> actualMap,
      {bool verbose}) {
    KernelFrontendStrategy frontendStrategy = compiler.frontendStrategy;
    ir.Library node = frontendStrategy.elementMap.getLibraryNode(library);
    List<PreFragment> preDeferredFragments = compiler
        .backendStrategy.emitterTask.emitter.preDeferredFragmentsForTesting;
    Map<String, List<FinalizedFragment>> fragmentsToLoad =
        compiler.backendStrategy.emitterTask.emitter.finalizedFragmentsToLoad;
    Set<OutputUnit> omittedOutputUnits =
        compiler.backendStrategy.emitterTask.emitter.omittedOutputUnits;
    PreFragmentsIrComputer(compiler.reporter, actualMap, preDeferredFragments,
            fragmentsToLoad, omittedOutputUnits)
        .computeForLibrary(node);
  }

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

class PreFragmentsIrComputer extends IrDataExtractor<Features> {
  final List<PreFragment> _preDeferredFragments;
  final Map<String, List<FinalizedFragment>> _fragmentsToLoad;
  final Set<OutputUnit> _omittedOutputUnits;

  PreFragmentsIrComputer(
      DiagnosticReporter reporter,
      Map<Id, ActualData<Features>> actualMap,
      this._preDeferredFragments,
      this._fragmentsToLoad,
      this._omittedOutputUnits)
      : super(reporter, actualMap);

  @override
  Features computeLibraryValue(Id id, ir.Library library) {
    var name = '${library.importUri.pathSegments.last}';
    Features features = new Features();
    if (!name.startsWith('main')) return features;

    // First build a list of pre fragments and their dependencies.
    int index = 1;
    Map<FinalizedFragment, int> finalizedFragmentIndices = {};
    Map<PreFragment, int> preFragmentIndices = {};
    Map<int, PreFragment> reversePreFragmentIndices = {};
    Map<int, FinalizedFragment> reverseFinalizedFragmentIndices = {};
    for (var preFragment in _preDeferredFragments) {
      if (!preFragmentIndices.containsKey(preFragment)) {
        var finalizedFragment = preFragment.finalizedFragment;
        preFragmentIndices[preFragment] = index;
        finalizedFragmentIndices[finalizedFragment] = index;
        reversePreFragmentIndices[index] = preFragment;
        reverseFinalizedFragmentIndices[index] = finalizedFragment;
        index++;
      }
    }

    for (int i = 1; i < index; i++) {
      var preFragment = reversePreFragmentIndices[i];
      List<String> needs = [];
      List<OutputUnit> supplied = [];
      List<String> usedBy = [];
      for (var dependent in preFragment.successors) {
        if (preFragmentIndices.containsKey(dependent)) {
          usedBy.add('p${preFragmentIndices[dependent]}');
        }
      }

      for (var dependency in preFragment.predecessors) {
        if (preFragmentIndices.containsKey(dependency)) {
          needs.add('p${preFragmentIndices[dependency]}');
        }
      }

      for (var emittedOutputUnit in preFragment.emittedOutputUnits) {
        supplied.add(emittedOutputUnit.outputUnit);
      }

      var suppliedString = '[${supplied.map(outputUnitString).join(', ')}]';
      features.addElement(Tags.preFragments,
          'p$i: {units: $suppliedString, usedBy: $usedBy, needs: $needs}');
    }

    // Now dump finalized fragments and load ids.
    for (int i = 1; i < index; i++) {
      var finalizedFragment = reverseFinalizedFragmentIndices[i];
      List<String> supplied = [];

      for (var codeFragment in finalizedFragment.codeFragments) {
        List<String> outputUnitStrings = [];
        for (var outputUnit in codeFragment.outputUnits) {
          if (!_omittedOutputUnits.contains(outputUnit)) {
            outputUnitStrings.add(outputUnitString(outputUnit));
          }
        }
        if (outputUnitStrings.isNotEmpty) {
          supplied.add(outputUnitStrings.join('+'));
        }
      }

      if (supplied.isNotEmpty) {
        var suppliedString = '[${supplied.join(', ')}]';
        features.addElement(Tags.finalizedFragments, 'f$i: $suppliedString');
      }
    }

    _fragmentsToLoad.forEach((loadId, finalizedFragments) {
      List<String> finalizedFragmentNeeds = [];
      for (var finalizedFragment in finalizedFragments) {
        assert(finalizedFragmentIndices.containsKey(finalizedFragment));
        finalizedFragmentNeeds
            .add('f${finalizedFragmentIndices[finalizedFragment]}');
      }
      features.addElement(
          Tags.steps, '$loadId=(${finalizedFragmentNeeds.join(', ')})');
    });

    return features;
  }
}

class OutputUnitIrComputer extends IrDataExtractor<Features> {
  final JsToElementMap _elementMap;
  final OutputUnitData _data;
  final ClosureData _closureDataLookup;

  Set<String> _constants = {};

  OutputUnitIrComputer(
      DiagnosticReporter reporter,
      Map<Id, ActualData<Features>> actualMap,
      this._elementMap,
      this._data,
      this._closureDataLookup)
      : super(reporter, actualMap);

  Features getMemberValue(
      String tag, MemberEntity member, Set<String> constants) {
    Features features = Features();
    features.add(tag,
        value: outputUnitString(_data.outputUnitForMemberForTesting(member)));
    for (var constant in constants) {
      features.addElement(Tags.constants, constant);
    }
    return features;
  }

  @override
  Features computeClassValue(Id id, ir.Class node) {
    var cls = _elementMap.getClass(node);
    Features features = Features();
    features.add(Tags.cls,
        value: outputUnitString(_data.outputUnitForClassForTesting(cls)));
    features.add(Tags.type,
        value: outputUnitString(_data.outputUnitForClassTypeForTesting(cls)));
    return features;
  }

  @override
  Features computeMemberValue(Id id, ir.Member node) {
    if (node is ir.Field && node.isConst) {
      ir.Expression initializer = node.initializer;
      ConstantValue constant = _elementMap.getConstantValue(node, initializer);
      if (!constant.isPrimitive) {
        SourceSpan span = computeSourceSpanFromTreeNode(initializer);
        if (initializer is ir.ConstructorInvocation) {
          // Adjust the source-span to match the AST-based location. The kernel FE
          // skips the "const" keyword for the expression offset and any prefix in
          // front of the constructor. The "-6" is an approximation assuming that
          // there is just a single space after "const" and no prefix.
          // TODO(sigmund): offsets should be fixed in the FE instead.
          span = SourceSpan(span.uri, span.begin - 6, span.end - 6);
        }
        _registerValue(
            NodeId(span.begin, IdKind.node),
            Features.fromMap({
              Tags.member: outputUnitString(
                  _data.outputUnitForConstantForTesting(constant))
            }),
            node,
            span,
            actualMap,
            reporter);
      }
    }

    Features features =
        getMemberValue(Tags.member, _elementMap.getMember(node), _constants);
    _constants = {};
    return features;
  }

  @override
  visitConstantExpression(ir.ConstantExpression node) {
    ConstantValue constant = _elementMap.getConstantValue(null, node);
    if (!constant.isPrimitive) {
      _constants.add('${constant.toStructuredText(_elementMap.types)}='
          '${outputUnitString(_data.outputUnitForConstant(constant))}');
    }
    return super.visitConstantExpression(node);
  }

  @override
  Features computeNodeValue(Id id, ir.TreeNode node) {
    if (node is ir.FunctionExpression || node is ir.FunctionDeclaration) {
      ClosureRepresentationInfo info = _closureDataLookup.getClosureInfo(node);
      return getMemberValue(Tags.closure, info.callMethod, const {});
    }
    return null;
  }
}

/// Set [actualMap] to hold a key of [id] with the computed data [value]
/// corresponding to [object] at location [sourceSpan]. We also perform error
/// checking to ensure that the same [id] isn't added twice.
void _registerValue<T>(Id id, T value, Object object, SourceSpan sourceSpan,
    Map<Id, ActualData<T>> actualMap, CompilerDiagnosticReporter reporter) {
  if (actualMap.containsKey(id)) {
    ActualData<T> existingData = actualMap[id];
    reportHere(reporter, sourceSpan,
        "Duplicate id ${id}, value=$value, object=$object");
    reportHere(
        reporter,
        sourceSpan,
        "Duplicate id ${id}, value=${existingData.value}, "
        "object=${existingData.object}");
    Expect.fail("Duplicate id $id.");
  }
  if (value != null) {
    actualMap[id] =
        ActualData<T>(id, value, sourceSpan.uri, sourceSpan.begin, object);
  }
}
