// 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 Element, MemberElement, ClassElement, LibraryElement, TypedefElement;
import 'package:compiler/src/world.dart' show ClosedWorld;
import 'compiler_helper.dart' as mock;
import 'memory_compiler.dart' as memory;
import 'kernel/compiler_helper.dart' as dill;

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

enum CompileMode { mock, memory, dill }

class TypeEnvironment {
  final Compiler compiler;
  final bool testBackendWorld;

  Resolution get resolution => compiler.resolution;

  Types get types => resolution.types;

  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}) 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.dill) {
      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]
              : [
                  Flags.disableTypeInference,
                  Flags.analyzeAll,
                  Flags.analyzeOnly
                ],
          beforeRun: (Compiler compiler) {
            compiler.stopAfterTypeInference = stopAfterTypeInference;
          });
    } else {
      if (compileMode == CompileMode.mock) {
        uri = new Uri(scheme: 'source');
        mock.MockCompiler mockCompiler = mock.compilerFor(source, uri,
            analyzeAll: !stopAfterTypeInference,
            analyzeOnly: !stopAfterTypeInference);
        mockCompiler.diagnosticHandler =
            mock.createHandler(mockCompiler, source);
        collector = mockCompiler.diagnosticCollector;
        compiler = mockCompiler;
      } else {
        collector = new memory.DiagnosticCollector();
        uri = Uri.parse('memory:main.dart');
        compiler = memory.compilerFor(
            entryPoint: uri,
            memorySourceFiles: {'main.dart': source},
            diagnosticHandler: collector,
            options: stopAfterTypeInference
                ? []
                : [Flags.analyzeAll, Flags.analyzeOnly]);
      }
      compiler.stopAfterTypeInference = stopAfterTypeInference;
      await compiler.run(uri);
    }
    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;
    }
  }

  Element getElement(String name) {
    LibraryElement mainApp = elementEnvironment.mainLibrary;
    dynamic element = mainApp.find(name);
    Expect.isNotNull(element);
    if (element.isClass) {
      element.ensureResolved(compiler.resolution);
    } else if (element.isTypedef) {
      element.computeType(compiler.resolution);
    }
    return element;
  }

  ClassEntity getClass(String name) {
    LibraryEntity mainLibrary = elementEnvironment.mainLibrary;
    ClassEntity element = elementEnvironment.lookupClass(mainLibrary, name);
    Expect.isNotNull(element);
    if (element is ClassElement) {
      element.ensureResolved(compiler.resolution);
    }
    return element;
  }

  ResolutionDartType getElementType(String name) {
    dynamic element = getElement(name);
    return element.computeType(compiler.resolution);
  }

  ResolutionDartType operator [](String name) {
    if (name == 'dynamic') return const ResolutionDynamicType();
    if (name == 'void') return const ResolutionVoidType();
    return getElementType(name);
  }

  ResolutionDartType getMemberType(ClassElement element, String name) {
    MemberElement member = element.localLookup(name);
    return member.computeType(compiler.resolution);
  }

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

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

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

  ResolutionDartType flatten(ResolutionDartType T) {
    return 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;
    }
  }
}
