// 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 mirror_system_helper;

import 'dart:async';
import 'package:compiler/implementation/mirrors/source_mirrors.dart';
import 'package:compiler/implementation/mirrors/dart2js_mirrors.dart';
import 'mock_compiler.dart';

export 'package:compiler/implementation/mirrors/source_mirrors.dart';
export 'package:compiler/implementation/mirrors/mirrors_util.dart';

const String SOURCE = 'source';
final Uri SOURCE_URI = new Uri(scheme: SOURCE, path: SOURCE);

// TODO(johnniwinther): Move this to a mirrors helper library.
Future<MirrorSystem> createMirrorSystem(String source) {
  MockCompiler compiler = new MockCompiler.internal(
      analyzeOnly: true,
      analyzeAll: true,
      preserveComments: true);
    compiler.registerSource(SOURCE_URI, source);
    compiler.librariesToAnalyzeWhenRun = <Uri>[SOURCE_URI];
  return compiler.runCompiler(null).then((_) {
    return new Dart2JsMirrorSystem(compiler);
  });
}

/**
 * Returns [:true:] if [type] is an instance of [:decl:] with type arguments
 * equal to [typeArgument].
 */
bool isInstance(ClassMirror decl, List<TypeMirror> typeArguments,
            ClassMirror type) {
  if (type.isOriginalDeclaration) return false;
  if (!isSameDeclaration(decl, type)) return false;
  return areEqualsTypes(typeArguments, type.typeArguments);
}

/**
 * Returns [:true:] if [type] is the same type as [expected]. This method
 * equates a non-generic declaration with its instantiation.
 */
bool isEqualType(TypeMirror expected, TypeMirror type) {
  if (expected == type) return true;
  if (expected is ClassMirror && type is ClassMirror) {
    if (!isSameDeclaration(expected, type)) return false;
    if (expected.isOriginalDeclaration || expected.typeArguments.isEmpty) {
      return type.isOriginalDeclaration || type.typeArguments.isEmpty;
    }
    return areEqualsTypes(expected.typeArguments, type.typeArguments);
  }
  return true;
}

/**
 * Returns [:true:] if [types] are equals to [expected] using the equalitry
 * defined by [isEqualType].
 */
bool areEqualsTypes(List<TypeMirror> expected, List<TypeMirror> types) {
  return checkSameList(expected, types, isEqualType);
}

/**
 * Returns [:true:] if an instance of [type] with type arguments equal to
 * [typeArguments] is found in [types].
 */
bool containsType(ClassMirror decl, List<TypeMirror> typeArguments,
                  Iterable<TypeMirror> types) {
  return types.any((type) => isInstance(decl, typeArguments, type));
}

/**
 * Returns the declaration of [type].
 */
TypeMirror toDeclaration(TypeMirror type) {
  return type is ClassMirror ? type.originalDeclaration : type;
}

/**
 * Returns [:true:] if [type] is of the same declaration as [expected].
 */
bool isSameDeclaration(TypeMirror expected, TypeMirror type) {
  return toDeclaration(expected) == toDeclaration(type);
}

/**
 * Returns [:true:] if a type of the declaration of [expected] is in [types].
 */
bool containsDeclaration(TypeMirror expected, Iterable<TypeMirror> types) {
  for (var type in types) {
    if (isSameDeclaration(expected, type)) {
      return true;
    }
  }
  return false;
}

/**
 * Returns [:true:] if declarations of [expected] are the same as those of
 * [types], taking order into account.
 */
bool isSameDeclarationList(Iterable<TypeMirror> expected,
                           Iterable<TypeMirror> types) {
  return checkSameList(expected, types, isSameDeclaration);
}

/**
 * Returns [:true:] if declarations of [expected] are the same as those of
 * [iterable], not taking order into account.
 */
bool isSameDeclarationSet(Iterable<TypeMirror> expected,
                          Iterable<TypeMirror> types) {
   Set<TypeMirror> expectedSet = expected.map(toDeclaration).toSet();
   Set<TypeMirror> typesSet = types.map(toDeclaration).toSet();
   return expectedSet.length == typesSet.length &&
          expectedSet.containsAll(typesSet);
}

/**
 * Utility method for checking whether [expected] and [iterable] contains the
 * same elements with respect to the checking function [check], takin order
 * into account.
 */
bool checkSameList(Iterable<TypeMirror> expected,
                   Iterable<TypeMirror> types,
                   bool check(TypeMirror a, TypeMirror b)) {
  if (expected.length != types.length) return false;
  Iterator<TypeMirror> expectedIterator = expected.iterator;
  Iterator<TypeMirror> typesIterator = types.iterator;
  while (expectedIterator.moveNext() && typesIterator.moveNext()) {
    if (!check(expectedIterator.current, typesIterator.current)) {
      return false;
    }
  }
  return true;
}
