// Copyright (c) 2016, 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 fasta.redirecting_factory_body;

import 'package:kernel/ast.dart';

import 'package:kernel/type_algebra.dart' show Substitution;

import 'body_builder.dart' show EnsureLoaded;

/// Name used for a static field holding redirecting factory information.
const String redirectingName = "_redirecting#";

/// Returns `true` if [member] is synthesized field holding the names of
/// redirecting factories declared in the same class.
///
/// This field should be special-cased by backends.
bool isRedirectingFactoryField(Member member) {
  return member is Field &&
      member.isStatic &&
      member.name.text == redirectingName;
}

/// Name used for a synthesized let variable used to encode redirecting factory
/// information in a factory method body.
const String letName = "#redirecting_factory";

/// Name used for a synthesized let variable used to encode type arguments to
/// the redirection target in a factory method body.
const String varNamePrefix = "#typeArg";

class RedirectingFactoryBody extends ExpressionStatement {
  RedirectingFactoryBody.internal(Expression value,
      [List<DartType>? typeArguments])
      : super(new Let(new VariableDeclaration(letName, initializer: value),
            encodeTypeArguments(typeArguments)));

  RedirectingFactoryBody(Member target, [List<DartType>? typeArguments])
      : this.internal(new StaticGet(target), typeArguments);

  RedirectingFactoryBody.unresolved(String name)
      : this.internal(new StringLiteral(name));

  Member? get target {
    dynamic value = getValue(expression);
    return value is StaticGet ? value.target : null;
  }

  String? get unresolvedName {
    dynamic value = getValue(expression);
    return value is StringLiteral ? value.value : null;
  }

  bool get isUnresolved => unresolvedName != null;

  List<DartType>? get typeArguments {
    if (expression is Let) {
      Let bodyExpression = expression as Let;
      if (bodyExpression.variable.name == letName) {
        return decodeTypeArguments(bodyExpression.body);
      }
    }
    return null;
  }

  static getValue(Expression expression) {
    if (expression is Let) {
      VariableDeclaration variable = expression.variable;
      if (variable.name == letName) {
        return variable.initializer;
      }
    }
    return null;
  }

  static void restoreFromDill(Procedure factory) {
    // This is a hack / work around for storing redirecting constructors in
    // dill files. See `ClassBuilder.addRedirectingConstructor` in
    // [kernel_class_builder.dart](kernel_class_builder.dart).
    FunctionNode function = factory.function;
    ExpressionStatement statement = function.body as ExpressionStatement;
    List<DartType>? typeArguments;
    if (statement.expression is Let) {
      Let expression = statement.expression as Let;
      typeArguments = decodeTypeArguments(expression.body);
    }
    function.body = new RedirectingFactoryBody.internal(
        getValue(statement.expression), typeArguments)
      ..parent = function;
  }

  static bool hasRedirectingFactoryBodyShape(Procedure factory) {
    if (factory.function.body is! ExpressionStatement) return false;
    Expression body = (factory.function.body as ExpressionStatement).expression;
    if (body is Let &&
        body.variable.name == letName &&
        body.variable.type is DynamicType &&
        body.variable.initializer is StaticGet) {
      Expression currentArgument = body.body;
      int argumentCount = 0;
      while (currentArgument is! InvalidExpression) {
        Expression argument = currentArgument;
        if (argument is Let) {
          String argumentName = "${varNamePrefix}${argumentCount}";
          if (argument.variable.name != argumentName) {
            return false;
          }
          if (argument.variable.initializer is! NullLiteral) {
            return false;
          }
          currentArgument = argument.body;
          ++argumentCount;
        } else {
          return false;
        }
      }
      return true;
    } else {
      return false;
    }
  }

  static Expression encodeTypeArguments(List<DartType>? typeArguments) {
    Expression result = new InvalidExpression(null);
    if (typeArguments == null) {
      return result;
    }
    for (int i = typeArguments.length - 1; i >= 0; i--) {
      result = new Let(
          new VariableDeclaration("$varNamePrefix$i",
              type: typeArguments[i], initializer: new NullLiteral()),
          result);
    }
    return result;
  }

  static List<DartType>? decodeTypeArguments(Expression encoded) {
    if (encoded is InvalidExpression) {
      return null;
    }
    List<DartType> result = <DartType>[];
    while (encoded is Let) {
      Let head = encoded;
      result.add(head.variable.type);
      encoded = head.body;
    }
    return result;
  }

  @override
  String toString() {
    return "RedirectingFactoryBody(${toStringInternal()})";
  }

  @override
  String toStringInternal() {
    return "";
  }
}

bool isRedirectingFactory(Member? member, {EnsureLoaded? helper}) {
  assert(helper == null || helper.isLoaded(member));
  return member is Procedure && member.function.body is RedirectingFactoryBody;
}

RedirectingFactoryBody? getRedirectingFactoryBody(Member? member) {
  return isRedirectingFactory(member)
      ? member!.function!.body as RedirectingFactoryBody
      : null;
}

class RedirectionTarget {
  final Member target;
  final List<DartType> typeArguments;

  RedirectionTarget(this.target, this.typeArguments);
}

RedirectionTarget? getRedirectionTarget(Procedure member, EnsureLoaded helper) {
  List<DartType> typeArguments = <DartType>[]..length =
      member.function.typeParameters.length;
  for (int i = 0; i < typeArguments.length; i++) {
    typeArguments[i] = new TypeParameterType.withDefaultNullabilityForLibrary(
        member.function.typeParameters[i], member.enclosingLibrary);
  }

  // We use the [tortoise and hare algorithm]
  // (https://en.wikipedia.org/wiki/Cycle_detection#Tortoise_and_hare) to
  // handle cycles.
  Member tortoise = member;
  RedirectingFactoryBody? tortoiseBody = getRedirectingFactoryBody(tortoise);
  Member? hare = tortoiseBody?.target;
  helper.ensureLoaded(hare);
  RedirectingFactoryBody? hareBody = getRedirectingFactoryBody(hare);
  while (tortoise != hare) {
    if (tortoiseBody?.isUnresolved ?? true) {
      return new RedirectionTarget(tortoise, typeArguments);
    }
    Member nextTortoise = tortoiseBody!.target!;
    helper.ensureLoaded(nextTortoise);
    List<DartType>? nextTypeArguments = tortoiseBody.typeArguments;
    if (nextTypeArguments == null) {
      nextTypeArguments = <DartType>[];
    }

    Substitution sub = Substitution.fromPairs(
        tortoise.function!.typeParameters, typeArguments);
    typeArguments = <DartType>[]..length = nextTypeArguments.length;
    for (int i = 0; i < typeArguments.length; i++) {
      typeArguments[i] = sub.substituteType(nextTypeArguments[i]);
    }

    tortoise = nextTortoise;
    tortoiseBody = getRedirectingFactoryBody(tortoise);
    helper.ensureLoaded(hareBody?.target);
    hare = getRedirectingFactoryBody(hareBody?.target)?.target;
    helper.ensureLoaded(hare);
    hareBody = getRedirectingFactoryBody(hare);
  }
  return null;
}
