// Copyright (c) 2015, 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:mirrors';
import 'dart:_foreign_helper' show JS;
import 'dart:_internal' as _internal;

String getName(Symbol symbol) =>
    _internal.Symbol.getName(symbol as _internal.Symbol);

Symbol getSymbol(name, library) =>
    throw new UnimplementedError("MirrorSystem.getSymbol unimplemented");

final currentJsMirrorSystem = throw new UnimplementedError(
    "MirrorSystem.currentJsMirrorSystem unimplemented");

final _typeMirror = JS('', 'Symbol("_typeMirror")');

InstanceMirror reflect(reflectee) {
  // TODO(vsm): Consider caching the mirror here.  Unlike the type below,
  // reflectee may be a primitive - i.e., we can't just add an expando.
  if (reflectee is Function) {
    return new JsClosureMirror._(reflectee);
  } else {
    return new JsInstanceMirror._(reflectee);
  }
}

TypeMirror reflectType(Type key) {
  var unwrapped = _unwrap(key);
  var property =
      JS('', 'Object.getOwnPropertyDescriptor(#, #)', unwrapped, _typeMirror);
  if (property != null) {
    return JS('', '#.value', property);
  }
  // TODO(vsm): Might not be a class.
  var mirror = new JsClassMirror._(key);
  JS('', '#[#] = #', unwrapped, _typeMirror, mirror);
  return mirror;
}

final dynamic _dart = JS('', 'dart');

dynamic _dload(obj, String name) {
  return JS('', '#.dloadMirror(#, #)', _dart, obj, name);
}

void _dput(obj, String name, val) {
  JS('', '#.dputMirror(#, #, #)', _dart, obj, name, val);
}

dynamic _dcall(obj, List args) {
  return JS('', '#.dcall(#, ...#)', _dart, obj, args);
}

dynamic _dsend(obj, String name, List args) {
  return JS('', '#.dsend(#, #, ...#)', _dart, obj, name, args);
}

dynamic _getGenericClass(obj) {
  return JS('', '#.getGenericClass(#)', _dart, obj);
}

dynamic _getGenericArgs(obj) {
  return JS('', '#.getGenericArgs(#)', _dart, obj);
}

dynamic _defaultConstructorType(type) {
  return JS('', '#.definiteFunctionType(#, [])', _dart, type);
}

dynamic _getMixins(type) {
  return JS('', '#.getMixins(#, [])', _dart, type);
}

typedef T _Lazy<T>();

dynamic _getESSymbol(Symbol symbol) =>
    _internal.Symbol.getNativeSymbol(symbol as _internal.Symbol);

dynamic _getMember(Symbol symbol) {
  var privateSymbol = _getESSymbol(symbol);
  if (privateSymbol != null) {
    return privateSymbol;
  }
  var name = getName(symbol);
  // TODO(jacobr): this code is duplicated in code_generator.dart
  switch (name) {
    case '[]':
      name = '_get';
      break;
    case '[]=':
      name = '_set';
      break;
    case 'unary-':
      name = '_negate';
      break;
    case 'constructor':
    case 'prototype':
      name = '_$name';
      break;
  }
  return name;
}

String _getNameForESSymbol(member) {
  // Convert private JS symbol "Symbol(_foo)" to string "_foo".
  assert(JS('bool', 'typeof # == "symbol"', member));
  var str = member.toString();
  assert(str.startsWith('Symbol(') && str.endsWith(')'));
  return str.substring(7, str.length - 1);
}

Symbol _getSymbolForESSymbol(member) {
  var name = _getNameForESSymbol(member);
  return new _internal.Symbol.es6(name, member);
}

// The [member] must be either a string (public) or an ES6 symbol (private).
Symbol _getSymbolForMember(member) {
  if (member is String) {
    return new Symbol(member);
  } else {
    var name = _getNameForESSymbol(member);
    return new _internal.Symbol.es6(name, member);
  }
}

Map<Symbol, dynamic> _toDartMap(data) {
  if (data == null) return {};
  var map = new Map<Symbol, dynamic>();
  // Note: we recorded a map from fields/methods to their type and metadata.
  // The key is a string name for public members but an ES6 symbol for private
  // ones.  That's works nicely for dynamic operations, but dart:mirrors expects
  // Dart symbols, so we convert here.
  var publicMembers = JS('', 'Object.getOwnPropertyNames(#)', data);
  for (var member in publicMembers) {
    var symbol = new Symbol(member);
    map[symbol] = JS('', '#[#]', data, member);
  }

  var privateMembers = JS('', 'Object.getOwnPropertySymbols(#)', data);
  for (var member in privateMembers) {
    var symbol = _getSymbolForESSymbol(member);
    map[symbol] = JS('', '#[#]', data, member);
  }
  return map;
}

Map<Symbol, dynamic> _getConstructors(obj) {
  List sig = JS('', '#.getConstructorSig(#)', _dart, obj);
  return _toDartMap(sig);
}

Map<Symbol, dynamic> _getFields(obj) {
  List sig = JS('', '#.getFieldSig(#)', _dart, obj);
  return _toDartMap(sig);
}

Map<Symbol, dynamic> _getMethods(obj) {
  List sig = JS('', '#.getMethodSig(#)', _dart, obj);
  return _toDartMap(sig);
}

Map<Symbol, dynamic> _getGetters(obj) {
  List sig = JS('', '#.getGetterSig(#)', _dart, obj);
  return _toDartMap(sig);
}

Map<Symbol, dynamic> _getSetters(obj) {
  List sig = JS('', '#.getSetterSig(#)', _dart, obj);
  return _toDartMap(sig);
}

Map<Symbol, dynamic> _getStaticFields(obj) {
  List sig = JS('', '#.getStaticFieldSig(#)', _dart, obj);
  return _toDartMap(sig);
}

Map<Symbol, dynamic> _getStatics(obj) {
  List sig = JS('', '#.getStaticSig(#)', _dart, obj);
  return _toDartMap(sig);
}

Map<Symbol, dynamic> _getStaticGetters(obj) {
  List sig = JS('', '#.getStaticGetterSig(#)', _dart, obj);
  return _toDartMap(sig);
}

Map<Symbol, dynamic> _getStaticSetters(obj) {
  List sig = JS('', '#.getStaticSetterSig(#)', _dart, obj);
  return _toDartMap(sig);
}

// TODO(vsm): These methods need to validate whether we really have a
// WrappedType or a raw type that should be wrapped (as opposed to a
// function).
dynamic _unwrap(obj) => JS('', '#.unwrapType(#)', _dart, obj);

dynamic _wrap(obj) => JS('', '#.wrapType(#)', _dart, obj);

dynamic _runtimeType(obj) => _wrap(JS('', '#.getReifiedType(#)', _dart, obj));

_unimplemented(Type t, Invocation i) {
  throw new UnimplementedError('$t.${getName(i.memberName)} unimplemented');
}

dynamic _toJsMap(Map<Symbol, dynamic> map) {
  var obj = JS('', '{}');
  map.forEach((Symbol key, value) {
    JS('', '#[#] = #', obj, getName(key), value);
  });
  return obj;
}

class JsMirror implements Mirror {
  noSuchMethod(Invocation i) {
    _unimplemented(this.runtimeType, i);
  }
}

class JsCombinatorMirror extends JsMirror implements CombinatorMirror {}

class JsDeclarationMirror extends JsMirror implements DeclarationMirror {}

class JsIsolateMirror extends JsMirror implements IsolateMirror {}

class JsLibraryDependencyMirror extends JsMirror
    implements LibraryDependencyMirror {}

class JsObjectMirror extends JsMirror implements ObjectMirror {}

class JsInstanceMirror extends JsObjectMirror implements InstanceMirror {
  // Reflected object
  final reflectee;
  bool get hasReflectee => true;

  ClassMirror get type {
    // The spec guarantees that `null` is the singleton instance of the `Null`
    // class.
    if (reflectee == null) return reflectClass(Null);
    return reflectType(_runtimeType(reflectee));
  }

  JsInstanceMirror._(this.reflectee);

  bool operator ==(Object 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;
  }

  // Returns a String for public members or an ES6 symbol for private members.
  _getAccessor(dynamic reflectee, Symbol symbol,
      [List<dynamic> args, Map<Symbol, dynamic> namedArgs]) {
    return _getMember(symbol);
  }

  InstanceMirror getField(Symbol symbol) {
    var name = _getAccessor(reflectee, symbol);
    var field = _dload(reflectee, name);
    return reflect(field);
  }

  InstanceMirror setField(Symbol symbol, Object value) {
    var name = _getAccessor(reflectee, symbol);
    _dput(reflectee, name, value);
    return reflect(value);
  }

  InstanceMirror invoke(Symbol symbol, List<dynamic> args,
      [Map<Symbol, dynamic> namedArgs]) {
    var name = _getAccessor(reflectee, symbol, args, namedArgs);
    if (namedArgs != null) {
      args = new List.from(args);
      args.add(_toJsMap(namedArgs));
    }
    var result = _dsend(reflectee, name, args);
    return reflect(result);
  }

  String toString() => "InstanceMirror on '$reflectee'";
}

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

  InstanceMirror apply(List<dynamic> args, [Map<Symbol, dynamic> namedArgs]) {
    if (namedArgs != null) {
      args = new List.from(args);
      args.add(_toJsMap(namedArgs));
    }
    var result = _dcall(reflectee, args);
    return reflect(result);
  }
}

class JsClassMirror extends JsMirror implements ClassMirror {
  final Type _cls;
  final Symbol simpleName;
  // Generic class factory
  final dynamic _raw;

  // TODO(vsm): Do this properly
  ClassMirror _mixin = null;
  List<TypeMirror> _typeArguments;

  List<InstanceMirror> _metadata;
  Map<Symbol, DeclarationMirror> _declarations;

  List<InstanceMirror> get metadata {
    if (_metadata == null) {
      // Load metadata.
      var unwrapped = _unwrap(_cls);
      // Only get metadata directly embedded on this class, not its
      // superclasses.
      var fn = JS(
          'Function',
          'Object.hasOwnProperty.call(#, dart.metadata) ? #[dart.metadata] : null',
          unwrapped,
          unwrapped);
      _metadata = (fn == null)
          ? const <InstanceMirror>[]
          : new List<InstanceMirror>.unmodifiable(fn().map((i) => reflect(i)));
    }
    return _metadata;
  }

  Map<Symbol, DeclarationMirror> get declarations {
    if (_declarations == null) {
      // Load declarations.
      // TODO(vsm): This is only populating the default constructor right now.
      _declarations = new Map<Symbol, DeclarationMirror>();
      var unwrapped = _unwrap(_cls);
      var constructors = _getConstructors(unwrapped);
      constructors.forEach((symbol, ft) {
        var name = getName(symbol);
        _declarations[symbol] =
            new JsMethodMirror._constructor(this, symbol, ft);
      });
      if (constructors.isEmpty) {
        // Add a default
        var name = 'new';
        var ft = _defaultConstructorType(_unwrap(_cls));
        var symbol = new Symbol(name);
        _declarations[symbol] =
            new JsMethodMirror._constructor(this, symbol, ft);
      }
      var fields = _getFields(unwrapped);
      fields.forEach((symbol, t) {
        var metadata = [];
        if (t is List) {
          metadata = t.skip(1).toList();
          t = t[0];
        }
        _declarations[symbol] =
            new JsVariableMirror._(symbol, _wrap(t), metadata);
      });
      var methods = _getMethods(unwrapped);
      methods.forEach((symbol, ft) {
        var name = getName(symbol);
        _declarations[symbol] =
            new JsMethodMirror._instanceMethod(this, symbol, ft);
      });
      var getters = _getGetters(unwrapped);
      getters.forEach((symbol, ft) {
        var name = getName(symbol);
        _declarations[symbol] =
            new JsMethodMirror._instanceMethod(this, symbol, ft);
      });
      var setters = _getSetters(unwrapped);
      setters.forEach((symbol, ft) {
        var name = getName(symbol) + '=';
        // Create a separate symbol for the setter.
        symbol = new _internal.Symbol.es6(name, _getESSymbol(symbol));
        _declarations[symbol] =
            new JsMethodMirror._instanceMethod(this, symbol, ft);
      });
      var staticFields = _getStaticFields(unwrapped);
      staticFields.forEach((symbol, t) {
        var name = getName(symbol);
        var metadata = [];
        if (t is List) {
          metadata = t.skip(1).toList();
          t = t[0];
        }
        _declarations[symbol] =
            new JsVariableMirror._(symbol, _wrap(t), metadata);
      });
      var statics = _getStatics(unwrapped);
      statics.forEach((symbol, ft) {
        var name = getName(symbol);
        _declarations[symbol] =
            new JsMethodMirror._staticMethod(this, symbol, ft);
      });
      var staticGetters = _getStaticGetters(unwrapped);
      staticGetters.forEach((symbol, ft) {
        var name = getName(symbol);
        _declarations[symbol] =
            new JsMethodMirror._staticMethod(this, symbol, ft);
      });
      var staticSetters = _getStaticSetters(unwrapped);
      staticSetters.forEach((symbol, ft) {
        var name = getName(symbol);
        _declarations[symbol] =
            new JsMethodMirror._staticMethod(this, symbol, ft);
      });
      _declarations =
          new Map<Symbol, DeclarationMirror>.unmodifiable(_declarations);
    }
    return _declarations;
  }

  JsClassMirror._(Type cls)
      : _cls = cls,
        _raw = _getGenericClass(_unwrap(cls)),
        simpleName = new Symbol(JS('String', '#.name', _unwrap(cls))) {
    var typeArgs = _getGenericArgs(_unwrap(cls));
    if (typeArgs == null) {
      _typeArguments = const [];
    } else {
      _typeArguments =
          new List.unmodifiable(typeArgs.map((t) => reflectType(_wrap(t))));
    }
  }

  InstanceMirror newInstance(Symbol constructorName, List args,
      [Map<Symbol, dynamic> namedArgs]) {
    // TODO(vsm): Support factory constructors and named arguments.
    var name = getName(constructorName);
    assert(namedArgs == null || namedArgs.isEmpty);
    var instance = (name == 'new' || name == '')
        ? JS('', 'new #(...#)', _unwrap(_cls), args)
        : JS('', 'new (#.#)(...#)', _unwrap(_cls), name, args);
    return reflect(instance);
  }

  // TODO(vsm): Need to check for NSM, types on accessors below.  Unlike the
  // InstanceMirror case, there is no dynamic helper to delegate to - we never
  // need a dload, etc. on a static.

  InstanceMirror getField(Symbol symbol) {
    var name = getName(symbol);
    return reflect(JS('', '#[#]', _unwrap(_cls), name));
  }

  InstanceMirror setField(Symbol symbol, Object value) {
    var name = getName(symbol);
    JS('', '#[#] = #', _unwrap(_cls), name, value);
    return reflect(value);
  }

  InstanceMirror invoke(Symbol symbol, List<dynamic> args,
      [Map<Symbol, dynamic> namedArgs]) {
    var name = getName(symbol);
    if (namedArgs != null) {
      args = new List.from(args);
      args.add(_toJsMap(namedArgs));
    }
    var result = JS('', '#.#(...#)', _unwrap(_cls), name, args);
    return reflect(result);
  }

  List<ClassMirror> get superinterfaces {
    _Lazy<List<Type>> interfaceThunk =
        JS('', '#[dart.implements]', _unwrap(_cls));
    if (interfaceThunk == null) {
      return [];
    } else {
      List<Type> interfaces = interfaceThunk();
      return interfaces.map((t) => reflectType(t)).toList();
    }
  }

  bool get hasReflectedType => true;
  Type get reflectedType {
    return _cls;
  }

  bool get isOriginalDeclaration => _raw == null;

  List<TypeMirror> get typeArguments => _typeArguments;

  TypeMirror get originalDeclaration {
    // TODO(vsm): Handle generic case.  How should we represent an original
    // declaration for a generic class?
    if (_raw == null) {
      return this;
    }
    throw new UnimplementedError(
        "ClassMirror.originalDeclaration unimplemented");
  }

  ClassMirror get superclass {
    if (_cls == Object) {
      return null;
    } else {
      return reflectType(_wrap(JS('Type', '#.__proto__', _unwrap(_cls))));
    }
  }

  ClassMirror get mixin {
    if (_mixin != null) {
      return _mixin;
    }
    var mixins = _getMixins(_unwrap(_cls));
    if (mixins == null || mixins.isEmpty) {
      // If there is no mixin, return this mirror per API.
      _mixin = this;
      return _mixin;
    }
    if (mixins.length > 1) {
      throw new UnsupportedError("ClassMirror.mixin not yet supported for "
          "classes ($_cls) with multiple mixins");
    }
    _mixin = reflectType(_wrap(mixins[0]));
    return _mixin;
  }

  String toString() => "ClassMirror on '$_cls'";
}

class JsVariableMirror extends JsMirror implements VariableMirror {
  final Symbol _symbol;
  final String _name;
  final TypeMirror type;
  final List<InstanceMirror> metadata;

  // TODO(vsm): Refactor this out.
  Symbol get simpleName => _symbol;

  // TODO(vsm): Fix this
  final bool isStatic = false;
  final bool isFinal = false;

  JsVariableMirror._(Symbol symbol, Type t, List annotations)
      : _symbol = symbol,
        _name = getName(symbol),
        type = reflectType(t),
        metadata = new List<InstanceMirror>.unmodifiable(
            annotations.map((a) => reflect(a)));

  String toString() => "VariableMirror on '$_name'";
}

class JsParameterMirror extends JsVariableMirror implements ParameterMirror {
  JsParameterMirror._(Symbol member, Type t, List annotations)
      : super._(member, t, annotations);

  String toString() => "ParameterMirror on '$_name'";
}

class JsMethodMirror extends JsMirror implements MethodMirror {
  final Symbol _symbol;
  final String _name;
  List<ParameterMirror> _params;
  List<InstanceMirror> _metadata;
  final bool isConstructor;
  final bool isStatic;

  // TODO(vsm): Fix this
  final bool isFinal = false;
  bool get isSetter => _name.endsWith('=');
  bool get isPrivate => _name.startsWith('_');

  // TODO(vsm): Refactor this out.
  Symbol get simpleName => _symbol;

  JsMethodMirror._constructor(JsClassMirror cls, Symbol symbol, ftype)
      : _symbol = symbol,
        _name = getName(symbol),
        isConstructor = true,
        isStatic = false {
    _createParameterMirrorList(ftype);
  }

  JsMethodMirror._instanceMethod(JsClassMirror cls, Symbol symbol, ftype)
      : _symbol = symbol,
        _name = getName(symbol),
        isConstructor = false,
        isStatic = false {
    _createParameterMirrorList(ftype);
  }

  JsMethodMirror._staticMethod(JsClassMirror cls, Symbol symbol, ftype)
      : _symbol = symbol,
        _name = getName(symbol),
        isConstructor = false,
        isStatic = true {
    _createParameterMirrorList(ftype);
  }

  // TODO(vsm): Support named constructors.
  Symbol get constructorName => isConstructor ? _symbol : null;
  List<ParameterMirror> get parameters => _params;
  List<InstanceMirror> get metadata => _metadata;

  void _createParameterMirrorList(ftype) {
    if (ftype == null) {
      // TODO(vsm): No explicit constructor.  Verify this.
      _params = const [];
      _metadata = const [];
      return;
    }

    // TODO(vsm): Why does generic function type trigger true for List?
    if (ftype is! Function && ftype is List) {
      // Record metadata
      _metadata = new List<InstanceMirror>.unmodifiable(
          ftype.skip(1).map((a) => reflect(a)));
      ftype = ftype[0];
    } else {
      _metadata = const [];
    }

    // TODO(vsm): Handle generic function types properly.  Or deprecate mirrors
    // before we need to!
    if (JS('bool', 'typeof(#) == "function"', ftype)) {
      // Instantiate the generic version.
      // TODO(vsm): Can't use arguments.length on arrow function.
      ftype = JS('', '#.apply(null, #)', ftype, [dynamic, dynamic, dynamic]);
    }

    // TODO(vsm): Add named args.
    List args = ftype.args;
    List opts = ftype.optionals;
    var params = new List<ParameterMirror>(args.length + opts.length);

    for (var i = 0; i < args.length; ++i) {
      var type = args[i];
      var metadata = ftype.metadata[i];
      // TODO(vsm): Recover the param name.
      var param =
          new JsParameterMirror._(new Symbol(''), _wrap(type), metadata);
      params[i] = param;
    }

    for (var i = 0; i < opts.length; ++i) {
      var type = opts[i];
      var metadata = ftype.metadata[args.length + i];
      // TODO(vsm): Recover the param name.
      var param =
          new JsParameterMirror._(new Symbol(''), _wrap(type), metadata);
      params[i + args.length] = param;
    }

    _params = new List.unmodifiable(params);
  }

  String toString() => "MethodMirror on '$_name'";
}
