// 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
                ? options
                : ([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);
  }

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

  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();
}
