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

class LibraryContents {
  final List<ClassEntity> classes = [];
  final List<MemberEntity> members = [];
  final List<ClassEntity> classTypes = [];
}

/// Maps [LibraryEntity]s to their classes, members, and class types.
///
/// Fundamentally, this class nicely encapsulates a
/// `Map<LibraryEntity, Tuple<classes, members, class types>>`.
///
/// where both classes and class types are lists of [ClassEntity] and
/// members is a list of [MemberEntity].
///
/// There exists exactly one instance per [OutputUnit].
class LibrariesMap {
  final Map<LibraryEntity, LibraryContents> _mapping =
      <LibraryEntity, LibraryContents>{};

  // It is very common to access the same library multiple times in a row, so
  // we cache the last access.
  LibraryEntity _lastLibrary;
  LibraryContents _lastMapping;

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

  LibraryContents _getMapping(LibraryEntity library) {
    if (_lastLibrary != library) {
      _lastLibrary = library;
      _lastMapping = _mapping.putIfAbsent(library, () => new LibraryContents());
    }
    return _lastMapping;
  }

  void addClass(LibraryEntity library, ClassEntity element) {
    _getMapping(library).classes.add(element);
  }

  void addClassType(LibraryEntity library, ClassEntity element) {
    _getMapping(library).classTypes.add(element);
  }

  void addMember(LibraryEntity library, MemberEntity element) {
    _getMapping(library).members.add(element);
  }

  int get length => _mapping.length;

  void forEach(
      void f(LibraryEntity library, List<ClassEntity> classes,
          List<MemberEntity> members, List<ClassEntity> classTypeData)) {
    _mapping.forEach((LibraryEntity library, LibraryContents mapping) {
      f(library, mapping.classes, mapping.members, mapping.classTypes);
    });
  }
}

/// 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 OutputUnit _mainOutputUnit;
  final Sorter _sorter;
  final Map<OutputUnit, LibrariesMap> _deferredLibrariesMap =
      <OutputUnit, LibrariesMap>{};

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

  Iterable<LibrariesMap> get deferredLibrariesMap =>
      _deferredLibrariesMap.values;

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

  LibrariesMap mainLibrariesMap;

  Registry(this._mainOutputUnit, this._sorter);

  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(_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 registerClasses(OutputUnit outputUnit, Iterable<ClassEntity> elements) {
    LibrariesMap targetLibrariesMap = _mapUnitToLibrariesMap(outputUnit);
    for (ClassEntity element in _sorter.sortClasses(elements)) {
      targetLibrariesMap.addClass(element.library, element);
    }
  }

  /// Adds all elements to their respective libraries in the correct
  /// libraries map.
  void registerClassTypes(
      OutputUnit outputUnit, Iterable<ClassEntity> elements) {
    LibrariesMap targetLibrariesMap = _mapUnitToLibrariesMap(outputUnit);
    for (ClassEntity element in _sorter.sortClasses(elements)) {
      targetLibrariesMap.addClassType(element.library, element);
    }
  }

  /// Adds all elements to their respective libraries in the correct
  /// libraries map.
  void registerMembers(OutputUnit outputUnit, Iterable<MemberEntity> elements) {
    LibrariesMap targetLibrariesMap = _mapUnitToLibrariesMap(outputUnit);
    for (MemberEntity element in _sorter.sortMembers(elements)) {
      targetLibrariesMap.addMember(element.library, element);
    }
  }

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