// 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 '../common.dart';
import '../compiler.dart' show
    Compiler;
import '../constants/expressions.dart';
import '../constants/values.dart';
import '../dart_types.dart';
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.reporter.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 = new SourceSpan.fromTokens(
          script.resourceUri, beginToken, endToken);
    }
    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.resolution);
        _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.reporter.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.reporter.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);
  }
}
