// 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);
  }
}
