// Copyright (c) 2013, 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 deferred_load;

import 'dart:collection'
       show LinkedHashMap,
            LinkedHashSet;

import 'dart2jslib.dart'
       show Compiler,
            CompilerTask,
            ConstructedConstant,
            MessageKind,
            SourceString,
            StringConstant;

import 'elements/elements.dart'
       show ClassElement,
            Element,
            Elements,
            FunctionElement,
            LibraryElement,
            MetadataAnnotation,
            ScopeContainerElement;

import 'util/util.dart'
       show Link;

import 'tree/tree.dart'
       show LibraryTag,
            Node,
            Visitor;

import 'resolution/resolution.dart'
       show TreeElements;

class DeferredLoadTask extends CompilerTask {
  final Set<LibraryElement> deferredLibraries =
      new LinkedHashSet<LibraryElement>();

  /// Records all elements that are deferred.
  ///
  /// Long term, we want to split deferred element into more than one
  /// file (one for each library that is deferred), and this field
  /// should become obsolete.
  final Set<Element> allDeferredElements = new LinkedHashSet<Element>();

  DeferredLoadTask(Compiler compiler) : super(compiler);

  String get name => 'Deferred Loading';

  /// DeferredLibrary from dart:async
  ClassElement get deferredLibraryClass => compiler.deferredLibraryClass;

  bool get areAnyElementsDeferred => !allDeferredElements.isEmpty;

  bool isDeferred(Element element) {
    element = element.implementation;
    return allDeferredElements.contains(element);
  }

  bool isExplicitlyDeferred(Element element) {
    element = element.implementation;
    return deferredLibraries.contains(element.getLibrary());
  }

  void onResolutionComplete(FunctionElement main) {
    if (main == null) return;
    LibraryElement mainApp = main.getLibrary();
    measureElement(mainApp, () {
      deferredLibraries.addAll(findDeferredLibraries(mainApp).toList());
      if (deferredLibraries.isEmpty) return;

      // TODO(ahe): Enforce the following invariants on
      // [deferredElements] and [eagerElements]:
      // 1. Only static or top-level elements are recorded.
      // 2. Only implementation is stored.
      Map<LibraryElement, Set<Element>> deferredElements =
          new LinkedHashMap<LibraryElement, Set<Element>>();
      Set<Element> eagerElements = new LinkedHashSet<Element>();

      // Iterate through live local members of the main script.  Create
      // a root-set of elements that must be loaded eagerly
      // (everything that is directly referred to from the main
      // script, but not imported from a deferred library), as well as
      // root-sets for deferred libraries.
      mainApp.forEachLocalMember((Element e) {
        if (compiler.enqueuer.resolution.isLive(e)) {
          for (Element dependency in allElementsResolvedFrom(e)) {
            if (isExplicitlyDeferred(dependency)) {
              Set<Element> deferredElementsFromLibrary =
                  deferredElements.putIfAbsent(
                      dependency.getLibrary(),
                      () => new LinkedHashSet<Element>());
              deferredElementsFromLibrary.add(dependency);
            } else if (dependency.getLibrary() != mainApp) {
              eagerElements.add(dependency.implementation);
            }
          }
        }
      });

      // Also add "global" dependencies to the eager root-set.  These
      // are things that the backend need but cannot associate with a
      // particular element, for example, startRootIsolate.  This set
      // also contains elements for which we lack precise information.
      eagerElements.addAll(compiler.globalDependencies.otherDependencies);

      addTransitiveClosureTo(eagerElements);

      for (Set<Element> e in deferredElements.values) {
        addTransitiveClosureTo(e);
        e.removeAll(eagerElements);
        for (Element element in e) {
          allDeferredElements.add(element);
        }
      }

      // TODO(ahe): The following code has no effect yet.  I'm
      // including it as a comment for how to extend this to support
      // multiple deferred files.
      Map<Element, List<LibraryElement>> reverseMap =
          new LinkedHashMap<Element, List<LibraryElement>>();

      deferredElements.forEach((LibraryElement library, Set<Element> map) {
        for (Element element in map) {
          List<LibraryElement> libraries =
              reverseMap.putIfAbsent(element, () => <LibraryElement>[]);
          libraries.add(library);
        }
      });

      // Now compute the output files based on the lists in reverseMap.
      // TODO(ahe): Do that.
    });
  }

  /// Returns all elements in the tree map of [element], but not the
  /// transitive closure.
  Set<Element> allElementsResolvedFrom(Element element) {
    element = element.implementation;
    Set<Element> result = new LinkedHashSet<Element>();
    if (element.isGenerativeConstructor()) {
      // When instantiating a class, we record a reference to the
      // constructor, not the class itself.  We must add all the
      // instance members of the constructor's class (see below).
      result.addAll(
          allElementsResolvedFrom(element.getEnclosingClass().implementation));
    }
    if (element.isClass()) {
      // If we see a class, add everything its instance members refer
      // to.  Static members are not relevant.
      ClassElement cls = element.declaration;
      cls.forEachLocalMember((Element e) {
        if (!e.isInstanceMember()) return;
        result.addAll(DependencyCollector.collect(e.implementation, compiler));
      });
      if (cls.implementation != cls) {
        // TODO(ahe): Why doesn't ClassElement.forEachLocalMember do this?
        cls.implementation.forEachLocalMember((Element e) {
          if (!e.isInstanceMember()) return;
          result.addAll(DependencyCollector.collect(e.implementation,
                                                    compiler));
        });
      }
      for (var type in cls.allSupertypes) {
        result.add(type.element.implementation);
      }
      result.add(cls.implementation);
    } else if (Elements.isStaticOrTopLevel(element)
               || element.isConstructor()) {
      result.addAll(DependencyCollector.collect(element, compiler));
    }
    // Other elements, in particular instance members, are ignored as
    // they are processed as part of the class.
    return result;
  }

  void addTransitiveClosureTo(Set<Element> elements) {
    Set<Element> workSet = new LinkedHashSet.from(elements);
    Set<Element> closure = new LinkedHashSet<Element>();
    while (!workSet.isEmpty) {
      Element current = workSet.first;
      workSet.remove(current);
      if (closure.contains(current)) continue;
      workSet.addAll(allElementsResolvedFrom(current));
      closure.add(current);
    }
    elements.addAll(closure);
  }

  Link<LibraryElement> findDeferredLibraries(LibraryElement library) {
    Link<LibraryElement> link = const Link<LibraryElement>();
    for (LibraryTag tag in library.tags) {
      // TODO(ahe): This iterates over parts and exports as well, but should
      // only iterate over imports.
      Link<MetadataAnnotation> metadata = tag.metadata;
      if (metadata == null) continue;
      for (MetadataAnnotation metadata in tag.metadata) {
        metadata.ensureResolved(compiler);
        Element element = metadata.value.computeType(compiler).element;
        if (element == deferredLibraryClass) {
          ConstructedConstant value = metadata.value;
          StringConstant nameField = value.fields[0];
          SourceString expectedName = nameField.toDartString().source;
          LibraryElement deferredLibrary = library.getLibraryFromTag(tag);
          link = link.prepend(deferredLibrary);
          SourceString actualName =
              new SourceString(deferredLibrary.getLibraryOrScriptName());
          if (expectedName != actualName) {
            compiler.reportError(
                metadata,
                MessageKind.DEFERRED_LIBRARY_NAME_MISMATCH,
                { 'expectedName': expectedName.slowToString(),
                  'actualName': actualName.slowToString()});
          }
        }
      }
    }
    return link;
  }
}

class DependencyCollector extends Visitor {
  final Set<Element> dependencies = new LinkedHashSet<Element>();
  final TreeElements elements;
  final Compiler compiler;

  DependencyCollector(this.elements, this.compiler);

  visitNode(Node node) {
    node.visitChildren(this);
    Element dependency = elements[node];
    if (Elements.isUnresolved(dependency)) return;
    dependencies.add(dependency.implementation);
  }

  static Set<Element> collect(Element element, Compiler compiler) {
    TreeElements elements =
        compiler.enqueuer.resolution.getCachedElements(element);
    if (elements == null) return new LinkedHashSet<Element>();
    Node node = element.parseNode(compiler);
    if (node == null) return new LinkedHashSet<Element>();
    var collector = new DependencyCollector(elements, compiler);
    node.accept(collector);
    collector.dependencies.addAll(elements.otherDependencies);
    return collector.dependencies;
  }
}
