// Copyright (c) 2012, 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 dart2js.mirrors;

import 'dart:collection' show UnmodifiableListView, UnmodifiableMapView;

import '../compiler.dart' show
    Compiler;
import '../constants/expressions.dart';
import '../constants/values.dart';
import '../dart_types.dart';
import '../diagnostics/invariant.dart' show
    invariant;
import '../diagnostics/source_span.dart' show
    SourceSpan;
import '../diagnostics/spannable.dart' show
    NO_LOCATION_SPANNABLE;
import '../elements/elements.dart';
import '../elements/modelx.dart' show
    LibraryElementX;
import '../resolution/scope.dart' show
    Scope;
import '../script.dart';
import '../tokens/token.dart';
import '../tokens/token_constants.dart' as Tokens;
import '../tree/tree.dart';
import '../util/util.dart'
    show Link,
         LinkBuilder;
import '../util/characters.dart' show $CR, $LF;

import 'source_mirrors.dart';
import 'mirrors_util.dart';

part 'dart2js_library_mirror.dart';
part 'dart2js_type_mirrors.dart';
part 'dart2js_member_mirrors.dart';
part 'dart2js_instance_mirrors.dart';

//------------------------------------------------------------------------------
// Utility types and functions for the dart2js mirror system
//------------------------------------------------------------------------------

bool _includeLibrary(Dart2JsLibraryMirror mirror) {
  return const bool.fromEnvironment("list_all_libraries") ||
      !mirror._element.isInternalLibrary;
}

bool _isPrivate(String name) {
  return name.startsWith('_');
}

List<ParameterMirror> _parametersFromFunctionSignature(
    Dart2JsDeclarationMirror owner,
    FunctionSignature signature) {
  var parameters = <ParameterMirror>[];
  signature.requiredParameters.forEach((FormalElement parameter) {
    parameters.add(new Dart2JsParameterMirror(
        owner, parameter, isOptional: false, isNamed: false));
  });
  bool isNamed = signature.optionalParametersAreNamed;
  signature.optionalParameters.forEach((FormalElement parameter) {
    parameters.add(new Dart2JsParameterMirror(
        owner, parameter, isOptional: true, isNamed: isNamed));
  });
  return parameters;
}

MethodMirror _convertElementMethodToMethodMirror(
    Dart2JsDeclarationMirror library, Element element) {
  if (element is FunctionElement) {
    return new Dart2JsMethodMirror(library, element);
  } else {
    return null;
  }
}

//------------------------------------------------------------------------------
// Dart2Js specific extensions of mirror interfaces
//------------------------------------------------------------------------------

abstract class Dart2JsMirror implements Mirror {
  Dart2JsMirrorSystem get mirrorSystem;
}

abstract class Dart2JsDeclarationMirror extends Dart2JsMirror
    implements DeclarationSourceMirror {

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

  bool get isPrivate => _isPrivate(_simpleNameString);

  String get _simpleNameString;

  String get _qualifiedNameString {
    var parent = owner;
    if (parent is Dart2JsDeclarationMirror) {
      return '${parent._qualifiedNameString}.${_simpleNameString}';
    }
    assert(parent == null);
    return _simpleNameString;
  }

  Symbol get simpleName => symbolOf(_simpleNameString, getLibrary(this));

  Symbol get qualifiedName => symbolOf(_qualifiedNameString, getLibrary(this));

  DeclarationMirror lookupInScope(String name) => null;

  bool get isNameSynthetic => false;

  /// Returns the type mirror for [type] in the context of this declaration.
  TypeMirror _getTypeMirror(DartType type) {
    return mirrorSystem._convertTypeToTypeMirror(type);
  }

  /// Returns a list of the declaration mirrorSystem for [element].
  Iterable<Dart2JsMemberMirror> _getDeclarationMirrors(Element element) {
    if (element.isSynthesized) {
      return const <Dart2JsMemberMirror>[];
    } else if (element is VariableElement) {
      return <Dart2JsMemberMirror>[new Dart2JsFieldMirror(this, element)];
    } else if (element is FunctionElement) {
      return <Dart2JsMemberMirror>[new Dart2JsMethodMirror(this, element)];
    } else if (element is AbstractFieldElement) {
      var members = <Dart2JsMemberMirror>[];
      AbstractFieldElement field = element;
      if (field.getter != null) {
        members.add(new Dart2JsMethodMirror(this, field.getter));
      }
      if (field.setter != null) {
        members.add(new Dart2JsMethodMirror(this, field.setter));
      }
      return members;
    }
    mirrorSystem.compiler.internalError(element,
        "Unexpected member type $element ${element.kind}.");
    return null;
  }
}

abstract class Dart2JsElementMirror extends Dart2JsDeclarationMirror {
  final Dart2JsMirrorSystem mirrorSystem;
  final Element _element;
  List<InstanceMirror> _metadata;

  Dart2JsElementMirror(this.mirrorSystem, this._element) {
    assert (mirrorSystem != null);
    assert (_element != null);
  }

  String get _simpleNameString => _element.name;

  /**
   * Computes the first token for this declaration using the begin token of the
   * element node or element position as indicator.
   */
  Token getBeginToken() {
    Element element = _element;
    if (element is AstElement) {
      Node node = element.node;
      if (node != null) {
        return node.getBeginToken();
      }
    }
    return element.position;
  }

  /**
   * Computes the last token for this declaration using the end token of the
   * element node or element position as indicator.
   */
  Token getEndToken() {
    Element element = _element;
    if (element is AstElement) {
      Node node = element.node;
      if (node != null) {
        return node.getEndToken();
      }
    }
    return element.position;
  }

  /**
   * Returns the first token for the source of this declaration, including
   * metadata annotations.
   */
  Token getFirstToken() {
    if (!_element.metadata.isEmpty) {
      for (MetadataAnnotation metadata in _element.metadata) {
        if (metadata.beginToken != null) {
          return metadata.beginToken;
        }
      }
    }
    return getBeginToken();
  }

  Script getScript() => _element.compilationUnit.script;

  SourceLocation get location {
    Token beginToken = getFirstToken();
    Script script = getScript();
    SourceSpan span;
    if (beginToken == null) {
      span = new SourceSpan(script.resourceUri, 0, 0);
    } else {
      Token endToken = getEndToken();
      span = mirrorSystem.compiler.spanFromTokens(
          beginToken, endToken, script.resourceUri);
    }
    return new Dart2JsSourceLocation(script, span);
  }

  String toString() => _element.toString();

  void _appendCommentTokens(Token commentToken) {
    while (commentToken != null && commentToken.kind == Tokens.COMMENT_TOKEN) {
      _metadata.add(new Dart2JsCommentInstanceMirror(
          mirrorSystem, commentToken.value));
      commentToken = commentToken.next;
    }
  }

  List<InstanceMirror> get metadata {
    if (_metadata == null) {
      _metadata = <InstanceMirror>[];
      for (MetadataAnnotation metadata in _element.metadata) {
        _appendCommentTokens(
            mirrorSystem.compiler.commentMap[metadata.beginToken]);
        metadata.ensureResolved(mirrorSystem.compiler);
        _metadata.add(_convertConstantToInstanceMirror(
            mirrorSystem, metadata.constant,
            mirrorSystem.compiler.constants.getConstantValue(
                metadata.constant)));
      }
      _appendCommentTokens(mirrorSystem.compiler.commentMap[getBeginToken()]);
    }
    // TODO(johnniwinther): Return an unmodifiable list instead.
    return new List<InstanceMirror>.from(_metadata);
  }

  DeclarationMirror lookupInScope(String name) {
    // TODO(11653): Support lookup of constructors.
    Scope scope = _element.buildScope();
    Element result;
    int index = name.indexOf('.');
    if (index != -1) {
      // Lookup [: prefix.id :].
      String prefix = name.substring(0, index);
      String id = name.substring(index+1);
      result = scope.lookup(prefix);
      if (result != null && result.isPrefix) {
        PrefixElement prefix = result;
        result = prefix.lookupLocalMember(id);
      } else {
        result = null;
      }
    } else {
      // Lookup [: id :].
      result = scope.lookup(name);
    }
    if (result == null || result.isPrefix) return null;
    return _convertElementToDeclarationMirror(mirrorSystem, result);
  }

  bool operator ==(var other) {
    if (identical(this, other)) return true;
    if (other == null) return false;
    if (other is! Dart2JsElementMirror) return false;
    return _element == other._element &&
           owner == other.owner;
  }

  int get hashCode {
    return 13 * _element.hashCode + 17 * owner.hashCode;
  }
}

//------------------------------------------------------------------------------
// Mirror system implementation.
//------------------------------------------------------------------------------

class Dart2JsMirrorSystem extends MirrorSystem {
  final Compiler compiler;
  Map<LibraryElement, Dart2JsLibraryMirror> _libraryMap;
  UnmodifiableMapView<Uri, LibraryMirror> _filteredLibraries;

  Dart2JsMirrorSystem(this.compiler);

  IsolateMirror get isolate => null;

  void _ensureLibraries() {
    if (_filteredLibraries == null) {
      var filteredLibs = new Map<Uri, LibraryMirror>();
      _libraryMap = new Map<LibraryElement, Dart2JsLibraryMirror>();
      compiler.libraryLoader.libraries.forEach((LibraryElement v) {
        var mirror = new Dart2JsLibraryMirror(mirrorSystem, v);
        if (_includeLibrary(mirror)) {
          filteredLibs[mirror.uri] = mirror;
        }
        _libraryMap[v] = mirror;
      });

      _filteredLibraries =
          new UnmodifiableMapView<Uri, LibraryMirror>(filteredLibs);
    }
  }

  Map<Uri, LibraryMirror> get libraries {
    _ensureLibraries();
    return _filteredLibraries;
  }

  Dart2JsLibraryMirror _getLibrary(LibraryElement element) =>
      _libraryMap[element];

  Dart2JsMirrorSystem get mirrorSystem => this;

  TypeMirror get dynamicType =>
      _convertTypeToTypeMirror(const DynamicType());

  TypeMirror get voidType =>
      _convertTypeToTypeMirror(const VoidType());

  TypeMirror _convertTypeToTypeMirror(DartType type) {
    assert(type != null);
    if (type.treatAsDynamic) {
      return new Dart2JsDynamicMirror(this, type);
    } else if (type is InterfaceType) {
      if (type.typeArguments.isEmpty) {
        return _getTypeDeclarationMirror(type.element);
      } else {
        return new Dart2JsInterfaceTypeMirror(this, type);
      }
    } else if (type is TypeVariableType) {
      return new Dart2JsTypeVariableMirror(this, type);
    } else if (type is FunctionType) {
      return new Dart2JsFunctionTypeMirror(this, type);
    } else if (type is VoidType) {
      return new Dart2JsVoidMirror(this, type);
    } else if (type is TypedefType) {
      if (type.typeArguments.isEmpty) {
        return _getTypeDeclarationMirror(type.element);
      } else {
        return new Dart2JsTypedefMirror(this, type);
      }
    }
    compiler.internalError(type.element,
        "Unexpected type $type of kind ${type.kind}.");
    return null;
  }

  DeclarationMirror _getTypeDeclarationMirror(TypeDeclarationElement element) {
    if (element.isClass) {
      return new Dart2JsClassDeclarationMirror(this, element.thisType);
    } else if (element.isTypedef) {
      return new Dart2JsTypedefDeclarationMirror(this, element.thisType);
    }
    compiler.internalError(element, "Unexpected element $element.");
    return null;
  }
}

abstract class ContainerMixin {
  UnmodifiableMapView<Symbol, DeclarationMirror> _declarations;

  void _ensureDeclarations() {
    if (_declarations == null) {
      var declarations = <Symbol, DeclarationMirror>{};
      _forEachElement((Element element) {
        for (DeclarationMirror mirror in _getDeclarationMirrors(element)) {
          assert(invariant(_element,
              !declarations.containsKey(mirror.simpleName),
              message: "Declaration name '${nameOf(mirror)}' "
                       "is not unique in $_element."));
          declarations[mirror.simpleName] = mirror;
        }
      });
      _declarations =
          new UnmodifiableMapView<Symbol, DeclarationMirror>(declarations);
    }
  }

  Element get _element;

  void _forEachElement(f(Element element));

  Iterable<Dart2JsMemberMirror> _getDeclarationMirrors(Element element);

  Map<Symbol, DeclarationMirror> get declarations {
    _ensureDeclarations();
    return _declarations;
  }
}

/**
 * Converts [element] into its corresponding [DeclarationMirror], if any.
 *
 * If [element] is an [AbstractFieldElement] the mirror for its getter is
 * returned or, if not present, the mirror for its setter.
 */
DeclarationMirror _convertElementToDeclarationMirror(Dart2JsMirrorSystem system,
                                                     Element element) {
  if (element.isTypeVariable) {
    TypeVariableElement typeVariable = element;
    return new Dart2JsTypeVariableMirror(system, typeVariable.type);
  }

  Dart2JsLibraryMirror library = system._libraryMap[element.library];
  if (element.isLibrary) return library;
  if (element.isTypedef) {
    TypedefElement typedefElement = element;
    return new Dart2JsTypedefMirror.fromLibrary(
        library, typedefElement.thisType);
  }

  Dart2JsDeclarationMirror container = library;
  if (element.enclosingClass != null) {
    container = system._getTypeDeclarationMirror(element.enclosingClass);
  }
  if (element.isClass) return container;
  if (element.isParameter) {
    Dart2JsMethodMirror method = _convertElementMethodToMethodMirror(
        container, element.outermostEnclosingMemberOrTopLevel);
    // TODO(johnniwinther): Find the right info for [isOptional] and [isNamed].
    return new Dart2JsParameterMirror(
        method, element, isOptional: false, isNamed: false);
  }
  Iterable<DeclarationMirror> members =
      container._getDeclarationMirrors(element);
  if (members.isEmpty) return null;
  return members.first;
}

/**
 * Experimental API for accessing compilation units defined in a
 * library.
 */
// TODO(ahe): Superclasses? Is this really a mirror?
class Dart2JsCompilationUnitMirror extends Dart2JsMirror with ContainerMixin {
  final Dart2JsLibraryMirror _library;
  final CompilationUnitElement _element;

  Dart2JsCompilationUnitMirror(this._element, this._library);

  Dart2JsMirrorSystem get mirrorSystem => _library.mirrorSystem;

  // TODO(johnniwinther): make sure that these are returned in declaration
  // order.
  void _forEachElement(f(Element element)) => _element.forEachLocalMember(f);

  Iterable<DeclarationMirror> _getDeclarationMirrors(Element element) =>
      _library._getDeclarationMirrors(element);

  Uri get uri => _element.script.resourceUri;
}

/**
 * Transitional class that allows access to features that have not yet
 * made it to the mirror API.
 *
 * All API in this class is experimental.
 */
class BackDoor {
  /// Return the compilation units comprising [library].
  static List<Mirror> compilationUnitsOf(Dart2JsLibraryMirror library) {
    return library._element.compilationUnits.mapToList(
        (cu) => new Dart2JsCompilationUnitMirror(cu, library));
  }

  static Iterable<ConstantExpression> metadataSyntaxOf(
      Dart2JsElementMirror declaration) {
    return declaration._element.metadata.map((metadata) => metadata.constant);
  }

  static ConstantExpression initializerSyntaxOf(Dart2JsFieldMirror variable) {
    Compiler compiler = variable.mirrorSystem.compiler;
    return compiler.constants.getConstantForVariable(variable._variable);
  }

  static ConstantExpression defaultValueSyntaxOf(
        Dart2JsParameterMirror parameter) {
    if (!parameter.hasDefaultValue) return null;
    ParameterElement parameterElement = parameter._element;
    Compiler compiler = parameter.mirrorSystem.compiler;
    return compiler.constants.getConstantForVariable(parameterElement);
  }

  static Mirror getMirrorFromElement(Dart2JsMirror mirror, Element element) {
    return _convertElementToDeclarationMirror(mirror.mirrorSystem, element);
  }
}
