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

library dart2js.js_emitter.instantiation_stub_generator;

import '../common_elements.dart' show JCommonElements, JElementEnvironment;
import '../elements/entities.dart';
import '../io/source_information.dart';
import '../js/js.dart' as jsAst;
import '../js/js.dart' show js;
import '../js_backend/namer.dart' show Namer;
import '../universe/call_structure.dart' show CallStructure;
import '../universe/codegen_world_builder.dart';
import '../universe/selector.dart' show Selector;
import '../universe/world_builder.dart' show SelectorConstraints;
import '../world.dart' show JClosedWorld;

import 'model.dart';

import 'code_emitter_task.dart' show CodeEmitterTask, Emitter;

// Generator of stubs required for Instantiation classes.
class InstantiationStubGenerator {
  final CodeEmitterTask _emitterTask;
  final Namer _namer;
  final CodegenWorld _codegenWorld;
  final JClosedWorld _closedWorld;
  // ignore: UNUSED_FIELD
  final SourceInformationStrategy _sourceInformationStrategy;

  InstantiationStubGenerator(this._emitterTask, this._namer, this._closedWorld,
      this._codegenWorld, this._sourceInformationStrategy);

  Emitter get _emitter => _emitterTask.emitter;

  JCommonElements get _commonElements => _closedWorld.commonElements;
  JElementEnvironment get _elementEnvironment =>
      _closedWorld.elementEnvironment;

  /// Generates a stub to forward a call selector with no type arguments to a
  /// call selector with stored types.
  ///
  /// [instantiationClass] is the class containing the captured type arguments.
  /// [callSelector] is the selector with no type arguments. [targetSelector] is
  /// the selector accepting the type arguments.
  ParameterStubMethod _generateStub(
      ClassEntity instantiationClass,
      FieldEntity functionField,
      Selector callSelector,
      Selector targetSelector) {
    // TODO(sra): Generate source information for stub that has no member.
    //
    //SourceInformationBuilder sourceInformationBuilder =
    //    _sourceInformationStrategy.createBuilderForContext(member);
    //SourceInformation sourceInformation =
    //    sourceInformationBuilder.buildStub(member, callStructure);

    assert(callSelector.typeArgumentCount == 0);
    int typeArgumentCount = targetSelector.typeArgumentCount;
    assert(typeArgumentCount > 0);

    // The forwarding stub for three arguments of an instantiation with two type
    // arguments looks like this:
    //
    // ```
    // call$3: function(a0, a1, a2) {
    //   return this._f.call$2$3(a0, a1, a2, this.$ti[0], this.$ti[1]);
    // }
    // ```

    List<jsAst.Parameter> parameters = [];
    List<jsAst.Expression> arguments = [];

    for (int i = 0; i < callSelector.argumentCount; i++) {
      String jsName = 'a$i';
      arguments.add(js('#', jsName));
      parameters.add(jsAst.Parameter(jsName));
    }

    for (int i = 0; i < targetSelector.typeArgumentCount; i++) {
      arguments.add(js('this.#.#[#]', [
        _namer.rtiFieldJsName,
        _namer.instanceFieldPropertyName(_commonElements.rtiRestField),
        js.number(i)
      ]));
    }

    jsAst.Fun function = js('function(#) { return this.#.#(#); }', [
      parameters,
      _namer.instanceFieldPropertyName(functionField),
      _namer.invocationName(targetSelector),
      arguments,
    ]);
    // TODO(sra): .withSourceInformation(sourceInformation);

    jsAst.Name name = _namer.invocationName(callSelector);
    return ParameterStubMethod(name, null, function);
  }

  /// Generates a stub for a 'signature' selector. The stub calls the underlying
  /// function's 'signature' method and calls a helper to subsitute the type
  /// parameters in the type term. The stub looks like this:
  ///
  /// ```
  /// $signature:: function() {
  ///   return H.instantiatedGenericFunctionTypeNewRti(
  ///       H.closureFunctionType(this._genericClosure),
  ///       this.$ti);
  /// }
  /// ```
  ParameterStubMethod _generateSignatureStub(FieldEntity functionField) {
    jsAst.Name operatorSignature =
        _namer.asName(_namer.fixedNames.operatorSignature);

    jsAst.Fun function = _generateSignatureNewRti(functionField);

    // TODO(sra): Generate source information for stub that has no member.
    // TODO(sra): .withSourceInformation(sourceInformation);

    return ParameterStubMethod(operatorSignature, null, function);
  }

  jsAst.Fun _generateSignatureNewRti(FieldEntity functionField) =>
      js('function() { return #(#(this.#), this.#); }', [
        _emitter.staticFunctionAccess(
            _commonElements.instantiatedGenericFunctionTypeNewRti),
        _emitter.staticFunctionAccess(_commonElements.closureFunctionType),
        _namer.instanceFieldPropertyName(functionField),
        _namer.rtiFieldJsName,
      ]);

  // Returns all stubs for an instantiation class.
  //
  List<StubMethod> generateStubs(
      ClassEntity instantiationClass, FunctionEntity member) {
    // 1. Find the number of type parameters in [instantiationClass].
    int typeArgumentCount = _closedWorld.dartTypes
        .getThisType(instantiationClass)
        .typeArguments
        .length;
    assert(typeArgumentCount > 0);

    // 2. Find the function field access path.
    FieldEntity functionField;
    _elementEnvironment.forEachInstanceField(instantiationClass,
        (ClassEntity enclosing, FieldEntity field) {
      if (_closedWorld.fieldAnalysis.getFieldData(field).isElided) return;
      if (field.name == '_genericClosure') functionField = field;
    });
    assert(functionField != null,
        "Can't find Closure field of $instantiationClass");

    String call = _namer.closureInvocationSelectorName;
    Map<Selector, SelectorConstraints> callSelectors =
        _codegenWorld.invocationsByName(call);

    Set<ParameterStructure> computeLiveParameterStructures() {
      Set<ParameterStructure> parameterStructures = {};

      void process(FunctionEntity function) {
        if (function.parameterStructure.typeParameters == typeArgumentCount) {
          parameterStructures.add(function.parameterStructure);
        }
      }

      _codegenWorld.closurizedStatics.forEach(process);
      _codegenWorld.closurizedMembers.forEach(process);
      _codegenWorld.forEachGenericClosureCallMethod(process);

      return parameterStructures;
    }

    List<StubMethod> stubs = [];

    // For every call-selector generate a stub to the corresponding selector
    // with filled-in type arguments.

    if (callSelectors != null) {
      Set<ParameterStructure> parameterStructures;
      for (Selector selector in callSelectors.keys) {
        CallStructure callStructure = selector.callStructure;
        if (callStructure.typeArgumentCount != 0) continue;
        CallStructure genericCallStructure =
            callStructure.withTypeArgumentCount(typeArgumentCount);
        parameterStructures ??= computeLiveParameterStructures();
        for (ParameterStructure parameterStructure in parameterStructures) {
          if (genericCallStructure.signatureApplies(parameterStructure)) {
            Selector genericSelector =
                Selector.call(selector.memberName, genericCallStructure);
            stubs.add(_generateStub(
                instantiationClass, functionField, selector, genericSelector));
            break;
          }
        }
      }
    }

    stubs.add(_generateSignatureStub(functionField));

    return stubs;
  }
}
