// Copyright (c) 2013, 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 type_test_helper;

import 'dart:async';
import 'package:expect/expect.dart';
import 'package:compiler/src/common/resolution.dart';
import 'package:compiler/src/common_elements.dart';
import 'package:compiler/src/commandline_options.dart';
import 'package:compiler/src/elements/resolution_types.dart';
import 'package:compiler/src/elements/types.dart';
import 'package:compiler/src/compiler.dart' show Compiler;
import 'package:compiler/src/elements/entities.dart';
import 'package:compiler/src/elements/elements.dart'
    show ClassElement, LibraryElement, TypedefElement;
import 'package:compiler/src/kernel/kernel_strategy.dart';
import 'package:compiler/src/world.dart' show ClosedWorld;
import 'compiler_helper.dart' as mock;
import 'compiler_helper.dart' show CompileMode;
import 'memory_compiler.dart' as memory;
import 'kernel/compiler_helper.dart' as dill;

export 'compiler_helper.dart' show CompileMode;

DartType instantiate(Entity element, List<DartType> arguments) {
  if (element is ClassElement) {
    return new ResolutionInterfaceType(element, arguments);
  } else if (element is ClassEntity) {
    return new InterfaceType(element, arguments);
  } else {
    assert(element is TypedefElement);
    return new ResolutionTypedefType(element, arguments);
  }
}

class TypeEnvironment {
  final Compiler compiler;
  final bool testBackendWorld;

  Resolution get resolution => compiler.resolution;

  static Future<TypeEnvironment> create(String source,
      {CompileMode compileMode: CompileMode.mock,
      bool useDillCompiler: false,
      bool expectNoErrors: false,
      bool expectNoWarningsOrErrors: false,
      bool stopAfterTypeInference: false,
      String mainSource,
      bool testBackendWorld: false,
      List<String> options: const <String>[],
      Map<String, String> fieldTypeMap: const <String, String>{}}) async {
    Uri uri;
    Compiler compiler;
    if (mainSource != null) {
      stopAfterTypeInference = true;
    }
    if (testBackendWorld) {
      stopAfterTypeInference = true;
      assert(mainSource != null);
    }
    if (mainSource == null) {
      source = '''import 'dart:async';
                  main() {}
                  $source''';
    } else {
      source = '$mainSource\n$source';
    }
    memory.DiagnosticCollector collector;
    if (compileMode == CompileMode.kernel) {
      collector = new memory.DiagnosticCollector();
      uri = Uri.parse('memory:main.dart');
      compiler = await dill.compileWithDill(
          entryPoint: uri,
          memorySourceFiles: {'main.dart': source},
          diagnosticHandler: collector,
          options: stopAfterTypeInference
              ? ([Flags.disableTypeInference]..addAll(options))
              : ([
                  Flags.disableTypeInference,
                  Flags.analyzeAll,
                  Flags.analyzeOnly
                ]..addAll(options)),
          beforeRun: (Compiler compiler) {
            compiler.stopAfterTypeInference = stopAfterTypeInference;
          });
    } else {
      if (compileMode == CompileMode.mock) {
        uri = new Uri(scheme: 'source');
        mock.MockCompiler mockCompiler = mock.mockCompilerFor(source, uri,
            analyzeAll: !stopAfterTypeInference,
            analyzeOnly: !stopAfterTypeInference);
        mockCompiler.diagnosticHandler =
            mock.createHandler(mockCompiler, source);
        collector = mockCompiler.diagnosticCollector;
        compiler = mockCompiler;
        compiler.stopAfterTypeInference = stopAfterTypeInference;
        await compiler.run(uri);
      } else {
        collector = new memory.DiagnosticCollector();
        uri = Uri.parse('memory:main.dart');
        memory.CompilationResult result = await memory.runCompiler(
            entryPoint: uri,
            memorySourceFiles: {'main.dart': source},
            diagnosticHandler: collector,
            options: stopAfterTypeInference
                ? ([Flags.useOldFrontend]..addAll(options))
                : ([Flags.useOldFrontend, Flags.analyzeAll, Flags.analyzeOnly]
                  ..addAll(options)),
            beforeRun: (compiler) {
              compiler.stopAfterTypeInference = stopAfterTypeInference;
            });
        compiler = result.compiler;
      }
    }
    if (expectNoErrors || expectNoWarningsOrErrors) {
      var errors = collector.errors;
      Expect.isTrue(errors.isEmpty, 'Unexpected errors: ${errors}');
    }
    if (expectNoWarningsOrErrors) {
      var warnings = collector.warnings;
      Expect.isTrue(warnings.isEmpty, 'Unexpected warnings: ${warnings}');
    }
    return new TypeEnvironment._(compiler, testBackendWorld: testBackendWorld);
  }

  TypeEnvironment._(Compiler this.compiler, {this.testBackendWorld: false});

  ElementEnvironment get elementEnvironment {
    if (testBackendWorld) {
      return compiler.backendClosedWorldForTesting.elementEnvironment;
    } else {
      return compiler.frontendStrategy.elementEnvironment;
    }
  }

  CommonElements get commonElements {
    if (testBackendWorld) {
      return compiler.backendClosedWorldForTesting.commonElements;
    } else {
      return compiler.frontendStrategy.commonElements;
    }
  }

  DartTypes get types {
    if (resolution != null) {
      return resolution.types;
    } else {
      if (testBackendWorld) {
        return compiler.backendClosedWorldForTesting.dartTypes;
      } else {
        KernelFrontEndStrategy frontendStrategy = compiler.frontendStrategy;
        return frontendStrategy.elementMap.types;
      }
    }
  }

  Entity getElement(String name) {
    LibraryEntity mainLibrary = elementEnvironment.mainLibrary;
    dynamic element = elementEnvironment.lookupLibraryMember(mainLibrary, name);
    element ??= elementEnvironment.lookupClass(mainLibrary, name);
    element ??=
        elementEnvironment.lookupClass(commonElements.coreLibrary, name);
    if (element == null && mainLibrary is LibraryElement) {
      element = mainLibrary.find(name);
    }
    Expect.isNotNull(element, "No element named '$name' found.");
    if (element is ClassElement) {
      element.ensureResolved(compiler.resolution);
    } else if (element is TypedefElement) {
      element.computeType(compiler.resolution);
    }
    return element;
  }

  ClassEntity getClass(String name) {
    LibraryEntity mainLibrary = elementEnvironment.mainLibrary;
    ClassEntity element = elementEnvironment.lookupClass(mainLibrary, name);
    Expect.isNotNull(element, "No class named '$name' found.");
    if (element is ClassElement) {
      element.ensureResolved(compiler.resolution);
    }
    return element;
  }

  DartType getElementType(String name) {
    dynamic element = getElement(name);
    if (element is FieldEntity) {
      return elementEnvironment.getFieldType(element);
    } else if (element is FunctionEntity) {
      return elementEnvironment.getFunctionType(element);
    } else if (element is ClassEntity) {
      return elementEnvironment.getThisType(element);
    } else {
      /// ignore: undefined_method
      return element.computeType(compiler.resolution);
    }
  }

  DartType operator [](String name) {
    if (name == 'dynamic') {
      if (resolution != null) {
        return const ResolutionDynamicType();
      } else {
        return const DynamicType();
      }
    }
    if (name == 'void') {
      if (resolution != null) {
        return const ResolutionVoidType();
      } else {
        return const VoidType();
      }
    }
    return getElementType(name);
  }

  MemberEntity _getMember(String name, [ClassEntity cls]) {
    if (cls != null) {
      return elementEnvironment.lookupLocalClassMember(cls, name);
    } else {
      LibraryEntity mainLibrary = elementEnvironment.mainLibrary;
      return elementEnvironment.lookupLibraryMember(mainLibrary, name);
    }
  }

  DartType getMemberType(String name, [ClassEntity cls]) {
    MemberEntity member = _getMember(name, cls);
    if (member is FieldEntity) {
      return elementEnvironment.getFieldType(member);
    } else if (member is FunctionEntity) {
      return elementEnvironment.getFunctionType(member);
    }
    throw 'Unexpected member: $member for ${name}, cls=$cls';
  }

  DartType getClosureType(String name, [ClassEntity cls]) {
    if (testBackendWorld) {
      throw new UnsupportedError(
          "getClosureType not supported for backend testing.");
    }
    MemberEntity member = _getMember(name, cls);
    DartType type;
    compiler.resolutionWorldBuilder
        .forEachLocalFunction((MemberEntity m, Local local) {
      if (member == m) {
        type ??= elementEnvironment.getLocalFunctionType(local);
      }
    });
    return type;
  }

  DartType getFieldType(String name) {
    LibraryEntity mainLibrary = elementEnvironment.mainLibrary;
    FieldEntity field =
        elementEnvironment.lookupLibraryMember(mainLibrary, name);
    Expect.isNotNull(field);
    return elementEnvironment.getFieldType(field);
  }

  bool isSubtype(DartType T, DartType S) {
    return types.isSubtype(T, S);
  }

  bool isMoreSpecific(ResolutionDartType T, ResolutionDartType S) {
    return (types as Types).isMoreSpecific(T, S);
  }

  ResolutionDartType computeLeastUpperBound(
      ResolutionDartType T, ResolutionDartType S) {
    return (types as Types).computeLeastUpperBound(T, S);
  }

  ResolutionDartType flatten(ResolutionDartType T) {
    return (types as Types).flatten(T);
  }

  ResolutionFunctionType functionType(
      ResolutionDartType returnType, List<ResolutionDartType> parameters,
      {List<ResolutionDartType> optionalParameters:
          const <ResolutionDartType>[],
      Map<String, ResolutionDartType> namedParameters}) {
    List<String> namedParameterNames = <String>[];
    List<ResolutionDartType> namedParameterTypes = <ResolutionDartType>[];
    if (namedParameters != null) {
      namedParameters.forEach((String name, ResolutionDartType type) {
        namedParameterNames.add(name);
        namedParameterTypes.add(type);
      });
    }
    return new ResolutionFunctionType.synthesized(returnType, parameters,
        optionalParameters, namedParameterNames, namedParameterTypes);
  }

  ClosedWorld get closedWorld {
    if (testBackendWorld) {
      return compiler.backendClosedWorldForTesting;
    } else {
      return compiler.resolutionWorldBuilder.closedWorldForTesting;
    }
  }
}

/// Data used to create a function type either as method declaration or a
/// typedef declaration.
class FunctionTypeData {
  final String returnType;
  final String name;
  final String parameters;

  const FunctionTypeData(this.returnType, this.name, this.parameters);

  String toString() => '$returnType $name$parameters';
}

/// Return source code that declares the function types in [dataList] as
/// method declarations of the form:
///
///     $returnType $name$parameters => null;
String createMethods(List<FunctionTypeData> dataList,
    {String additionalData: '', String prefix: ''}) {
  StringBuffer sb = new StringBuffer();
  for (FunctionTypeData data in dataList) {
    sb.writeln(
        '${data.returnType} $prefix${data.name}${data.parameters} => null;');
  }
  sb.write(additionalData);
  return sb.toString();
}

/// Return source code that declares the function types in [dataList] as
/// typedefs of the form:
///
///     typedef fx = $returnType Function$parameters;
///     fx $name;
///
/// where a field using the typedef is add to make the type accessible by name.
String createTypedefs(List<FunctionTypeData> dataList,
    {String additionalData: '', String prefix: ''}) {
  StringBuffer sb = new StringBuffer();
  for (int index = 0; index < dataList.length; index++) {
    FunctionTypeData data = dataList[index];
    sb.writeln(
        'typedef f$index = ${data.returnType} Function${data.parameters};');
  }
  for (int index = 0; index < dataList.length; index++) {
    FunctionTypeData data = dataList[index];
    sb.writeln('f$index $prefix${data.name};');
  }
  sb.write(additionalData);
  return sb.toString();
}

/// Return source code that uses the function types in [dataList].
String createUses(List<FunctionTypeData> dataList, {String prefix: ''}) {
  StringBuffer sb = new StringBuffer();
  for (int index = 0; index < dataList.length; index++) {
    FunctionTypeData data = dataList[index];
    sb.writeln('$prefix${data.name};');
  }
  return sb.toString();
}
