// Copyright (c) 2017, 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:expect/expect.dart";
import "package:kernel/ast.dart";
import "package:kernel/core_types.dart";
import "package:kernel/testing/mock_sdk_program.dart";
import "package:kernel/text/ast_to_text.dart";
import "package:kernel/transformations/erasure.dart";

void main(List<String> arguments) {
  new Tester().testLocalFunction();
}

class Tester {
  final Program program;

  final Library library;

  final Procedure mainMethod;

  final CoreTypes coreTypes;

  static final Uri base =
      new Uri(scheme: "org.dartlang.kernel", host: "", path: "/");

  Tester.internal(this.program, this.library, this.mainMethod)
      : coreTypes = new CoreTypes(program);

  factory Tester() {
    Program program = createMockSdkProgram();
    Library library = new Library(base.resolve("main.dart"))..parent = program;
    Procedure mainMethod = buildProcedure("main");
    library.addMember(mainMethod);
    program.libraries.add(library);
    program.mainMethod = mainMethod;
    return new Tester.internal(program, library, mainMethod);
  }

  void addStatement(Statement statement) {
    Block body = mainMethod.function.body;
    body.statements.add(statement);
    statement.parent = body;
  }

  void testLocalFunction() {
    FunctionDeclaration fDeclaration = buildFunctionDeclaration(
        "f", buildFunctionNodeWithTypesAndParameters());
    FunctionExpression functionExpression =
        new FunctionExpression(buildFunctionNodeWithTypesAndParameters());

    addStatement(fDeclaration);
    addStatement(new ExpressionStatement(functionExpression));
    Expect.stringEquals(
        "<T extends dynamic, S extends dart.core::List<T>>(S) → T",
        debugNodeToString(fDeclaration.variable.type).trim());
    Expect.stringEquals(
        "<T extends dynamic, S extends dart.core::List<T>>(S) → T",
        debugNodeToString(functionExpression.getStaticType(null)).trim());
    transformProgram(coreTypes, program);
    Expect.stringEquals("(dart.core::List<dynamic>) → dynamic",
        debugNodeToString(fDeclaration.variable.type).trim());
    Expect.stringEquals("(dart.core::List<dynamic>) → dynamic",
        debugNodeToString(functionExpression.getStaticType(null)).trim());
  }

  /// Builds this function: `f<T, S extends List<T>>(S argument) → T {}`.
  FunctionNode buildFunctionNodeWithTypesAndParameters() {
    TypeParameter tVariable = new TypeParameter("T", const DynamicType());
    TypeParameter sVariable = new TypeParameter("S", const DynamicType());
    TypeParameterType tType = new TypeParameterType(tVariable);
    TypeParameterType sType = new TypeParameterType(sVariable);
    sVariable.bound = new InterfaceType(coreTypes.listClass, <DartType>[tType]);
    return new FunctionNode(buildBlock(),
        positionalParameters: <VariableDeclaration>[
          new VariableDeclaration("argument", type: sType),
        ],
        typeParameters: <TypeParameter>[tVariable, sVariable],
        returnType: tType);
  }

  static Block buildBlock([List<Statement> statements]) {
    return new Block(statements ?? <Statement>[]);
  }

  static FunctionNode buildFunction([Statement body]) {
    return new FunctionNode(body ?? buildBlock());
  }

  static Procedure buildProcedure(String name, [FunctionNode function]) {
    return new Procedure(
        new Name(name), ProcedureKind.Method, function ?? buildFunction());
  }

  static FunctionDeclaration buildFunctionDeclaration(
      String name, FunctionNode function) {
    return new FunctionDeclaration(
        new VariableDeclaration(name,
            type: function.functionType, isFinal: true),
        function);
  }
}
