// 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 'compiler_helper.dart' as mock;
import 'memory_compiler.dart' as memory;
import 'package:compiler/src/commandline_options.dart';
import 'package:compiler/src/dart_types.dart';
import 'package:compiler/src/compiler.dart'
    show Compiler;
import 'package:compiler/src/elements/elements.dart'
    show Element,
         MemberElement,
         TypeDeclarationElement,
         ClassElement;

GenericType instantiate(TypeDeclarationElement element,
                        List<DartType> arguments) {
  if (element.isClass) {
    return new InterfaceType(element, arguments);
  } else {
    assert(element.isTypedef);
    return new TypedefType(element, arguments);
  }
}

class TypeEnvironment {
  final Compiler compiler;

  static Future<TypeEnvironment> create(
      String source, {bool useMockCompiler: true,
                      bool expectNoErrors: false,
                      bool expectNoWarningsOrErrors: false,
                      bool stopAfterTypeInference: false,
                      String mainSource}) {
    Uri uri;
    Compiler compiler;
    bool stopAfterTypeInference = mainSource != null;
    if (mainSource == null) {
      source = '''import 'dart:async';
                  main() {}
                  $source''';
    } else {
      source = '$mainSource\n$source';
    }
    memory.DiagnosticCollector collector;
    if (useMockCompiler) {
      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(
          memorySourceFiles: {'main.dart': source},
          diagnosticHandler: collector,
          options: stopAfterTypeInference
              ? [] : [Flags.analyzeAll, Flags.analyzeOnly]);
    }
    compiler.stopAfterTypeInference = stopAfterTypeInference;
    return compiler.run(uri).then((_) {
      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);
    });
  }

  TypeEnvironment._(Compiler this.compiler);

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

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

  DartType operator[] (String name) {
    if (name == 'dynamic') return const DynamicType();
    if (name == 'void') return const VoidType();
    return getElementType(name);
  }

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

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

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

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

  DartType flatten(DartType T) {
    return compiler.types.flatten(T);
  }

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