// Copyright (c) 2014, 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.

part of dart2js.js_emitter.program_builder;

/// Maps [LibraryElement]s to their [Element]s.
///
/// Fundamentally, this class nicely encapsulates a
/// `Map<LibraryElement, List<Element>>`.
///
/// There exists exactly one instance per [OutputUnit].
class LibrariesMap {
  final Map<LibraryElement, List<Element>> _mapping =
      <LibraryElement, List<Element>>{};

  // It is very common to access the same library multiple times in a row, so
  // we cache the last access.
  LibraryElement _lastLibrary;
  List<Element> _lastElements;

  /// A unique name representing this instance.
  final String name;
  final OutputUnit outputUnit;

  LibrariesMap.main(this.outputUnit) : name = "";

  LibrariesMap.deferred(this.outputUnit, this.name) {
    assert(name != "");
  }

  void add(LibraryElement library, Element element) {
    if (_lastLibrary != library) {
      _lastLibrary = library;
      _lastElements = _mapping.putIfAbsent(library, () => <Element>[]);
    }
    _lastElements.add(element);
  }

  int get length => _mapping.length;

  void forEach(void f(LibraryElement library, List<Element> elements)) {
    _mapping.forEach(f);
  }
}

/// Keeps track of all elements and holders.
///
/// This class assigns each registered element to its [LibrariesMap] (which are
/// in bijection with [OutputUnit]s).
///
/// Registered holders are assigned a name.
class Registry {
  final Compiler _compiler;
  final Map<String, Holder> _holdersMap = <String, Holder>{};
  final Map<OutputUnit, LibrariesMap> _deferredLibrariesMap =
      <OutputUnit, LibrariesMap>{};

  /// Cache for the last seen output unit.
  OutputUnit _lastOutputUnit;
  LibrariesMap _lastLibrariesMap;

  DeferredLoadTask get _deferredLoadTask => _compiler.deferredLoadTask;
  Iterable<Holder> get holders => _holdersMap.values;
  Iterable<LibrariesMap> get deferredLibrariesMap =>
      _deferredLibrariesMap.values;

  // Add one for the main libraries map.
  int get librariesMapCount => _deferredLibrariesMap.length + 1;

  LibrariesMap mainLibrariesMap;

  Registry(this._compiler);

  bool get _isProgramSplit => _deferredLoadTask.isProgramSplit;
  OutputUnit get _mainOutputUnit => _deferredLoadTask.mainOutputUnit;

  LibrariesMap _mapUnitToLibrariesMap(OutputUnit targetUnit) {
    if (targetUnit == _lastOutputUnit) return _lastLibrariesMap;

    LibrariesMap result = (targetUnit == _mainOutputUnit)
        ? mainLibrariesMap
        : _deferredLibrariesMap[targetUnit];

    assert(result != null);
    _lastOutputUnit = targetUnit;
    _lastLibrariesMap = result;
    return result;
  }

  void registerOutputUnit(OutputUnit outputUnit) {
    if (outputUnit == _mainOutputUnit) {
      assert(mainLibrariesMap == null);
      mainLibrariesMap =
          new LibrariesMap.main(_deferredLoadTask.mainOutputUnit);
    } else {
      assert(!_deferredLibrariesMap.containsKey(outputUnit));
      String name = outputUnit.name;
      _deferredLibrariesMap[outputUnit] =
          new LibrariesMap.deferred(outputUnit, name);
    }
  }

  /// Adds all elements to their respective libraries in the correct
  /// libraries map.
  void registerElements(OutputUnit outputUnit, Iterable<Element> elements) {
    LibrariesMap targetLibrariesMap = _mapUnitToLibrariesMap(outputUnit);
    for (Element element in Elements.sortedByPosition(elements)) {
      targetLibrariesMap.add(element.library, element);
    }
  }

  void registerConstant(OutputUnit outputUnit, ConstantValue constantValue) {
    // Ignore for now.
  }

  Holder registerHolder(String name) {
    return _holdersMap.putIfAbsent(
        name,
        () => new Holder(name, _holdersMap.length));
  }
}