// 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 dart._js_mirrors;

import 'dart:async';
import 'dart:collection' show UnmodifiableListView;
import 'dart:mirrors';

import 'dart:_foreign_helper' show
    JS,
    JS_CURRENT_ISOLATE,
    JS_CURRENT_ISOLATE_CONTEXT,
    JS_GET_NAME;
import 'dart:_collection-dev' as _symbol_dev;
import 'dart:_js_helper' show
    BoundClosure,
    Closure,
    JSInvocationMirror,
    JsCache,
    Null,
    Primitives,
    RuntimeError,
    createRuntimeType,
    createUnmangledInvocationMirror,
    getMangledTypeName,
    throwInvalidReflectionError,
    hasReflectableProperty,
    runtimeTypeToString,
    TypeVariable;
import 'dart:_interceptors' show
    Interceptor,
    JSExtendableArray;
import 'dart:_js_names';

const String METHODS_WITH_OPTIONAL_ARGUMENTS = r'$methodsWithOptionalArguments';

/// No-op method that is called to inform the compiler that tree-shaking needs
/// to be disabled.
disableTreeShaking() => preserveNames();

/// No-op method that is called to inform the compiler that metadata must be
/// preserved at runtime.
preserveMetadata() {}

String getName(Symbol symbol) {
  preserveNames();
  return n(symbol);
}

class JsMirrorSystem implements MirrorSystem {
  UnmodifiableMapView<Uri, LibraryMirror> _cachedLibraries;

  final IsolateMirror isolate = new JsIsolateMirror();

  TypeMirror get dynamicType => _dynamicType;
  TypeMirror get voidType => _voidType;

  final static TypeMirror _dynamicType =
      new JsTypeMirror(const Symbol('dynamic'));
  final static TypeMirror _voidType = new JsTypeMirror(const Symbol('void'));

  static final Map<String, List<LibraryMirror>> librariesByName =
      computeLibrariesByName();

  Map<Uri, LibraryMirror> get libraries {
    if (_cachedLibraries != null) return _cachedLibraries;
    Map<Uri, LibraryMirror> result = new Map();
    for (List<LibraryMirror> list in librariesByName.values) {
      for (LibraryMirror library in list) {
        result[library.uri] = library;
      }
    }
    return _cachedLibraries =
        new UnmodifiableMapView<Uri, LibraryMirror>(result);
  }

  Iterable<LibraryMirror> findLibrary(Symbol libraryName) {
    return new UnmodifiableListView<LibraryMirror>(
        librariesByName[n(libraryName)]);
  }

  static Map<String, List<LibraryMirror>> computeLibrariesByName() {
    disableTreeShaking();
    var result = new Map<String, List<LibraryMirror>>();
    var jsLibraries = JS('JSExtendableArray|Null', 'init.libraries');
    if (jsLibraries == null) return result;
    for (List data in jsLibraries) {
      String name = data[0];
      Uri uri = Uri.parse(data[1]);
      List<String> classes = data[2];
      List<String> functions = data[3];
      var metadataFunction = data[4];
      var fields = data[5];
      bool isRoot = data[6];
      var globalObject = data[7];
      List metadata = (metadataFunction == null)
          ? const [] : JS('List', '#()', metadataFunction);
      var libraries = result.putIfAbsent(name, () => <LibraryMirror>[]);
      libraries.add(
          new JsLibraryMirror(
              s(name), uri, classes, functions, metadata, fields, isRoot,
              globalObject));
    }
    return result;
  }
}

abstract class JsMirror implements Mirror {
  const JsMirror();

  String get _prettyName;

  String toString() => _prettyName;

  // TODO(ahe): Remove this method from the API.
  MirrorSystem get mirrors => currentJsMirrorSystem;

  _getField(JsMirror receiver) {
    throw new UnimplementedError();
  }

  void _setField(JsMirror receiver, Object arg) {
    throw new UnimplementedError();
  }

  _loadField(String name) {
    throw new UnimplementedError();
  }

  void _storeField(String name, Object arg) {
    throw new UnimplementedError();
  }
}

// This class is somewhat silly in the current implementation.
class JsIsolateMirror extends JsMirror implements IsolateMirror {
  final _isolateContext = JS_CURRENT_ISOLATE_CONTEXT();

  String get _prettyName => 'Isolate';

  String get debugName {
    String id = _isolateContext == null ? 'X' : _isolateContext.id.toString();
    // Using name similar to what the VM uses.
    return '${n(rootLibrary.simpleName)}-$id';
  }

  bool get isCurrent => JS_CURRENT_ISOLATE_CONTEXT() == _isolateContext;

  LibraryMirror get rootLibrary {
    return currentJsMirrorSystem.libraries.values.firstWhere(
        (JsLibraryMirror library) => library._isRoot);
  }
}

abstract class JsDeclarationMirror extends JsMirror
    implements DeclarationMirror {
  final Symbol simpleName;

  const JsDeclarationMirror(this.simpleName);

  Symbol get qualifiedName => computeQualifiedName(owner, simpleName);

  bool get isPrivate => n(simpleName).startsWith('_');

  bool get isTopLevel => owner != null && owner is LibraryMirror;

  // TODO(ahe): This should use qualifiedName.
  String toString() => "$_prettyName on '${n(simpleName)}'";

  List<JsMethodMirror> get _methods {
    throw new RuntimeError('Should not call _methods');
  }

  _invoke(List positionalArguments, Map<Symbol, dynamic> namedArguments) {
    throw new RuntimeError('Should not call _invoke');
  }

  // TODO(ahe): Implement this.
  SourceLocation get location => throw new UnimplementedError();
}

class JsTypeVariableMirror extends JsTypeMirror implements TypeVariableMirror {
  final DeclarationMirror owner;
  final TypeVariable _typeVariable;
  TypeMirror _cachedUpperBound;

  JsTypeVariableMirror(TypeVariable typeVariable, this.owner)
      : this._typeVariable = typeVariable,
        super(s(typeVariable.name));

  bool operator ==(other) {
    return (other is JsTypeVariableMirror &&
        simpleName == other.simpleName &&
        owner == other.owner);
  }

  int get hashCode {
    int code = 0x3FFFFFFF & (JsTypeVariableMirror).hashCode;
    code ^= 17 * simpleName.hashCode;
    code ^= 19 * owner.hashCode;
    return code;
  }

  String get _prettyName => 'TypeVariableMirror';

  TypeMirror get upperBound {
    if (_cachedUpperBound != null) return _cachedUpperBound;
    return _cachedUpperBound = typeMirrorFromRuntimeTypeRepresentation(
        JS('', 'init.metadata[#]', _typeVariable.bound));
  }
}

class JsTypeMirror extends JsDeclarationMirror implements TypeMirror {
  JsTypeMirror(Symbol simpleName)
      : super(simpleName);

  String get _prettyName => 'TypeMirror';

  DeclarationMirror get owner => null;

  // TODO(ahe): Doesn't match the specification, see http://dartbug.com/11569.
  bool get isTopLevel => true;

  // TODO(ahe): Implement these.
  List<InstanceMirror> get metadata => throw new UnimplementedError();

  bool get hasReflectedType => false;
  Type get reflectedType => throw new UnsupportedError("This type does not support reflectedTypees");

  List<TypeVariableMirror> get typeVariables => throw new UnimplementedError();
  List<TypeMirror> get typeArguments => throw new UnimplementedError();

  bool get isOriginalDeclaration => true;
  TypeMirror get originalDeclaration => this;
}

class JsLibraryMirror extends JsDeclarationMirror with JsObjectMirror
    implements LibraryMirror {
  final Uri uri;
  final List<String> _classes;
  final List<String> _functions;
  final List _metadata;
  final String _compactFieldSpecification;
  final bool _isRoot;
  final _globalObject;
  List<JsMethodMirror> _cachedFunctionMirrors;
  List<JsVariableMirror> _cachedFields;
  UnmodifiableMapView<Symbol, ClassMirror> _cachedClasses;
  UnmodifiableMapView<Symbol, MethodMirror> _cachedFunctions;
  UnmodifiableMapView<Symbol, MethodMirror> _cachedGetters;
  UnmodifiableMapView<Symbol, MethodMirror> _cachedSetters;
  UnmodifiableMapView<Symbol, VariableMirror> _cachedVariables;
  UnmodifiableMapView<Symbol, Mirror> _cachedMembers;
  UnmodifiableListView<InstanceMirror> _cachedMetadata;

  JsLibraryMirror(Symbol simpleName,
                  this.uri,
                  this._classes,
                  this._functions,
                  this._metadata,
                  this._compactFieldSpecification,
                  this._isRoot,
                  this._globalObject)
      : super(simpleName);

  String get _prettyName => 'LibraryMirror';

  Symbol get qualifiedName => simpleName;

  List<JsMethodMirror> get _methods => _functionMirrors;

  Map<Symbol, ClassMirror> get classes {
    if (_cachedClasses != null) return _cachedClasses;
    var result = new Map();
    for (String className in _classes) {
      var cls = reflectClassByMangledName(className);
      if (cls is JsClassMirror) {
        result[cls.simpleName] = cls;
        cls._owner = this;
      }
    }
    return _cachedClasses =
        new UnmodifiableMapView<Symbol, ClassMirror>(result);
  }

  InstanceMirror setField(Symbol fieldName, Object arg) {
    String name = n(fieldName);
    if (name.endsWith('=')) throw new ArgumentError('');
    var mirror = functions[s('$name=')];
    if (mirror == null) mirror = variables[fieldName];
    if (mirror == null) {
      // TODO(ahe): What receiver to use?
      throw new NoSuchMethodError(this, setterSymbol(fieldName), [arg], null);
    }
    mirror._setField(this, arg);
    return reflect(arg);
  }

  InstanceMirror getField(Symbol fieldName) {
    JsMirror mirror = members[fieldName];
    if (mirror == null) {
      // TODO(ahe): What receiver to use?
      throw new NoSuchMethodError(this, fieldName, [], null);
    }
    return reflect(mirror._getField(this));
  }

  InstanceMirror invoke(Symbol memberName,
                        List positionalArguments,
                        [Map<Symbol, dynamic> namedArguments]) {
    if (namedArguments != null && !namedArguments.isEmpty) {
      throw new UnsupportedError('Named arguments are not implemented.');
    }
    JsDeclarationMirror mirror = members[memberName];
    if (mirror == null) {
      // TODO(ahe): What receiver to use?
      throw new NoSuchMethodError(
          this, memberName, positionalArguments, namedArguments);
    }
    if (mirror is JsMethodMirror) {
      JsMethodMirror method = mirror;
      if (!method.canInvokeReflectively()) {
        throwInvalidReflectionError(n(memberName));
      }
    }
    return reflect(mirror._invoke(positionalArguments, namedArguments));
  }

  _loadField(String name) {
    // TODO(ahe): What about lazily initialized fields? See
    // [JsClassMirror.getField].

    // '$' (JS_CURRENT_ISOLATE()) stores state which is read directly, so we
    // shouldn't use [_globalObject] here.
    assert(JS('bool', '# in #', name, JS_CURRENT_ISOLATE()));
    return JS('', '#[#]', JS_CURRENT_ISOLATE(), name);
  }

  void _storeField(String name, Object arg) {
    // '$' (JS_CURRENT_ISOLATE()) stores state which is stored directly, so we
    // shouldn't use [_globalObject] here.
    assert(JS('bool', '# in #', name, JS_CURRENT_ISOLATE()));
    JS('void', '#[#] = #', JS_CURRENT_ISOLATE(), name, arg);
  }

  List<JsMethodMirror> get _functionMirrors {
    if (_cachedFunctionMirrors != null) return _cachedFunctionMirrors;
    var result = new List<JsMethodMirror>();
    for (int i = 0; i < _functions.length; i++) {
      String name = _functions[i];
      var jsFunction = JS('', '#[#]', _globalObject, name);
      String unmangledName = mangledGlobalNames[name];
      if (unmangledName == null) {
        // If there is no unmangledName, [jsFunction] is either a synthetic
        // implementation detail, or something that is excluded
        // by @MirrorsUsed.
        continue;
      }
      bool isConstructor = unmangledName.startsWith('new ');
      bool isStatic = !isConstructor; // Top-level functions are static, but
                                      // constructors are not.
      if (isConstructor) {
        unmangledName = unmangledName.substring(4).replaceAll(r'$', '.');
      }
      JsMethodMirror mirror =
          new JsMethodMirror.fromUnmangledName(
              unmangledName, jsFunction, isStatic, isConstructor);
      result.add(mirror);
      mirror._owner = this;
    }
    return _cachedFunctionMirrors = result;
  }

  List<VariableMirror> get _fields {
    if (_cachedFields != null) return _cachedFields;
    var result = <VariableMirror>[];
    parseCompactFieldSpecification(
        this, _compactFieldSpecification, true, result);
    return _cachedFields = result;
  }

  Map<Symbol, MethodMirror> get functions {
    if (_cachedFunctions != null) return _cachedFunctions;
    var result = new Map();
    for (JsMethodMirror mirror in _functionMirrors) {
      if (!mirror.isConstructor) result[mirror.simpleName] = mirror;
    }
    return _cachedFunctions =
        new UnmodifiableMapView<Symbol, MethodMirror>(result);
  }

  Map<Symbol, MethodMirror> get getters {
    if (_cachedGetters != null) return _cachedGetters;
    var result = new Map();
    // TODO(ahe): Implement this.
    return _cachedGetters =
        new UnmodifiableMapView<Symbol, MethodMirror>(result);
  }

  Map<Symbol, MethodMirror> get setters {
    if (_cachedSetters != null) return _cachedSetters;
    var result = new Map();
    // TODO(ahe): Implement this.
    return _cachedSetters =
        new UnmodifiableMapView<Symbol, MethodMirror>(result);
  }

  Map<Symbol, VariableMirror> get variables {
    if (_cachedVariables != null) return _cachedVariables;
    var result = new Map();
    for (JsVariableMirror mirror in _fields) {
      result[mirror.simpleName] = mirror;
    }
    return _cachedVariables =
        new UnmodifiableMapView<Symbol, VariableMirror>(result);
  }

  Map<Symbol, Mirror> get members {
    if (_cachedMembers !=  null) return _cachedMembers;
    Map<Symbol, Mirror> result = new Map.from(classes);
    addToResult(Symbol key, Mirror value) {
      result[key] = value;
    }
    functions.forEach(addToResult);
    getters.forEach(addToResult);
    setters.forEach(addToResult);
    variables.forEach(addToResult);
    return _cachedMembers = new UnmodifiableMapView<Symbol, Mirror>(result);
  }

  List<InstanceMirror> get metadata {
    if (_cachedMetadata != null) return _cachedMetadata;
    preserveMetadata();
    return _cachedMetadata =
        new UnmodifiableListView<InstanceMirror>(_metadata.map(reflect));
  }

  // TODO(ahe): Test this getter.
  DeclarationMirror get owner => null;
}

String n(Symbol symbol) => _symbol_dev.Symbol.getName(symbol);

Symbol s(String name) {
  if (name == null) return null;
  return new _symbol_dev.Symbol.unvalidated(name);
}

Symbol setterSymbol(Symbol symbol) => s("${n(symbol)}=");

final JsMirrorSystem currentJsMirrorSystem = new JsMirrorSystem();

InstanceMirror reflect(Object reflectee) {
  if (reflectee is Closure) {
    return new JsClosureMirror(reflectee);
  } else {
    return new JsInstanceMirror(reflectee);
  }
}

TypeMirror reflectType(Type key) {
  return reflectClassByMangledName(getMangledTypeName(key));
}

TypeMirror reflectClassByMangledName(String mangledName) {
  String unmangledName = mangledGlobalNames[mangledName];
  if (unmangledName == null) unmangledName = mangledName;
  return reflectClassByName(s(unmangledName), mangledName);
}

var classMirrors;

TypeMirror reflectClassByName(Symbol symbol, String mangledName) {
  if (classMirrors == null) classMirrors = JsCache.allocate();
  var mirror = JsCache.fetch(classMirrors, mangledName);
  if (mirror != null) return mirror;
  disableTreeShaking();
  int typeArgIndex = mangledName.indexOf("<");
  if (typeArgIndex != -1) {
    mirror = new JsTypeBoundClassMirror(
        reflectClassByMangledName(mangledName.substring(0, typeArgIndex)),
        // Remove the angle brackets enclosing the type arguments.
        mangledName.substring(typeArgIndex + 1, mangledName.length - 1));
    JsCache.update(classMirrors, mangledName, mirror);
    return mirror;
  }
  var constructorOrInterceptor =
      Primitives.getConstructorOrInterceptor(mangledName);
  if (constructorOrInterceptor == null) {
    int index = JS('int|Null', 'init.functionAliases[#]', mangledName);
    if (index != null) {
      mirror = new JsTypedefMirror(
          symbol, mangledName, JS('=Object', 'init.metadata[#]', index));
      JsCache.update(classMirrors, mangledName, mirror);
      return mirror;
    }
    // Probably an intercepted class.
    // TODO(ahe): How to handle intercepted classes?
    throw new UnsupportedError('Cannot find class for: ${n(symbol)}');
  }
  var constructor = (constructorOrInterceptor is Interceptor)
      ? JS('', '#.constructor', constructorOrInterceptor)
      : constructorOrInterceptor;
  var descriptor = JS('', '#["@"]', constructor);
  var fields;
  var fieldsMetadata;
  if (descriptor == null) {
    // This is a native class, or an intercepted class.
    // TODO(ahe): Preserve descriptor for such classes.
  } else {
    fields = JS('', '#[""]', descriptor);
    if (fields is List) {
      fieldsMetadata = fields.getRange(1, fields.length).toList();
      fields = fields[0];
    }
    if (fields is! String) {
      // TODO(ahe): This is CSP mode.  Find a way to determine the
      // fields of this class.
      fields = '';
    }
  }

  var superclassName = fields.split(';')[0];
  var mixins = superclassName.split('+');
  if (mixins.length > 1 && mangledGlobalNames[mangledName] == null) {
    mirror = reflectMixinApplication(mixins, mangledName);
  } else {
    mirror = new JsClassMirror(
        symbol, mangledName, constructorOrInterceptor, fields, fieldsMetadata);
  }

  JsCache.update(classMirrors, mangledName, mirror);
  return mirror;
}

int counter = 0;

ClassMirror reflectMixinApplication(mixinNames, String mangledName) {
  disableTreeShaking();
  var mixins = [];
  for (String mangledName in mixinNames) {
    mixins.add(reflectClassByMangledName(mangledName));
  }
  var it = mixins.iterator;
  it.moveNext();
  var superclass = it.current;
  while (it.moveNext()) {
    superclass = new JsMixinApplication(superclass, it.current, mangledName);
  }
  return superclass;
}

class JsMixinApplication extends JsTypeMirror with JsObjectMirror
    implements ClassMirror {
  final ClassMirror superclass;
  final ClassMirror mixin;
  Symbol _cachedSimpleName;

  JsMixinApplication(ClassMirror superclass, ClassMirror mixin,
                     String mangledName)
      : this.superclass = superclass,
        this.mixin = mixin,
        super(s(mangledName));

  String get _prettyName => 'ClassMirror';

  Symbol get simpleName {
    if (_cachedSimpleName != null) return _cachedSimpleName;
    String superName = n(superclass.qualifiedName);
    return _cachedSimpleName = (superName.contains(' with '))
        ? s('$superName, ${n(mixin.qualifiedName)}')
        : s('$superName with ${n(mixin.qualifiedName)}');
  }

  Symbol get qualifiedName => simpleName;

  Map<Symbol, Mirror> get members => mixin.members;

  Map<Symbol, MethodMirror> get methods => mixin.methods;

  Map<Symbol, MethodMirror> get getters => mixin.getters;

  Map<Symbol, MethodMirror> get setters => mixin.setters;

  Map<Symbol, VariableMirror> get variables => mixin.variables;

  InstanceMirror invoke(
      Symbol memberName,
      List positionalArguments,
      [Map<Symbol,dynamic> namedArguments]) {
    // TODO(ahe): What receiver to use?
    throw new NoSuchMethodError(this, memberName,
                                positionalArguments, namedArguments);
  }

  InstanceMirror getField(Symbol fieldName) {
    // TODO(ahe): What receiver to use?
    throw new NoSuchMethodError(this, fieldName, null, null);
  }

  InstanceMirror setField(Symbol fieldName, Object arg) {
    // TODO(ahe): What receiver to use?
    throw new NoSuchMethodError(this, setterSymbol(fieldName), [arg], null);
  }

  List<ClassMirror> get superinterfaces => [mixin];

  Map<Symbol, MethodMirror> get constructors => mixin.constructors;

  InstanceMirror newInstance(
      Symbol constructorName,
      List positionalArguments,
      [Map<Symbol,dynamic> namedArguments]) {
    throw new UnsupportedError(
        "Can't instantiate mixin application '${n(qualifiedName)}'");
  }

  Future<InstanceMirror> newInstanceAsync(
      Symbol constructorName,
      List positionalArguments,
      [Map<Symbol, dynamic> namedArguments]) {
    return new Future<InstanceMirror>(
        () => this.newInstance(
            constructorName, positionalArguments, namedArguments));
  }

  bool get isOriginalDeclaration => true;

  ClassMirror get originalDeclaration => this;

  // TODO(ahe): Implement this.
  List<TypeVariableMirror> get typeVariables {
    throw new UnimplementedError();
  }

  List<TypeMirror> get typeArguments => new List();
}

abstract class JsObjectMirror implements ObjectMirror {
  Future<InstanceMirror> setFieldAsync(Symbol fieldName, Object value) {
    return new Future<InstanceMirror>(() => this.setField(fieldName, value));
  }

  Future<InstanceMirror> getFieldAsync(Symbol fieldName) {
    return new Future<InstanceMirror>(() => this.getField(fieldName));
  }

  Future<InstanceMirror> invokeAsync(Symbol memberName,
                                     List positionalArguments,
                                     [Map<Symbol, dynamic> namedArguments]) {
    return new Future<InstanceMirror>(
        () => this.invoke(memberName, positionalArguments, namedArguments));
  }
}

class JsInstanceMirror extends JsObjectMirror implements InstanceMirror {
  final reflectee;

  JsInstanceMirror(this.reflectee);

  bool get hasReflectee => true;

  ClassMirror get type => reflectType(reflectee.runtimeType);

  Future<InstanceMirror> invokeAsync(Symbol memberName,
                                     List<Object> positionalArguments,
                                     [Map<Symbol, dynamic> namedArguments]) {
    return
        new Future<InstanceMirror>(
            () => invoke(memberName, positionalArguments, namedArguments));
  }

  InstanceMirror invoke(Symbol memberName,
                        List positionalArguments,
                        [Map<Symbol,dynamic> namedArguments]) {
    String name = n(memberName);
    String reflectiveName;
    if (namedArguments != null && !namedArguments.isEmpty) {
      var methodsWithOptionalArguments =
          JS('=Object', '#.\$methodsWithOptionalArguments', reflectee);
      String mangledName =
          JS('String|Null', '#[#]', methodsWithOptionalArguments, '*$name');
      if (mangledName == null) {
        // TODO(ahe): Invoke noSuchMethod.
        throw new UnimplementedNoSuchMethodError(
            'Invoking noSuchMethod with named arguments not implemented');
      }
      var defaultValueIndices =
          JS('List|Null', '#[#].\$defaultValues', reflectee, mangledName);
      var defaultValues =
          defaultValueIndices.map((int i) => JS('', 'init.metadata[#]', i))
          .iterator;
      var defaultArguments = new Map();
      reflectiveName = mangledNames[mangledName];
      var reflectiveNames = reflectiveName.split(':');
      int requiredPositionalArgumentCount =
          int.parse(reflectiveNames.elementAt(1));
      positionalArguments = new List.from(positionalArguments);
      // Check the number of positional arguments is valid.
      if (requiredPositionalArgumentCount != positionalArguments.length) {
        // TODO(ahe): Invoke noSuchMethod.
        throw new UnimplementedNoSuchMethodError(
            'Invoking noSuchMethod with named arguments not implemented');
      }
      for (String parameter in reflectiveNames.skip(3)) {
        defaultValues.moveNext();
        defaultArguments[parameter] = defaultValues.current;
      }
      namedArguments.forEach((Symbol symbol, value) {
        String parameter = n(symbol);
        if (defaultArguments.containsKey(parameter)) {
          defaultArguments[parameter] = value;
        } else {
          // Extraneous named argument.
          // TODO(ahe): Invoke noSuchMethod.
          throw new UnimplementedNoSuchMethodError(
              'Invoking noSuchMethod with named arguments not implemented');
        }
      });
      positionalArguments.addAll(defaultArguments.values);
    } else {
      reflectiveName =
          JS('String', '# + ":" + # + ":0"', name, positionalArguments.length);
    }
    // We can safely pass positionalArguments to _invoke as it will wrap it in
    // a JSArray if needed.
    return _invoke(memberName, JSInvocationMirror.METHOD, reflectiveName,
                   positionalArguments);
  }

  InstanceMirror _invoke(Symbol name,
                         int type,
                         String reflectiveName,
                         List arguments) {
    String cacheName = Primitives.mirrorInvokeCacheName;
    var cache = JS('', r'#.constructor[#]', reflectee, cacheName);
    if (cache == null) {
      cache = JsCache.allocate();
      JS('void', r'#.constructor[#] = #', reflectee, cacheName, cache);
    }
    var cacheEntry = JsCache.fetch(cache, reflectiveName);
    var result;
    Invocation invocation;
    if (cacheEntry == null) {
      disableTreeShaking();
      String mangledName = reflectiveNames[reflectiveName];
      List<String> argumentNames = const [];
      if (type == JSInvocationMirror.METHOD) {
        // Note: [argumentNames] are not what the user actually provided, it is
        // always all the named paramters.
        argumentNames = reflectiveName.split(':').skip(3).toList();
      }

      // TODO(ahe): We don't need to create an invocation mirror here. The
      // logic from JSInvocationMirror.getCachedInvocation could easily be
      // inlined here.
      invocation = createUnmangledInvocationMirror(
          name, mangledName, type, arguments, argumentNames);

      cacheEntry =
          JSInvocationMirror.getCachedInvocation(invocation, reflectee);
      JsCache.update(cache, reflectiveName, cacheEntry);
    }
    if (cacheEntry.isNoSuchMethod) {
      if (invocation == null) {
        String mangledName = reflectiveNames[reflectiveName];
        // TODO(ahe): Get the argument names.
        List<String> argumentNames = [];
        invocation = createUnmangledInvocationMirror(
            name, mangledName, type, arguments, argumentNames);
      }
      return reflect(cacheEntry.invokeOn(reflectee, invocation));
    } else {
      return reflect(cacheEntry.invokeOn(reflectee, arguments));
    }
  }

  InstanceMirror setField(Symbol fieldName, Object arg) {
    String reflectiveName = '${n(fieldName)}=';
    _invoke(
        s(reflectiveName), JSInvocationMirror.SETTER, reflectiveName, [arg]);
    return reflect(arg);
  }

  InstanceMirror getField(Symbol fieldName) {
    String reflectiveName = n(fieldName);
    return _invoke(fieldName, JSInvocationMirror.GETTER, reflectiveName, []);
  }

  delegate(Invocation invocation) {
    return JSInvocationMirror.invokeFromMirror(invocation, reflectee);
  }

  operator ==(other) {
    return other is JsInstanceMirror &&
           identical(reflectee, other.reflectee);
  }

  int get hashCode {
    // Avoid hash collisions with the reflectee. This constant is in Smi range
    // and happens to be the inner padding from RFC 2104.
    return identityHashCode(reflectee) ^ 0x36363636;
  }

  String toString() => 'InstanceMirror on ${Error.safeToString(reflectee)}';

  // TODO(ahe): Remove this method from the API.
  MirrorSystem get mirrors => currentJsMirrorSystem;
}

/**
 * ClassMirror for generic classes where the type parameters are bound.
 *
 * [typeArguments] will return a list of the type arguments, in constrast
 * to JsCLassMirror that returns an empty list since it represents original
 * declarations and classes that are not generic.
 */
class JsTypeBoundClassMirror implements ClassMirror {
  final JsClassMirror _class;

  /**
   * When instantiated this field will hold a string representing the list of
   * type arguments for the class, i.e. what is inside the outermost angle
   * brackets. Then, when get typeArguments is called the first time, the string
   * is parsed into the actual list of TypeMirrors, and the field is overridden
   * with this value.
   */
  var _typeArgs;

  JsTypeBoundClassMirror(this._class, this._typeArgs);

  List<TypeVariableMirror> get typeVariables => _class.typeVariables;

  List<TypeMirror> get typeArguments {
    if (_typeArgs is! String) return _typeArgs;
    List result = new List();

    if (_typeArgs.indexOf('<') == -1) {
      for (String s in _typeArgs.split(',')) {
        result.add(reflectClassByMangledName(s.trim()));
      }
    } else {
      int level = 0;
      StringBuffer currentTypeArg = new StringBuffer();

      addCurrentTypeArg() {
        var classMirror = reflectClassByMangledName(currentTypeArg.toString());
        result.add(classMirror);
        currentTypeArg.clear();
      }

      for (int i = 0; i < _typeArgs.length; i++) {
        var character = _typeArgs[i];
        if (character == ' ') {
          continue;
        } else if (character == '<') {
          currentTypeArg.write(character);
          level++;
        } else if (character == '>') {
          currentTypeArg.write(character);
          level--;
        } else if (character == ',') {
          if (level > 0) {
            currentTypeArg.write(character);
          } else {
            addCurrentTypeArg();
          }
        } else {
          currentTypeArg.write(character);
        }
      }
      addCurrentTypeArg();
    }
    return _typeArgs = new UnmodifiableListView(result);
  }

  Map<Symbol, MethodMirror> get constructors => _class.constructors;

  Map<Symbol, MethodMirror> get methods => _class.methods;

  Map<Symbol, MethodMirror> get getters => _class.getters;

  Map<Symbol, MethodMirror> get setters => _class.setters;

  Map<Symbol, VariableMirror> get variables => _class.variables;

  Map<Symbol, Mirror> get members => _class.members;

  InstanceMirror setField(Symbol fieldName, Object arg) {
    return _class.setField(fieldName, arg);
  }

  InstanceMirror getField(Symbol fieldName) => _class.getField(fieldName);

  InstanceMirror newInstance(Symbol constructorName,
                             List positionalArguments,
                             [Map<Symbol, dynamic> namedArguments]) {
    return _class.newInstance(constructorName,
                              positionalArguments,
                              namedArguments);
  }

  Future<InstanceMirror> newInstanceAsync(
      Symbol constructorName,
      List positionalArguments,
      [Map<Symbol, dynamic> namedArguments]) {
    return _class.newInstanceAsync(constructorName,
                                   positionalArguments,
                                   namedArguments);
  }

  JsLibraryMirror get owner => _class.owner;

  List<InstanceMirror> get metadata => _class.metadata;

  ClassMirror get superclass => _class.superclass;

  InstanceMirror invoke(Symbol memberName,
                        List positionalArguments,
                        [Map<Symbol,dynamic> namedArguments]) {
    return _class.invoke(memberName, positionalArguments, namedArguments);
  }

  bool get isOriginalDeclaration => false;

  ClassMirror get originalDeclaration => _class;

  List<ClassMirror> get superinterfaces => _class.superinterfaces;

  Future<InstanceMirror> getFieldAsync(Symbol fieldName) {
    return _class.getFieldAsync(fieldName);
  }

  bool get hasReflectedType => _class.hasReflectedType;

  Future<InstanceMirror> invokeAsync(Symbol memberName,
                                     List positionalArguments,
                                     [Map<Symbol, dynamic> namedArguments]) {
    return _class.invokeAsync(memberName, positionalArguments, namedArguments);
  }

  bool get isPrivate => _class.isPrivate;

  bool get isTopLevel => _class.isTopLevel;

  SourceLocation get location => _class.location;

  MirrorSystem get mirrors => _class.mirrors;

  Symbol get qualifiedName => _class.qualifiedName;

  Type get reflectedType => _class.reflectedType;

  Future<InstanceMirror> setFieldAsync(Symbol fieldName, Object value) {
    return _class.setFieldAsync(fieldName, value);
  }

  Symbol get simpleName => _class.simpleName;
}

class JsClassMirror extends JsTypeMirror with JsObjectMirror
    implements ClassMirror {
  final String _mangledName;
  final _jsConstructorOrInterceptor;
  final String _fieldsDescriptor;
  final List _fieldsMetadata;
  final _jsConstructorCache = JsCache.allocate();
  List _metadata;
  ClassMirror _superclass;
  List<JsMethodMirror> _cachedMethods;
  List<JsVariableMirror> _cachedFields;
  UnmodifiableMapView<Symbol, MethodMirror> _cachedConstructors;
  UnmodifiableMapView<Symbol, MethodMirror> _cachedMethodsMap;
  UnmodifiableMapView<Symbol, MethodMirror> _cachedGetters;
  UnmodifiableMapView<Symbol, MethodMirror> _cachedSetters;
  UnmodifiableMapView<Symbol, VariableMirror> _cachedVariables;
  UnmodifiableMapView<Symbol, Mirror> _cachedMembers;
  UnmodifiableListView<InstanceMirror> _cachedMetadata;
  UnmodifiableListView<ClassMirror> _cachedSuperinterfaces;
  UnmodifiableListView<TypeVariableMirror> _cachedTypeVariables;

  // Set as side-effect of accessing JsLibraryMirror.classes.
  JsLibraryMirror _owner;

  JsClassMirror(Symbol simpleName,
                this._mangledName,
                this._jsConstructorOrInterceptor,
                this._fieldsDescriptor,
                this._fieldsMetadata)
      : super(simpleName);

  String get _prettyName => 'ClassMirror';

  get _jsConstructor {
    if (_jsConstructorOrInterceptor is Interceptor) {
      return JS('', '#.constructor', _jsConstructorOrInterceptor);
    } else {
      return _jsConstructorOrInterceptor;
    }
  }

  Map<Symbol, MethodMirror> get constructors {
    if (_cachedConstructors != null) return _cachedConstructors;
    var result = new Map();
    for (JsMethodMirror method in _methods) {
      if (method.isConstructor) {
        result[method.simpleName] = method;
      }
    }
    return _cachedConstructors =
        new UnmodifiableMapView<Symbol, MethodMirror>(result);
  }

  List<JsMethodMirror> get _methods {
    if (_cachedMethods != null) return _cachedMethods;
    var prototype = JS('', '#.prototype', _jsConstructor);
    List<String> keys = extractKeys(prototype);
    var result = <JsMethodMirror>[];
    for (String key in keys) {
      if (isReflectiveDataInPrototype(key)) continue;
      String simpleName = mangledNames[key];
      // [simpleName] can be null if [key] represents an implementation
      // detail, for example, a bailout method, or runtime type support.
      // It might also be null if the user has limited what is reified for
      // reflection with metadata.
      if (simpleName == null) continue;
      var function = JS('', '#[#]', prototype, key);
      var mirror =
          new JsMethodMirror.fromUnmangledName(
              simpleName, function, false, false);
      result.add(mirror);
      mirror._owner = this;
    }

    keys = extractKeys(JS('', 'init.statics[#]', _mangledName));
    int length = keys.length;
    for (int i = 0; i < length; i++) {
      String mangledName = keys[i];
      if (isReflectiveDataInPrototype(mangledName)) continue;
      String unmangledName = mangledName;
      var jsFunction = JS('', '#[#]', owner._globalObject, mangledName);

      bool isConstructor = false;
      if (i + 1 < length) {
        String reflectionName = keys[i + 1];
        if (reflectionName.startsWith('+')) {
          i++;
          reflectionName = reflectionName.substring(1);
          isConstructor = reflectionName.startsWith('new ');
          if (isConstructor) {
            reflectionName = reflectionName.substring(4).replaceAll(r'$', '.');
          }
        }
        unmangledName = reflectionName;
      }
      bool isStatic = !isConstructor; // Constructors are not static.
      JsMethodMirror mirror =
          new JsMethodMirror.fromUnmangledName(
              unmangledName, jsFunction, isStatic, isConstructor);
      result.add(mirror);
      mirror._owner = this;
    }

    return _cachedMethods = result;
  }

  List<VariableMirror> get _fields {
    if (_cachedFields != null) return _cachedFields;
    var result = <VariableMirror>[];

    var instanceFieldSpecfication = _fieldsDescriptor.split(';')[1];
    if (_fieldsMetadata != null) {
      instanceFieldSpecfication =
          [instanceFieldSpecfication]..addAll(_fieldsMetadata);
    }
    parseCompactFieldSpecification(
        this, instanceFieldSpecfication, false, result);

    var staticDescriptor = JS('', 'init.statics[#]', _mangledName);
    if (staticDescriptor != null) {
      parseCompactFieldSpecification(
          this, JS('', '#[""]', staticDescriptor), true, result);
    }
    _cachedFields = result;
    return _cachedFields;
  }

  Map<Symbol, MethodMirror> get methods {
    if (_cachedMethodsMap != null) return _cachedMethodsMap;
    var result = new Map();
    for (JsMethodMirror method in _methods) {
      if (!method.isConstructor && !method.isGetter && !method.isSetter) {
        result[method.simpleName] = method;
      }
    }
    return _cachedMethodsMap =
        new UnmodifiableMapView<Symbol, MethodMirror>(result);
  }

  Map<Symbol, MethodMirror> get getters {
    if (_cachedGetters != null) return _cachedGetters;
    // TODO(ahe): This is a hack to remove getters corresponding to a field.
    var fields = variables;

    var result = new Map();
    for (JsMethodMirror method in _methods) {
      if (method.isGetter) {

        // TODO(ahe): This is a hack to remove getters corresponding to a field.
        if (fields[method.simpleName] != null) continue;

        result[method.simpleName] = method;
      }
    }
    return _cachedGetters =
        new UnmodifiableMapView<Symbol, MethodMirror>(result);
  }

  Map<Symbol, MethodMirror> get setters {
    if (_cachedSetters != null) return _cachedSetters;
    // TODO(ahe): This is a hack to remove setters corresponding to a field.
    var fields = variables;

    var result = new Map();
    for (JsMethodMirror method in _methods) {
      if (method.isSetter) {

        // TODO(ahe): This is a hack to remove setters corresponding to a field.
        String name = n(method.simpleName);
        name = name.substring(0, name.length - 1); // Remove '='.
        if (fields[s(name)] != null) continue;

        result[method.simpleName] = method;
      }
    }
    return _cachedSetters =
        new UnmodifiableMapView<Symbol, MethodMirror>(result);
  }

  Map<Symbol, VariableMirror> get variables {
    if (_cachedVariables != null) return _cachedVariables;
    var result = new Map();
    for (JsVariableMirror mirror in _fields) {
      result[mirror.simpleName] = mirror;
    }
    return _cachedVariables =
        new UnmodifiableMapView<Symbol, VariableMirror>(result);
  }

  Map<Symbol, Mirror> get members {
    if (_cachedMembers != null) return _cachedMembers;
    Map<Symbol, Mirror> result = new Map.from(variables);
    for (JsMethodMirror method in _methods) {
      if (method.isSetter) {
        String name = n(method.simpleName);
        name = name.substring(0, name.length - 1);
        // Filter-out setters corresponding to variables.
        if (result[s(name)] is VariableMirror) continue;
      }
      // Constructors aren't 'members'.
      if (method.isConstructor) continue;
      // Use putIfAbsent to filter-out getters corresponding to variables.
      result.putIfAbsent(method.simpleName, () => method);
    }
    return _cachedMembers = new UnmodifiableMapView<Symbol, Mirror>(result);
  }

  InstanceMirror setField(Symbol fieldName, Object arg) {
    JsVariableMirror mirror = variables[fieldName];
    if (mirror != null && mirror.isStatic && !mirror.isFinal) {
      // '$' (JS_CURRENT_ISOLATE()) stores state which is stored directly, so
      // we shouldn't use [JsLibraryMirror._globalObject] here.
      String jsName = mirror._jsName;
      if (!JS('bool', '# in #', jsName, JS_CURRENT_ISOLATE())) {
        throw new RuntimeError('Cannot find "$jsName" in current isolate.');
      }
      JS('void', '#[#] = #', JS_CURRENT_ISOLATE(), jsName, arg);
      return reflect(arg);
    }
    // TODO(ahe): What receiver to use?
    throw new NoSuchMethodError(this, setterSymbol(fieldName), [arg], null);
  }

  InstanceMirror getField(Symbol fieldName) {
    JsVariableMirror mirror = variables[fieldName];
    if (mirror != null && mirror.isStatic) {
      String jsName = mirror._jsName;
      // '$' (JS_CURRENT_ISOLATE()) stores state which is read directly, so
      // we shouldn't use [JsLibraryMirror._globalObject] here.
      if (!JS('bool', '# in #', jsName, JS_CURRENT_ISOLATE())) {
        throw new RuntimeError('Cannot find "$jsName" in current isolate.');
      }
      if (JS('bool', '# in init.lazies', jsName)) {
        String getterName = JS('String', 'init.lazies[#]', jsName);
        return reflect(JS('', '#[#]()', JS_CURRENT_ISOLATE(), getterName));
      } else {
        return reflect(JS('', '#[#]', JS_CURRENT_ISOLATE(), jsName));
      }
    }
    // TODO(ahe): What receiver to use?
    throw new NoSuchMethodError(this, fieldName, null, null);
  }

  InstanceMirror newInstance(Symbol constructorName,
                             List positionalArguments,
                             [Map<Symbol, dynamic> namedArguments]) {
    if (namedArguments != null && !namedArguments.isEmpty) {
      throw new UnsupportedError('Named arguments are not implemented.');
    }
    JsMethodMirror mirror =
        JsCache.fetch(_jsConstructorCache, n(constructorName));
    if (mirror == null) {
      mirror = constructors.values.firstWhere(
          (m) => m.constructorName == constructorName,
          orElse: () {
            // TODO(ahe): What receiver to use?
            throw new NoSuchMethodError(
                this, constructorName, positionalArguments, namedArguments);
          });
      JsCache.update(_jsConstructorCache, n(constructorName), mirror);
    }
    return reflect(mirror._invoke(positionalArguments, namedArguments));
  }

  Future<InstanceMirror> newInstanceAsync(
      Symbol constructorName,
      List positionalArguments,
      [Map<Symbol, dynamic> namedArguments]) {
    if (namedArguments != null && !namedArguments.isEmpty) {
      throw new UnsupportedError('Named arguments are not implemented.');
    }
    return new Future<InstanceMirror>(
        () => newInstance(
            constructorName, positionalArguments, namedArguments));
  }

  JsLibraryMirror get owner {
    if (_owner == null) {
      if (_jsConstructorOrInterceptor is Interceptor) {
        _owner = reflectType(Object).owner;
      } else {
        for (var list in JsMirrorSystem.librariesByName.values) {
          for (JsLibraryMirror library in list) {
            // This will set _owner field on all clasess as a side
            // effect.  This gives us a fast path to reflect on a
            // class without parsing reflection data.
            library.classes;
          }
        }
      }
      if (_owner == null) {
        throw new StateError('Class "${n(simpleName)}" has no owner');
      }
    }
    return _owner;
  }

  List<InstanceMirror> get metadata {
    if (_cachedMetadata != null) return _cachedMetadata;
    if (_metadata == null) {
      _metadata = extractMetadata(JS('', '#.prototype', _jsConstructor));
    }
    return _cachedMetadata =
        new UnmodifiableListView<InstanceMirror>(_metadata.map(reflect));
  }

  ClassMirror get superclass {
    if (_superclass == null) {
      var superclassName = _fieldsDescriptor.split(';')[0];
      var mixins = superclassName.split('+');
      if (mixins.length > 1) {
        if (mixins.length != 2) {
          throw new RuntimeError('Strange mixin: $_fieldsDescriptor');
        }
        _superclass = reflectClassByMangledName(mixins[0]);
      } else {
        // Use _superclass == this to represent class with no superclass (Object).
        _superclass = (superclassName == '')
            ? this : reflectClassByMangledName(superclassName);
      }
    }
    return _superclass == this ? null : _superclass;
  }

  InstanceMirror invoke(Symbol memberName,
                        List positionalArguments,
                        [Map<Symbol,dynamic> namedArguments]) {
    // Mirror API gotcha: Calling [invoke] on a ClassMirror means invoke a
    // static method.

    if (namedArguments != null && !namedArguments.isEmpty) {
      throw new UnsupportedError('Named arguments are not implemented.');
    }
    JsMethodMirror mirror = methods[memberName];
    if (mirror == null || !mirror.isStatic) {
      // TODO(ahe): What receiver to use?
      throw new NoSuchMethodError(
          this, memberName, positionalArguments, namedArguments);
    }
    if (!mirror.canInvokeReflectively()) {
      throwInvalidReflectionError(n(memberName));
    }
    return reflect(mirror._invoke(positionalArguments, namedArguments));
  }

  bool get isOriginalDeclaration => true;

  ClassMirror get originalDeclaration => this;

  List<ClassMirror> get superinterfaces {
    if (_cachedSuperinterfaces != null) return _cachedSuperinterfaces;
    List<int> interfaces = JS('List|Null', 'init.interfaces[#]', _mangledName);
    var result = const [];
    if (interfaces != null) {
      ClassMirror lookupType(int i) {
        var type = JS('=Object', 'init.metadata[#]', i);
        return typeMirrorFromRuntimeTypeRepresentation(type);
      }
      result = interfaces.map(lookupType).toList();
    }
    return _cachedSuperinterfaces =
        new UnmodifiableListView<ClassMirror>(result);
  }

  List<TypeVariableMirror> get typeVariables {
   if (_cachedTypeVariables != null) return _cachedTypeVariables;
   List result = new List();
   List typeVars =
        JS('JSExtendableArray|Null', '#.prototype["<>"]', _jsConstructor);
    if (typeVars == null) return result;
    for (int i = 0; i < typeVars.length; i++) {
      TypeVariable typeVariable = JS('', 'init.metadata[#]', typeVars[i]);
      result.add(new JsTypeVariableMirror(typeVariable, this));
    }
    return _cachedTypeVariables = new UnmodifiableListView(result);
  }

  List<TypeMirror> get typeArguments => new List();
}

class JsVariableMirror extends JsDeclarationMirror implements VariableMirror {
  static final int REFLECTION_MARKER = 45;

  // TODO(ahe): The values in these fields are virtually untested.
  final String _jsName;
  final bool isFinal;
  final bool isStatic;
  final _metadataFunction;
  final DeclarationMirror _owner;
  List _metadata;

  JsVariableMirror(Symbol simpleName,
                   this._jsName,
                   this.isFinal,
                   this.isStatic,
                   this._metadataFunction,
                   this._owner)
      : super(simpleName);

  factory JsVariableMirror.from(String descriptor,
                                metadataFunction,
                                JsDeclarationMirror owner,
                                bool isStatic) {
    int length = descriptor.length;
    var code = fieldCode(descriptor.codeUnitAt(length - 1));
    if (code == REFLECTION_MARKER) {
      // If the field descriptor has a reflection marker, remove it by
      // changing length and getting the real getter/setter code.  The
      // descriptor will be truncated below.
      length--;
      code = fieldCode(descriptor.codeUnitAt(length - 1));
    } else {
      // The field is not available for reflection.
      return null;
    }
    bool isFinal = false;
    if (code == 0) return null; // Inherited field.
    bool hasGetter = (code & 3) != 0;
    bool hasSetter = (code >> 2) != 0;
    isFinal = !hasSetter;
    length--;
    String jsName;
    String accessorName = jsName = descriptor.substring(0, length);
    int divider = descriptor.indexOf(':');
    if (divider > 0) {
      accessorName = accessorName.substring(0, divider);
      jsName = descriptor.substring(divider + 1);
    }
    var unmangledName;
    if (isStatic) {
      unmangledName = mangledGlobalNames[accessorName];
    } else {
      String getterPrefix = JS_GET_NAME('GETTER_PREFIX');
      unmangledName = mangledNames['$getterPrefix$accessorName'];
    }
    if (unmangledName == null) unmangledName = accessorName;
    if (!hasSetter) {
      // TODO(ahe): This is a hack to handle checked setters in checked mode.
      var setterName = s('$unmangledName=');
      for (JsMethodMirror method in owner._methods) {
        if (method.simpleName == setterName) {
          isFinal = false;
          break;
        }
      }
    }
    return new JsVariableMirror(
        s(unmangledName), jsName, isFinal, isStatic, metadataFunction, owner);
  }

  String get _prettyName => 'VariableMirror';

  // TODO(ahe): Improve this information and test it.
  TypeMirror get type => JsMirrorSystem._dynamicType;

  DeclarationMirror get owner => _owner;

  List<InstanceMirror> get metadata {
    preserveMetadata();
    if (_metadata == null) {
      _metadata = (_metadataFunction == null)
          ? const [] : JS('', '#()', _metadataFunction);
    }
    return _metadata.map(reflect).toList();
  }

  static int fieldCode(int code) {
    if (code == REFLECTION_MARKER) return code;
    if (code >= 60 && code <= 64) return code - 59;
    if (code >= 123 && code <= 126) return code - 117;
    if (code >= 37 && code <= 43) return code - 27;
    return 0;
  }

  _getField(JsMirror receiver) => receiver._loadField(_jsName);

  void _setField(JsMirror receiver, Object arg) {
    if (isFinal) {
      throw new NoSuchMethodError(this, setterSymbol(simpleName), [arg], null);
    }
    receiver._storeField(_jsName, arg);
  }
}

class JsClosureMirror extends JsInstanceMirror implements ClosureMirror {
  JsClosureMirror(reflectee)
      : super(reflectee);

  MethodMirror get function {
    String cacheName = Primitives.mirrorFunctionCacheName;
    JsMethodMirror cachedFunction =
        JS('JsMethodMirror|Null', r'#.constructor[#]', reflectee, cacheName);
    if (cachedFunction != null) return cachedFunction;
    disableTreeShaking();
    // TODO(ahe): What about optional parameters (named or not).
    var extractCallName = JS('', r'''
function(reflectee) {
  for (var property in reflectee) {
    if ("call$" == property.substring(0, 5)) return property;
  }
  return null;
}
''');
    String callName = JS('String|Null', '#(#)', extractCallName, reflectee);
    if (callName == null) {
      throw new RuntimeError('Cannot find callName on "$reflectee"');
    }
    int parameterCount = int.parse(callName.split(r'$')[1]);
    if (reflectee is BoundClosure) {
      var target = BoundClosure.targetOf(reflectee);
      var self = BoundClosure.selfOf(reflectee);
      var name = mangledNames[BoundClosure.nameOf(reflectee)];
      if (name == null) {
        throwInvalidReflectionError(name);
      }
      cachedFunction = new JsMethodMirror.fromUnmangledName(
          name, target, false, false);
    } else {
      bool isStatic = true; // TODO(ahe): Compute isStatic correctly.
      var jsFunction = JS('', '#[#]', reflectee, callName);
      cachedFunction = new JsMethodMirror(
          s(callName), jsFunction, parameterCount,
          false, false, isStatic, false, false);
    }
    JS('void', r'#.constructor[#] = #', reflectee, cacheName, cachedFunction);
    return cachedFunction;
  }

  InstanceMirror apply(List positionalArguments,
                       [Map<Symbol, dynamic> namedArguments]) {
    return reflect(
        Function.apply(reflectee, positionalArguments, namedArguments));
  }

  Future<InstanceMirror> applyAsync(List positionalArguments,
                                    [Map<Symbol, dynamic> namedArguments]) {
    return new Future<InstanceMirror>(
        () => apply(positionalArguments, namedArguments));
  }

  String toString() => "ClosureMirror on '${Error.safeToString(reflectee)}'";

  // TODO(ahe): Implement these.
  String get source => throw new UnimplementedError();
  Future<InstanceMirror> findInContext(Symbol name)
      => throw new UnimplementedError();
}

class JsMethodMirror extends JsDeclarationMirror implements MethodMirror {
  final _jsFunction;
  final int _parameterCount;
  final bool isGetter;
  final bool isSetter;
  final bool isStatic;
  final bool isConstructor;
  final bool isOperator;
  DeclarationMirror _owner;
  List _metadata;
  var _returnType;
  UnmodifiableListView<ParameterMirror> _parameters;

  JsMethodMirror(Symbol simpleName,
                 this._jsFunction,
                 this._parameterCount,
                 this.isGetter,
                 this.isSetter,
                 this.isStatic,
                 this.isConstructor,
                 this.isOperator)
      : super(simpleName);

  factory JsMethodMirror.fromUnmangledName(String name,
                                           jsFunction,
                                           bool isStatic,
                                           bool isConstructor) {
    List<String> info = name.split(':');
    name = info[0];
    bool isOperator = isOperatorName(name);
    bool isSetter = !isOperator && name.endsWith('=');
    int requiredParameterCount = 0;
    int optionalParameterCount = 0;
    bool isGetter = false;
    if (info.length == 1) {
      if (isSetter) {
        requiredParameterCount = 1;
      } else {
        isGetter = true;
        requiredParameterCount = 0;
      }
    } else {
      requiredParameterCount = int.parse(info[1]);
      optionalParameterCount = int.parse(info[2]);
    }
    return new JsMethodMirror(
        s(name), jsFunction, requiredParameterCount + optionalParameterCount,
        isGetter, isSetter, isStatic, isConstructor, isOperator);
  }

  String get _prettyName => 'MethodMirror';

  List<ParameterMirror> get parameters {
    if (_parameters != null) return _parameters;
    metadata; // Compute _parameters as a side-effect of extracting metadata.
    return _parameters;
  }

  bool canInvokeReflectively() {
    return hasReflectableProperty(_jsFunction);
  }

  DeclarationMirror get owner => _owner;

  TypeMirror get returnType {
    metadata; // Compute _returnType as a side-effect of extracting metadata.
    return typeMirrorFromRuntimeTypeRepresentation(_returnType);
  }

  List<InstanceMirror> get metadata {
    if (_metadata == null) {
      var raw = extractMetadata(_jsFunction);
      var formals = new List(_parameterCount);
      if (!raw.isEmpty) {
        _returnType = raw[0];
        int parameterLength = 1 + _parameterCount * 2;
        int formalsCount = 0;
        for (int i = 1; i < parameterLength; i += 2) {
          var name = raw[i];
          var type = raw[i + 1];
          formals[formalsCount++] = new JsParameterMirror(name, this, type);
        }
        raw = raw.sublist(parameterLength);
      } else {
        for (int i = 0; i < _parameterCount; i++) {
          formals[i] = new JsParameterMirror('argument$i', this, null);
        }
      }
      _parameters = new UnmodifiableListView<ParameterMirror>(formals);
      _metadata = new UnmodifiableListView(raw.map(reflect));
    }
    return _metadata;
  }

  Symbol get constructorName {
    // TODO(ahe): I believe it is more appropriate to throw an exception or
    // return null.
    if (!isConstructor) return const Symbol('');
    String name = n(simpleName);
    int index = name.indexOf('.');
    if (index == -1) return const Symbol('');
    return s(name.substring(index + 1));
  }

  _invoke(List positionalArguments, Map<Symbol, dynamic> namedArguments) {
    if (namedArguments != null && !namedArguments.isEmpty) {
      throw new UnsupportedError('Named arguments are not implemented.');
    }
    if (!isStatic && !isConstructor) {
      throw new RuntimeError('Cannot invoke instance method without receiver.');
    }
    if (_parameterCount != positionalArguments.length || _jsFunction == null) {
      // TODO(ahe): What receiver to use?
      throw new NoSuchMethodError(
          owner, simpleName, positionalArguments, namedArguments);
    }
    // Using JS_CURRENT_ISOLATE() ('$') here is actually correct, although
    // _jsFunction may not be a property of '$', most static functions do not
    // care who their receiver is. But to lazy getters, it is important that
    // 'this' is '$'.
    return JS('', r'#.apply(#, #)', _jsFunction, JS_CURRENT_ISOLATE(),
              new List.from(positionalArguments));
  }

  _getField(JsMirror receiver) {
    if (isGetter) {
      return _invoke([], null);
    } else {
      // TODO(ahe): Closurize method.
      throw new UnimplementedError('getField on $receiver');
    }
  }

  _setField(JsMirror receiver, Object arg) {
    if (isSetter) {
      return _invoke([arg], null);
    } else {
      throw new NoSuchMethodError(this, setterSymbol(simpleName), [], null);
    }
  }

  // Abstract methods are tree-shaken away.
  bool get isAbstract => false;

  // TODO(ahe): Test this.
  bool get isRegularMethod => !isGetter && !isSetter && !isConstructor;

  // TODO(ahe): Implement these.
  bool get isConstConstructor => throw new UnimplementedError();
  bool get isGenerativeConstructor => throw new UnimplementedError();
  bool get isRedirectingConstructor => throw new UnimplementedError();
  bool get isFactoryConstructor => throw new UnimplementedError();
}

class JsParameterMirror extends JsDeclarationMirror implements ParameterMirror {
  final DeclarationMirror owner;
  // A JS object representing the type.
  final _type;

  JsParameterMirror(String unmangledName, this.owner, this._type)
      : super(s(unmangledName));

  String get _prettyName => 'ParameterMirror';

  TypeMirror get type => typeMirrorFromRuntimeTypeRepresentation(_type);

  // Only true for static fields, never for a parameter.
  bool get isStatic => false;

  // TODO(ahe): Implement this.
  bool get isFinal => false;

  // TODO(ahe): Implement this.
  bool get isOptional => false;

  // TODO(ahe): Implement this.
  bool get isNamed => false;

  // TODO(ahe): Implement this.
  bool get hasDefaultValue => false;

  // TODO(ahe): Implement this.
  get defaultValue => null;

  // TODO(ahe): Implement this.
  List<InstanceMirror> get metadata => throw new UnimplementedError();
}

class JsTypedefMirror extends JsDeclarationMirror implements TypedefMirror {
  final String _mangledName;
  final JsFunctionTypeMirror referent;

  JsTypedefMirror(Symbol simpleName,  this._mangledName, _typeData)
      : referent = new JsFunctionTypeMirror(_typeData),
        super(simpleName);

  JsFunctionTypeMirror get value => referent;

  String get _prettyName => 'TypedefMirror';
}

class JsFunctionTypeMirror implements FunctionTypeMirror {
  final _typeData;
  String _cachedToString;
  TypeMirror _cachedReturnType;
  UnmodifiableListView<ParameterMirror> _cachedParameters;

  JsFunctionTypeMirror(this._typeData);

  bool get _hasReturnType => JS('bool', '"ret" in #', _typeData);
  get _returnType => JS('', '#.ret', _typeData);

  bool get _isVoid => JS('bool', '!!#.void', _typeData);

  bool get _hasArguments => JS('bool', '"args" in #', _typeData);
  List get _arguments => JS('JSExtendableArray', '#.args', _typeData);

  bool get _hasOptionalArguments => JS('bool', '"opt" in #', _typeData);
  List get _optionalArguments => JS('JSExtendableArray', '#.opt', _typeData);

  bool get _hasNamedArguments => JS('bool', '"named" in #', _typeData);
  get _namedArguments => JS('=Object', '#.named', _typeData);

  TypeMirror get returnType {
    if (_cachedReturnType != null) return _cachedReturnType;
    if (_isVoid) return _cachedReturnType = JsMirrorSystem._voidType;
    if (!_hasReturnType) return _cachedReturnType = JsMirrorSystem._dynamicType;
    return _cachedReturnType =
        typeMirrorFromRuntimeTypeRepresentation(_returnType);
  }

  List<ParameterMirror> get parameters {
    if (_cachedParameters != null) return _cachedParameters;
    List result = [];
    int parameterCount = 0;
    if (_hasArguments) {
      for (var type in _arguments) {
        result.add(
            new JsParameterMirror('argument${parameterCount++}', this, type));
      }
    }
    if (_hasOptionalArguments) {
      for (var type in _optionalArguments) {
        result.add(
            new JsParameterMirror('argument${parameterCount++}', this, type));
      }
    }
    if (_hasNamedArguments) {
      for (var name in extractKeys(_namedArguments)) {
        var type = JS('', '#[#]', _namedArguments, name);
        result.add(new JsParameterMirror(name, this, type));
      }
    }
    return _cachedParameters = new UnmodifiableListView<ParameterMirror>(
        result);
  }

  String toString() {
    if (_cachedToString != null) return _cachedToString;
    var s = "FunctionTypeMirror on '(";
    var sep = '';
    if (_hasArguments) {
      for (var argument in _arguments) {
        s += sep;
        s += runtimeTypeToString(argument);
        sep = ', ';
      }
    }
    if (_hasOptionalArguments) {
      s += '$sep[';
      sep = '';
      for (var argument in _optionalArguments) {
        s += sep;
        s += runtimeTypeToString(argument);
        sep = ', ';
      }
      s += ']';
    }
    if (_hasNamedArguments) {
      s += '$sep{';
      sep = '';
      for (var name in extractKeys(_namedArguments)) {
        s += sep;
        s += '$name: ';
        s += runtimeTypeToString(JS('', '#[#]', _namedArguments, name));
        sep = ', ';
      }
      s += '}';
    }
    s += ') -> ';
    if (_isVoid) {
      s += 'void';
    } else if (_hasReturnType) {
      s += runtimeTypeToString(_returnType);
    } else {
      s += 'dynamic';
    }
    return _cachedToString = "$s'";
  }
}

TypeMirror typeMirrorFromRuntimeTypeRepresentation(type) {
  if (type == null) return JsMirrorSystem._dynamicType;
  String representation = runtimeTypeToString(type);
  if (representation == null) return reflectClass(Function);
  return reflectClass(createRuntimeType(representation));
}

Symbol computeQualifiedName(DeclarationMirror owner, Symbol simpleName) {
  if (owner == null) return simpleName;
  String ownerName = n(owner.qualifiedName);
  if (ownerName == '') return simpleName;
  return s('$ownerName.${n(simpleName)}');
}

List extractMetadata(victim) {
  preserveMetadata();
  var metadataFunction = JS('', '#["@"]', victim);
  if (metadataFunction != null) return JS('', '#()', metadataFunction);
  if (JS('String', 'typeof #', victim) != 'function') return const [];
  String source = JS('String', 'Function.prototype.toString.call(#)', victim);
  int index = source.lastIndexOf(new RegExp('"[0-9,]*";?[ \n\r]*}'));
  if (index == -1) return const [];
  index++;
  int endQuote = source.indexOf('"', index);
  return source.substring(index, endQuote).split(',').map(int.parse).map(
      (int i) => JS('', 'init.metadata[#]', i)).toList();
}

List<JsVariableMirror> parseCompactFieldSpecification(
    JsDeclarationMirror owner,
    fieldSpecification,
    bool isStatic,
    List<Mirror> result) {
  List fieldsMetadata = null;
  List<String> fieldNames;
  if (fieldSpecification is List) {
    fieldNames = splitFields(fieldSpecification[0], ',');
    fieldsMetadata = fieldSpecification.sublist(1);
  } else if (fieldSpecification is String) {
    fieldNames = splitFields(fieldSpecification, ',');
  } else {
    fieldNames = [];
  }
  int fieldNumber = 0;
  for (String field in fieldNames) {
    var metadata;
    if (fieldsMetadata != null) {
      metadata = fieldsMetadata[fieldNumber++];
    }
    var mirror = new JsVariableMirror.from(field, metadata, owner, isStatic);
    if (mirror != null) {
      result.add(mirror);
    }
  }
}

/// Similar to [String.split], but returns an empty list if [string] is empty.
List<String> splitFields(String string, Pattern pattern) {
  if (string.isEmpty) return <String>[];
  return string.split(pattern);
}

bool isOperatorName(String name) {
  switch (name) {
  case '==':
  case '[]':
  case '*':
  case '/':
  case '%':
  case '~/':
  case '+':
  case '<<':
  case '>>':
  case '>=':
  case '>':
  case '<=':
  case '<':
  case '&':
  case '^':
  case '|':
  case '-':
  case 'unary-':
  case '[]=':
  case '~':
    return true;
  default:
    return false;
  }
}

/// Returns true if the key represent ancillary reflection data, that is, not a
/// method.
bool isReflectiveDataInPrototype(String key) {
  if (key == '' || key == METHODS_WITH_OPTIONAL_ARGUMENTS) return true;
  String firstChar = key[0];
  return firstChar == '*' || firstChar == '+';
}

// Copied from package "unmodifiable_collection".
// TODO(ahe): Lobby to get it added to dart:collection.
class UnmodifiableMapView<K, V> implements Map<K, V> {
  Map<K, V> _source;
  UnmodifiableMapView(Map<K, V> source) : _source = source;

  static void _throw() {
    throw new UnsupportedError("Cannot modify an unmodifiable Map");
  }

  int get length => _source.length;

  bool get isEmpty => _source.isEmpty;

  bool get isNotEmpty => _source.isNotEmpty;

  V operator [](K key) => _source[key];

  bool containsKey(K key) => _source.containsKey(key);

  bool containsValue(V value) => _source.containsValue(value);

  void forEach(void f(K key, V value)) => _source.forEach(f);

  Iterable<K> get keys => _source.keys;

  Iterable<V> get values => _source.values;


  void operator []=(K key, V value) => _throw();

  V putIfAbsent(K key, V ifAbsent()) { _throw(); }

  void addAll(Map<K, V> other) => _throw();

  V remove(K key) { _throw(); }

  void clear() => _throw();
}

// TODO(ahe): Remove this class and call noSuchMethod instead.
class UnimplementedNoSuchMethodError extends Error
    implements NoSuchMethodError {
  final String _message;

  UnimplementedNoSuchMethodError(this._message);

  String toString() => "Unsupported operation: $_message";
}
