// Copyright (c) 2021, 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 'package:_fe_analyzer_shared/src/testing/features.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;

// 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) {
  List<String> importNames = [];
  for (ImportEntity import in unit.imports) {
    importNames.add(import.name);
    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;
  }
  importNames.sort();
  return importNames.join(', ');
}

/// 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);
  }
}
