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

import 'package:kernel/ast.dart';
import 'package:kernel/type_algebra.dart';
import '../builder/member_builder.dart';
import '../source/source_library_builder.dart';
import 'kernel_helper.dart';

const String _tearOffNamePrefix = '_#';
const String _tearOffNameSuffix = '#tearOff';

/// Creates the synthesized name to use for the lowering of the tear off of a
/// constructor or factory by the given [name] in [library].
Name constructorTearOffName(String name, Library library) {
  return new Name(
      '$_tearOffNamePrefix'
      '${name.isEmpty ? 'new' : name}'
      '$_tearOffNameSuffix',
      library);
}

/// Creates the synthesized name to use for the lowering of the tear off of a
/// constructor or factory by the given [constructorName] in [library].
Name typedefTearOffName(
    String typedefName, String constructorName, Library library) {
  return new Name(
      '$_tearOffNamePrefix'
      '$typedefName#'
      '${constructorName.isEmpty ? 'new' : constructorName}'
      '$_tearOffNameSuffix',
      library);
}

/// Returns the name of the corresponding constructor or factory if [name] is
/// the synthesized name of a lowering of the tear off of a constructor or
/// factory. Returns `null` otherwise.
String? extractConstructorNameFromTearOff(Name name) {
  if (name.text.startsWith(_tearOffNamePrefix) &&
      name.text.endsWith(_tearOffNameSuffix) &&
      name.text.length >
          _tearOffNamePrefix.length + _tearOffNameSuffix.length) {
    String text =
        name.text.substring(0, name.text.length - _tearOffNameSuffix.length);
    text = text.substring(_tearOffNamePrefix.length);
    if (text.contains('#')) {
      return null;
    }
    return text == 'new' ? '' : text;
  }
  return null;
}

/// If [name] is the synthesized name of a lowering of a typedef tear off, a
/// list containing the [String] name of the typedef and the [Name] name of the
/// corresponding constructor or factory is returned. Returns `null` otherwise.
List<Object>? extractTypedefNameFromTearOff(Name name) {
  if (name.text.startsWith(_tearOffNamePrefix) &&
      name.text.endsWith(_tearOffNameSuffix) &&
      name.text.length >
          _tearOffNamePrefix.length + _tearOffNameSuffix.length) {
    String text =
        name.text.substring(0, name.text.length - _tearOffNameSuffix.length);
    text = text.substring(_tearOffNamePrefix.length);
    int hashIndex = text.indexOf('#');
    if (hashIndex == -1) {
      return null;
    }
    String typedefName = text.substring(0, hashIndex);
    String constructorName = text.substring(hashIndex + 1);
    constructorName = constructorName == 'new' ? '' : constructorName;
    return [typedefName, new Name(constructorName, name.library)];
  }
  return null;
}

/// Returns `true` if [member] is a lowered constructor, factory or typedef tear
/// off.
bool isTearOffLowering(Member member) {
  return member is Procedure &&
      (isConstructorTearOffLowering(member) ||
          isTypedefTearOffLowering(member));
}

/// Returns `true` if [procedure] is a lowered constructor or factory tear off.
bool isConstructorTearOffLowering(Procedure procedure) {
  return extractConstructorNameFromTearOff(procedure.name) != null;
}

/// Returns `true` if [procedure] is a lowered typedef tear off.
bool isTypedefTearOffLowering(Procedure procedure) {
  return extractTypedefNameFromTearOff(procedure.name) != null;
}

/// Creates the [Procedure] for the lowering of a generative constructor of
/// the given [name] in [compilationUnit].
///
/// If constructor tear off lowering is not enabled, `null` is returned.
Procedure? createConstructorTearOffProcedure(
    String name,
    SourceLibraryBuilder compilationUnit,
    Uri fileUri,
    int fileOffset,
    Reference? reference,
    {required bool forAbstractClassOrEnum}) {
  if (!forAbstractClassOrEnum &&
      compilationUnit
          .loader.target.backendTarget.isConstructorTearOffLoweringEnabled) {
    return _createTearOffProcedure(
        compilationUnit,
        constructorTearOffName(name, compilationUnit.library),
        fileUri,
        fileOffset,
        reference);
  }
  return null;
}

/// Creates the [Procedure] for the lowering of a non-redirecting factory of
/// the given [name] in [compilationUnit].
///
/// If constructor tear off lowering is not enabled, `null` is returned.
Procedure? createFactoryTearOffProcedure(
    String name,
    SourceLibraryBuilder compilationUnit,
    Uri fileUri,
    int fileOffset,
    Reference? reference) {
  if (compilationUnit
      .loader.target.backendTarget.isFactoryTearOffLoweringEnabled) {
    return _createTearOffProcedure(
        compilationUnit,
        constructorTearOffName(name, compilationUnit.library),
        fileUri,
        fileOffset,
        reference);
  }
  return null;
}

/// Creates the [Procedure] for the lowering of a typedef tearoff of a
/// constructor of the given [name] in with the typedef defined in
/// [libraryBuilder].
Procedure createTypedefTearOffProcedure(
    String typedefName,
    String name,
    SourceLibraryBuilder libraryBuilder,
    Uri fileUri,
    int fileOffset,
    Reference? reference) {
  return _createTearOffProcedure(
      libraryBuilder,
      typedefTearOffName(typedefName, name, libraryBuilder.library),
      fileUri,
      fileOffset,
      reference);
}

/// Creates the parameters and body for [tearOff] based on [constructor] in
/// [enclosingClass].
void buildConstructorTearOffProcedure(Procedure tearOff, Member constructor,
    Class enclosingClass, SourceLibraryBuilder libraryBuilder) {
  assert(
      constructor is Constructor ||
          (constructor is Procedure && constructor.isFactory) ||
          (constructor is Procedure && constructor.isStatic),
      "Unexpected constructor tear off target $constructor "
      "(${constructor.runtimeType}).");

  int fileOffset = tearOff.fileOffset;

  FunctionNode function = constructor.function!;
  List<TypeParameter> classTypeParameters;
  if (constructor is Constructor) {
    // Generative constructors implicitly have the type parameters of the
    // enclosing class.
    classTypeParameters = enclosingClass.typeParameters;
  } else {
    // Factory constructors explicitly copy over the type parameters of the
    // enclosing class.
    classTypeParameters = function.typeParameters;
  }

  FreshTypeParameters freshTypeParameters =
      _createFreshTypeParameters(classTypeParameters, tearOff.function);

  List<DartType> typeArguments = freshTypeParameters.freshTypeArguments;
  Substitution substitution = freshTypeParameters.substitution;
  _createParameters(tearOff, constructor, substitution, libraryBuilder);
  Arguments arguments = _createArguments(tearOff, typeArguments, fileOffset);
  _createTearOffBody(tearOff, constructor, arguments);
  tearOff.function.fileOffset = tearOff.fileOffset;
  tearOff.function.fileEndOffset = tearOff.fileOffset;
  updatePrivateMemberName(tearOff, libraryBuilder);
}

/// Creates the parameters and body for [tearOff] for a typedef tearoff of
/// [constructor] in [enclosingClass] with [typeParameters] as the typedef
/// parameters and [typeArguments] as the arguments passed to the
/// [enclosingClass].
void buildTypedefTearOffProcedure(
    Procedure tearOff,
    Member constructor,
    Class enclosingClass,
    List<TypeParameter> typeParameters,
    List<DartType> typeArguments,
    SourceLibraryBuilder libraryBuilder) {
  assert(
      constructor is Constructor ||
          (constructor is Procedure && constructor.isFactory) ||
          (constructor is Procedure && constructor.isStatic),
      "Unexpected constructor tear off target $constructor "
      "(${constructor.runtimeType}).");

  int fileOffset = tearOff.fileOffset;

  FunctionNode function = constructor.function!;
  List<TypeParameter> classTypeParameters;
  if (constructor is Constructor) {
    // Generative constructors implicitly have the type parameters of the
    // enclosing class.
    classTypeParameters = enclosingClass.typeParameters;
  } else {
    // Factory constructors explicitly copy over the type parameters of the
    // enclosing class.
    classTypeParameters = function.typeParameters;
  }

  FreshTypeParameters freshTypeParameters =
      _createFreshTypeParameters(typeParameters, tearOff.function);

  Substitution substitution = freshTypeParameters.substitution;
  if (!substitution.isEmpty) {
    if (typeArguments.isNotEmpty) {
      // Translate [typeArgument] into the context of the synthesized procedure.
      typeArguments = new List<DartType>.generate(typeArguments.length,
          (int index) => substitution.substituteType(typeArguments[index]));
    }
  }
  _createParameters(
      tearOff,
      constructor,
      Substitution.fromPairs(classTypeParameters, typeArguments),
      libraryBuilder);
  Arguments arguments = _createArguments(tearOff, typeArguments, fileOffset);
  _createTearOffBody(tearOff, constructor, arguments);
  tearOff.function.fileOffset = tearOff.fileOffset;
  tearOff.function.fileEndOffset = tearOff.fileOffset;
  updatePrivateMemberName(tearOff, libraryBuilder);
}

/// Creates the parameters for the redirecting factory [tearOff] based on the
/// [redirectingConstructor] declaration.
FreshTypeParameters buildRedirectingFactoryTearOffProcedureParameters(
    Procedure tearOff,
    Procedure redirectingConstructor,
    SourceLibraryBuilder libraryBuilder) {
  assert(redirectingConstructor.isRedirectingFactory);
  FunctionNode function = redirectingConstructor.function;
  FreshTypeParameters freshTypeParameters =
      _createFreshTypeParameters(function.typeParameters, tearOff.function);
  Substitution substitution = freshTypeParameters.substitution;
  _createParameters(
      tearOff, redirectingConstructor, substitution, libraryBuilder);
  tearOff.function.fileOffset = tearOff.fileOffset;
  tearOff.function.fileEndOffset = tearOff.fileOffset;
  updatePrivateMemberName(tearOff, libraryBuilder);
  return freshTypeParameters;
}

/// Creates the body for the redirecting factory [tearOff] with the target
/// [constructor] and [typeArguments].
///
/// Returns the [SynthesizedFunctionNode] object need to perform default value
/// computation.
SynthesizedFunctionNode buildRedirectingFactoryTearOffBody(
    Procedure tearOff,
    Member target,
    List<DartType> typeArguments,
    FreshTypeParameters freshTypeParameters) {
  int fileOffset = tearOff.fileOffset;

  List<TypeParameter> typeParameters;
  if (target is Constructor) {
    typeParameters = target.enclosingClass.typeParameters;
  } else {
    typeParameters = target.function!.typeParameters;
  }

  if (!freshTypeParameters.substitution.isEmpty) {
    if (typeArguments.length != typeParameters.length) {
      // Error case: Use default types as type arguments.
      typeArguments = new List<DartType>.generate(typeParameters.length,
          (int index) => typeParameters[index].defaultType);
    }
    if (typeArguments.isNotEmpty) {
      // Translate [typeArgument] into the context of the synthesized procedure.
      typeArguments = new List<DartType>.generate(
          typeArguments.length,
          (int index) => freshTypeParameters.substitution
              .substituteType(typeArguments[index]));
    }
  }
  Map<TypeParameter, DartType> substitutionMap;
  if (typeParameters.length == typeArguments.length) {
    substitutionMap = new Map<TypeParameter, DartType>.fromIterables(
        typeParameters, typeArguments);
  } else {
    // Error case: Substitute type parameters with `dynamic`.
    substitutionMap = new Map<TypeParameter, DartType>.fromIterables(
        typeParameters,
        new List<DartType>.generate(
            typeParameters.length, (int index) => const DynamicType()));
  }
  Arguments arguments = _createArguments(tearOff, typeArguments, fileOffset);
  _createTearOffBody(tearOff, target, arguments);
  return new SynthesizedFunctionNode(
      substitutionMap, target.function!, tearOff.function,
      identicalSignatures: false);
}

/// Creates the synthesized [Procedure] node for a tear off lowering by the
/// given [name].
Procedure _createTearOffProcedure(SourceLibraryBuilder libraryBuilder,
    Name name, Uri fileUri, int fileOffset, Reference? reference) {
  return new Procedure(name, ProcedureKind.Method, new FunctionNode(null),
      fileUri: fileUri, isStatic: true, reference: reference)
    ..startFileOffset = fileOffset
    ..fileOffset = fileOffset
    ..fileEndOffset = fileOffset
    ..isNonNullableByDefault = libraryBuilder.isNonNullableByDefault;
}

/// Creates the synthesized type parameters for a tear off lowering. The type
/// parameters are based [originalTypeParameters] and are inserted into
/// [newFunctionNode]. The created [FreshTypeParameters] is returned.
FreshTypeParameters _createFreshTypeParameters(
    List<TypeParameter> originalTypeParameters, FunctionNode newFunctionNode) {
  FreshTypeParameters freshTypeParameters;
  if (originalTypeParameters.isNotEmpty) {
    freshTypeParameters = getFreshTypeParameters(originalTypeParameters);
    List<TypeParameter> typeParameters =
        freshTypeParameters.freshTypeParameters;
    newFunctionNode.typeParameters.addAll(typeParameters);
    setParents(typeParameters, newFunctionNode);
  } else {
    freshTypeParameters = new FreshTypeParameters([], [], Substitution.empty);
  }
  return freshTypeParameters;
}

/// Creates the parameters for the [tearOff] lowering based of the parameters
/// in [constructor] and using the [substitution] to compute the parameter and
/// return types.
void _createParameters(Procedure tearOff, Member constructor,
    Substitution substitution, SourceLibraryBuilder libraryBuilder) {
  FunctionNode function = constructor.function!;
  for (VariableDeclaration constructorParameter
      in function.positionalParameters) {
    VariableDeclaration tearOffParameter = new VariableDeclaration(
        constructorParameter.name,
        type: substitution.substituteType(constructorParameter.type))
      ..fileOffset = constructorParameter.fileOffset;
    tearOff.function.positionalParameters.add(tearOffParameter);
    tearOffParameter.parent = tearOff.function;
  }
  for (VariableDeclaration constructorParameter in function.namedParameters) {
    VariableDeclaration tearOffParameter = new VariableDeclaration(
        constructorParameter.name,
        type: substitution.substituteType(constructorParameter.type),
        isRequired: constructorParameter.isRequired)
      ..fileOffset = constructorParameter.fileOffset;
    tearOff.function.namedParameters.add(tearOffParameter);
    tearOffParameter.parent = tearOff.function;
  }
  tearOff.function.returnType =
      substitution.substituteType(function.returnType);
  tearOff.function.requiredParameterCount = function.requiredParameterCount;
  libraryBuilder.loader.registerTypeDependency(
      tearOff,
      new TypeDependency(tearOff, constructor, substitution,
          copyReturnType: true));
}

/// Creates the [Arguments] for passing the parameters from [tearOff] to its
/// target, using [typeArguments] as the passed type arguments.
Arguments _createArguments(
    Procedure tearOff, List<DartType> typeArguments, int fileOffset) {
  List<Expression> positionalArguments = [];
  for (VariableDeclaration tearOffParameter
      in tearOff.function.positionalParameters) {
    positionalArguments
        .add(new VariableGet(tearOffParameter)..fileOffset = fileOffset);
  }
  List<NamedExpression> namedArguments = [];
  for (VariableDeclaration tearOffParameter
      in tearOff.function.namedParameters) {
    namedArguments.add(new NamedExpression(tearOffParameter.name!,
        new VariableGet(tearOffParameter)..fileOffset = fileOffset)
      ..fileOffset = fileOffset);
  }
  Arguments arguments = new Arguments(positionalArguments,
      named: namedArguments, types: typeArguments)
    ..fileOffset = tearOff.fileOffset;
  return arguments;
}

/// Creates the tear of body for [tearOff] which calls [target] with
/// [arguments].
void _createTearOffBody(Procedure tearOff, Member target, Arguments arguments) {
  assert(target is Constructor ||
      (target is Procedure && target.isFactory) ||
      (target is Procedure && target.isStatic));
  Expression constructorInvocation;
  if (target is Constructor) {
    constructorInvocation = new ConstructorInvocation(target, arguments)
      ..fileOffset = tearOff.fileOffset;
  } else {
    constructorInvocation = new StaticInvocation(target as Procedure, arguments)
      ..fileOffset = tearOff.fileOffset;
  }
  tearOff.function.body = new ReturnStatement(constructorInvocation)
    ..fileOffset = tearOff.fileOffset
    ..parent = tearOff.function;
}

/// Reverse engineered typedef tear off information.
class LoweredTypedefTearOff {
  Procedure typedefTearOff;
  Expression targetTearOff;
  List<DartType> typeArguments;

  LoweredTypedefTearOff(
      this.typedefTearOff, this.targetTearOff, this.typeArguments);

  /// Reverse engineers [expression] to a [LoweredTypedefTearOff] if
  /// [expression] is the encoding of a lowered typedef tear off.
  static LoweredTypedefTearOff? fromExpression(Expression expression) {
    if (expression is StaticTearOff &&
        isTypedefTearOffLowering(expression.target)) {
      Procedure typedefTearOff = expression.target;
      Statement? body = typedefTearOff.function.body;
      if (body is ReturnStatement) {
        Expression? constructorInvocation = body.expression;
        Member? target;
        List<DartType>? typeArguments;
        if (constructorInvocation is ConstructorInvocation) {
          target = constructorInvocation.target;
          typeArguments = constructorInvocation.arguments.types;
        } else if (constructorInvocation is StaticInvocation) {
          target = constructorInvocation.target;
          typeArguments = constructorInvocation.arguments.types;
        }
        if (target != null) {
          Class cls = target.enclosingClass!;
          Name tearOffName =
              constructorTearOffName(target.name.text, cls.enclosingLibrary);
          for (Procedure procedure in cls.procedures) {
            if (procedure.name == tearOffName) {
              target = procedure;
              break;
            }
          }
          Expression targetTearOff;
          if (target is Constructor ||
              target is Procedure && target.isFactory) {
            targetTearOff = new ConstructorTearOff(target!);
          } else {
            targetTearOff = new StaticTearOff(target as Procedure);
          }
          return new LoweredTypedefTearOff(
              typedefTearOff, targetTearOff, typeArguments!);
        }
      }
    }
    return null;
  }
}
