// Copyright (c) 2016, 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_handler;

import '../common.dart';
import '../common/resolution.dart';
import '../diagnostics/diagnostic_listener.dart';
import '../elements/elements.dart';
import '../elements/entities.dart';
import '../universe/selector.dart';
import '../universe/use.dart';
import '../universe/world_impact.dart';
import 'backend.dart';

class MirrorsAnalysis {
  final MirrorsHandler resolutionHandler;
  final MirrorsHandler codegenHandler;

  MirrorsAnalysis(JavaScriptBackend backend, Resolution resolution)
      : resolutionHandler = new MirrorsHandler(backend, resolution),
        codegenHandler = new MirrorsHandler(backend, resolution);

  /// Compute the impact for elements that are matched by the mirrors used
  /// annotation or, in lack thereof, all elements.
  WorldImpact computeImpactForReflectiveElements(
      Iterable<ClassEntity> recents,
      Iterable<ClassEntity> processedClasses,
      Iterable<LibraryElement> loadedLibraries,
      {bool forResolution}) {
    MirrorsHandler handler = forResolution ? resolutionHandler : codegenHandler;
    handler.enqueueReflectiveElements(
        recents, processedClasses, loadedLibraries);
    return handler.flush();
  }

  /// Compute the impact for the static fields that have been marked as used by
  /// reflective usage through `MirrorsUsed`.
  WorldImpact computeImpactForReflectiveStaticFields(Iterable<Element> elements,
      {bool forResolution}) {
    MirrorsHandler handler = forResolution ? resolutionHandler : codegenHandler;
    handler.enqueueReflectiveStaticFields(elements);
    return handler.flush();
  }
}

class MirrorsHandler {
  static final TRACE_MIRROR_ENQUEUING =
      const bool.fromEnvironment("TRACE_MIRROR_ENQUEUING");

  final JavaScriptBackend _backend;
  final Resolution _resolution;

  bool hasEnqueuedReflectiveElements = false;
  bool hasEnqueuedReflectiveStaticFields = false;

  StagedWorldImpactBuilder impactBuilder = new StagedWorldImpactBuilder();

  MirrorsHandler(this._backend, this._resolution);

  DiagnosticReporter get _reporter => _resolution.reporter;

  WorldImpact flush() => impactBuilder.flush();

  void _logEnqueueReflectiveAction(action, [msg = ""]) {
    if (TRACE_MIRROR_ENQUEUING) {
      print("MIRROR_ENQUEUE (R): $action $msg");
    }
  }

  /**
   * Decides whether an element should be included to satisfy requirements
   * of the mirror system.
   *
   * During resolution, we have to resort to matching elements against the
   * [MirrorsUsed] pattern, as we do not have a complete picture of the world,
   * yet.
   */
  bool _shouldIncludeElementDueToMirrors(Element element,
      {bool includedEnclosing}) {
    return includedEnclosing || _backend.requiredByMirrorSystem(element);
  }

  /// Enqueue the constructor [ctor] if it is required for reflection.
  ///
  /// [enclosingWasIncluded] provides a hint whether the enclosing element was
  /// needed for reflection.
  void _enqueueReflectiveConstructor(ConstructorElement constructor,
      {bool enclosingWasIncluded}) {
    if (_shouldIncludeElementDueToMirrors(constructor,
        includedEnclosing: enclosingWasIncluded)) {
      _logEnqueueReflectiveAction(constructor);
      ClassElement cls = constructor.declaration.enclosingClass;
      impactBuilder
          .registerTypeUse(new TypeUse.mirrorInstantiation(cls.rawType));
      impactBuilder
          .registerStaticUse(new StaticUse.foreignUse(constructor.declaration));
    }
  }

  /// Enqueue the member [element] if it is required for reflection.
  ///
  /// [enclosingWasIncluded] provides a hint whether the enclosing element was
  /// needed for reflection.
  void _enqueueReflectiveMember(Element element, bool enclosingWasIncluded) {
    if (_shouldIncludeElementDueToMirrors(element,
        includedEnclosing: enclosingWasIncluded)) {
      _logEnqueueReflectiveAction(element);
      if (element.isTypedef) {
        TypedefElement typedef = element;
        typedef.ensureResolved(_resolution);
      } else if (Elements.isStaticOrTopLevel(element)) {
        impactBuilder
            .registerStaticUse(new StaticUse.foreignUse(element.declaration));
      } else if (element.isInstanceMember) {
        // We need to enqueue all members matching this one in subclasses, as
        // well.
        // TODO(herhut): Use TypedSelector.subtype for enqueueing
        DynamicUse dynamicUse =
            new DynamicUse(new Selector.fromElement(element), null);
        impactBuilder.registerDynamicUse(dynamicUse);
        if (element.isField) {
          DynamicUse dynamicUse = new DynamicUse(
              new Selector.setter(
                  new Name(element.name, element.library, isSetter: true)),
              null);
          impactBuilder.registerDynamicUse(dynamicUse);
        }
      }
    }
  }

  /// Enqueue the member [element] if it is required for reflection.
  ///
  /// [enclosingWasIncluded] provides a hint whether the enclosing element was
  /// needed for reflection.
  void _enqueueReflectiveElementsInClass(
      ClassElement cls, Iterable<ClassEntity> recents,
      {bool enclosingWasIncluded}) {
    if (cls.library.isInternalLibrary || cls.isInjected) return;
    bool includeClass = _shouldIncludeElementDueToMirrors(cls,
        includedEnclosing: enclosingWasIncluded);
    if (includeClass) {
      _logEnqueueReflectiveAction(cls, "register");
      ClassElement declaration = cls.declaration;
      declaration.ensureResolved(_resolution);
      impactBuilder.registerTypeUse(
          new TypeUse.mirrorInstantiation(declaration.rawType));
    }
    // If the class is never instantiated, we know nothing of it can possibly
    // be reflected upon.
    // TODO(herhut): Add a warning if a mirrors annotation cannot hit.
    if (recents.contains(cls.declaration)) {
      _logEnqueueReflectiveAction(cls, "members");
      cls.constructors.forEach((Element element) {
        _enqueueReflectiveConstructor(element,
            enclosingWasIncluded: includeClass);
      });
      cls.forEachClassMember((Member member) {
        _enqueueReflectiveMember(member.element, includeClass);
      });
    }
  }

  /// Enqueue special classes that might not be visible by normal means or that
  /// would not normally be enqueued:
  ///
  /// [Closure] is treated specially as it is the superclass of all closures.
  /// Although it is in an internal library, we mark it as reflectable. Note
  /// that none of its methods are reflectable, unless reflectable by
  /// inheritance.
  void _enqueueReflectiveSpecialClasses() {
    Iterable<ClassElement> classes = _backend.classesRequiredForReflection;
    for (ClassElement cls in classes) {
      if (_backend.referencedFromMirrorSystem(cls)) {
        _logEnqueueReflectiveAction(cls);
        cls.ensureResolved(_resolution);
        impactBuilder
            .registerTypeUse(new TypeUse.mirrorInstantiation(cls.rawType));
      }
    }
  }

  /// Enqueue all local members of the library [lib] if they are required for
  /// reflection.
  void _enqueueReflectiveElementsInLibrary(
      LibraryElement lib, Iterable<ClassEntity> recents) {
    bool includeLibrary =
        _shouldIncludeElementDueToMirrors(lib, includedEnclosing: false);
    lib.forEachLocalMember((Element member) {
      if (member.isInjected) return;
      if (member.isClass) {
        ClassElement cls = member;
        cls.ensureResolved(_resolution);
        do {
          _enqueueReflectiveElementsInClass(cls, recents,
              enclosingWasIncluded: includeLibrary);
          cls = cls.superclass;
        } while (cls != null && cls.isUnnamedMixinApplication);
      } else {
        _enqueueReflectiveMember(member, includeLibrary);
      }
    });
  }

  /// Enqueue all elements that are matched by the mirrors used
  /// annotation or, in lack thereof, all elements.
  // TODO(johnniwinther): Compute [WorldImpact] instead of enqueuing directly.
  void enqueueReflectiveElements(
      Iterable<ClassEntity> recents,
      Iterable<ClassEntity> processedClasses,
      Iterable<LibraryElement> loadedLibraries) {
    if (!hasEnqueuedReflectiveElements) {
      _logEnqueueReflectiveAction("!START enqueueAll");
      // First round of enqueuing, visit everything that is visible to
      // also pick up static top levels, etc.
      // Also, during the first round, consider all classes that have been seen
      // as recently seen, as we do not know how many rounds of resolution might
      // have run before tree shaking is disabled and thus everything is
      // enqueued.
      recents = processedClasses.toSet();
      _reporter.log('Enqueuing everything');
      for (LibraryElement lib in loadedLibraries) {
        _enqueueReflectiveElementsInLibrary(lib, recents);
      }
      _enqueueReflectiveSpecialClasses();
      hasEnqueuedReflectiveElements = true;
      hasEnqueuedReflectiveStaticFields = true;
      _logEnqueueReflectiveAction("!DONE enqueueAll");
    } else if (recents.isNotEmpty) {
      // Keep looking at new classes until fixpoint is reached.
      _logEnqueueReflectiveAction("!START enqueueRecents");
      recents.forEach((ClassElement cls) {
        _enqueueReflectiveElementsInClass(cls, recents,
            enclosingWasIncluded: _shouldIncludeElementDueToMirrors(cls.library,
                includedEnclosing: false));
      });
      _logEnqueueReflectiveAction("!DONE enqueueRecents");
    }
  }

  /// Enqueue the static fields that have been marked as used by reflective
  /// usage through `MirrorsUsed`.
  // TODO(johnniwinther): Compute [WorldImpact] instead of enqueuing directly.
  void enqueueReflectiveStaticFields(Iterable<Element> elements) {
    if (hasEnqueuedReflectiveStaticFields) return;
    hasEnqueuedReflectiveStaticFields = true;
    for (Element element in elements) {
      _enqueueReflectiveMember(element, true);
    }
  }
}
