// 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,
    {required bool forAbstractClassOrEnum}) {
  if (!forAbstractClassOrEnum &&
      compilationUnit
          .loader.target.backendTarget.isConstructorTearOffLoweringEnabled) {
    return _createTearOffProcedure(
        compilationUnit,
        constructorTearOffName(name, compilationUnit.library),
        fileUri,
        fileOffset);
  }
  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) {
  if (compilationUnit
      .loader.target.backendTarget.isFactoryTearOffLoweringEnabled) {
    return _createTearOffProcedure(
        compilationUnit,
        constructorTearOffName(name, compilationUnit.library),
        fileUri,
        fileOffset);
  }
  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) {
  return _createTearOffProcedure(
      libraryBuilder,
      typedefTearOffName(typedefName, name, libraryBuilder.library),
      fileUri,
      fileOffset);
}

/// 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) {
  return new Procedure(name, ProcedureKind.Method, new FunctionNode(null),
      fileUri: fileUri, isStatic: true)
    ..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));
}

/// 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;
  Constant targetTearOffConstant;
  List<DartType> typeArguments;

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

  /// Reverse engineers [constant] to a [LoweredTypedefTearOff] if [constant] is
  /// the encoding of a lowered typedef tear off.
  // TODO(johnniwinther): Check that this works with outlines.
  static LoweredTypedefTearOff? fromConstant(Constant constant) {
    if (constant is StaticTearOffConstant &&
        isTypedefTearOffLowering(constant.target)) {
      Procedure typedefTearOff = constant.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;
            }
          }
          Constant tearOffConstant;
          if (target is Constructor ||
              target is Procedure && target.isFactory) {
            tearOffConstant = new ConstructorTearOffConstant(target!);
          } else {
            tearOffConstant = new StaticTearOffConstant(target as Procedure);
          }
          return new LoweredTypedefTearOff(
              typedefTearOff, tearOffConstant, typeArguments!);
        }
      }
    }
    return null;
  }
}
