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

library services.src.index.store.split_store;

import 'dart:async';
import 'dart:collection';
import 'dart:typed_data';

import 'package:analysis_server/plugin/index/index_core.dart';
import 'package:analysis_server/src/analysis_server.dart';
import 'package:analysis_server/src/services/index/index.dart';
import 'package:analysis_server/src/services/index/index_store.dart';
import 'package:analysis_server/src/services/index/indexable_element.dart';
import 'package:analysis_server/src/services/index/store/codec.dart';
import 'package:analysis_server/src/services/index/store/collection.dart';
import 'package:analyzer/src/generated/ast.dart' show CompilationUnit;
import 'package:analyzer/src/generated/element.dart';
import 'package:analyzer/src/generated/engine.dart';
import 'package:analyzer/src/generated/java_engine.dart';
import 'package:analyzer/src/generated/source.dart';
import 'package:analyzer/src/generated/utilities_general.dart';

/**
 * The implementation of [IndexObjectManager] for indexing
 * [CompilationUnitElement]s.
 */
class DartUnitIndexObjectManager extends IndexObjectManager {
  /**
   * The mapping of library [Source] to the [Source]s of part units.
   */
  Map<AnalysisContext, Map<Source, Set<Source>>> _contextToLibraryToUnits =
      new HashMap<AnalysisContext, Map<Source, Set<Source>>>();

  /**
   * The mapping of unit [Source] to the [Source]s of libraries it is used in.
   */
  Map<AnalysisContext, Map<Source, Set<Source>>> _contextToUnitToLibraries =
      new HashMap<AnalysisContext, Map<Source, Set<Source>>>();

  @override
  String aboutToIndex(AnalysisContext context, Object object) {
    CompilationUnitElement unitElement;
    if (object is CompilationUnit) {
      unitElement = object.element;
    } else if (object is CompilationUnitElement) {
      unitElement = object;
    }
    // validate unit
    if (unitElement == null) {
      return null;
    }
    LibraryElement libraryElement = unitElement.library;
    if (libraryElement == null) {
      return null;
    }
    CompilationUnitElement definingUnitElement =
        libraryElement.definingCompilationUnit;
    if (definingUnitElement == null) {
      return null;
    }
    // prepare sources
    Source library = definingUnitElement.source;
    Source unit = unitElement.source;
    // special handling for the defining library unit
    if (unit == library) {
      // prepare new parts
      HashSet<Source> newParts = new HashSet<Source>();
      for (CompilationUnitElement part in libraryElement.parts) {
        newParts.add(part.source);
      }
      // prepare old parts
      Map<Source, Set<Source>> libraryToUnits =
          _contextToLibraryToUnits[context];
      if (libraryToUnits == null) {
        libraryToUnits = new HashMap<Source, Set<Source>>();
        _contextToLibraryToUnits[context] = libraryToUnits;
      }
      Set<Source> oldParts = libraryToUnits[library];
      // check if some parts are not in the library now
      if (oldParts != null) {
        Set<Source> noParts = oldParts.difference(newParts);
        for (Source noPart in noParts) {
          String nodeName = _getNodeName(library, noPart);
          site.removeNodeByName(context, nodeName);
          site.removeSource(library);
          site.removeSource(noPart);
        }
      }
      // remember new parts
      libraryToUnits[library] = newParts;
    }
    // remember library/unit relations
    _recordUnitInLibrary(context, library, unit);
    _recordLibraryWithUnit(context, library, unit);
    site.addSource(library);
    site.addSource(unit);
    // prepare node
    String nodeName = _getNodeName(library, unit);
    return nodeName;
  }

  @override
  void removeContext(AnalysisContext context) {
    _contextToLibraryToUnits.remove(context);
    _contextToUnitToLibraries.remove(context);
  }

  @override
  void removeSource(AnalysisContext context, Source source) {
    // remove nodes for unit/library pairs
    Map<Source, Set<Source>> unitToLibraries =
        _contextToUnitToLibraries[context];
    if (unitToLibraries != null) {
      Set<Source> libraries = unitToLibraries.remove(source);
      if (libraries != null) {
        for (Source library in libraries) {
          String nodeName = _getNodeName(library, source);
          site.removeNodeByName(context, nodeName);
          site.removeSource(library);
          site.removeSource(source);
        }
      }
    }
    // remove nodes for library/unit pairs
    Map<Source, Set<Source>> libraryToUnits = _contextToLibraryToUnits[context];
    if (libraryToUnits != null) {
      Set<Source> units = libraryToUnits.remove(source);
      if (units != null) {
        for (Source unit in units) {
          String nodeName = _getNodeName(source, unit);
          site.removeNodeByName(context, nodeName);
          site.removeSource(source);
          site.removeSource(unit);
        }
      }
    }
  }

  @override
  void removeSources(AnalysisContext context, SourceContainer container) {
    // remove nodes for unit/library pairs
    Map<Source, Set<Source>> unitToLibraries =
        _contextToUnitToLibraries[context];
    if (unitToLibraries != null) {
      List<Source> units = unitToLibraries.keys.toList();
      for (Source source in units) {
        if (container == null || container.contains(source)) {
          removeSource(context, source);
        }
      }
    }
    // remove nodes for library/unit pairs
    Map<Source, Set<Source>> libraryToUnits = _contextToLibraryToUnits[context];
    if (libraryToUnits != null) {
      List<Source> libraries = libraryToUnits.keys.toList();
      for (Source source in libraries) {
        if (container == null || container.contains(source)) {
          removeSource(context, source);
        }
      }
    }
  }

  String _getNodeName(Source library, Source unit) {
    String libraryName = library != null ? library.fullName : null;
    String unitName = unit.fullName;
    int libraryNameIndex = site.encodeString(libraryName);
    int unitNameIndex = site.encodeString(unitName);
    return 'DartUnitElement_${libraryNameIndex}_${unitNameIndex}.index';
  }

  void _recordLibraryWithUnit(
      AnalysisContext context, Source library, Source unit) {
    Map<Source, Set<Source>> libraryToUnits = _contextToLibraryToUnits[context];
    if (libraryToUnits == null) {
      libraryToUnits = new HashMap<Source, Set<Source>>();
      _contextToLibraryToUnits[context] = libraryToUnits;
    }
    Set<Source> units = libraryToUnits[library];
    if (units == null) {
      units = new HashSet<Source>();
      libraryToUnits[library] = units;
    }
    units.add(unit);
  }

  void _recordUnitInLibrary(
      AnalysisContext context, Source library, Source unit) {
    Map<Source, Set<Source>> unitToLibraries =
        _contextToUnitToLibraries[context];
    if (unitToLibraries == null) {
      unitToLibraries = new HashMap<Source, Set<Source>>();
      _contextToUnitToLibraries[context] = unitToLibraries;
    }
    Set<Source> libraries = unitToLibraries[unit];
    if (libraries == null) {
      libraries = new HashSet<Source>();
      unitToLibraries[unit] = libraries;
    }
    libraries.add(library);
  }
}

/**
 * A manager for files content.
 */
abstract class FileManager {
  /**
   * Removes all files.
   */
  void clear();

  /**
   * Deletes the file with the given name.
   */
  void delete(String name);

  /**
   * Returns names of all known nodes.
   */
  List<String> inspect_getAllNodeNames();

  /**
   * Read the entire file contents as a list of bytes.
   */
  Future<List<int>> read(String name);

  /**
   * Write a list of bytes to a file.
   */
  Future write(String name, List<int> bytes);
}

/**
 * A [FileManager] based [NodeManager].
 */
class FileNodeManager implements NodeManager {
  static int _VERSION = 1;

  final FileManager _fileManager;
  final Logger _logger;

  final ContextCodec contextCodec;
  final ElementCodec elementCodec;
  final StringCodec stringCodec;
  final RelationshipCodec _relationshipCodec;

  int _locationCount = 0;

  Map<String, int> _nodeLocationCounts = new HashMap<String, int>();

  FileNodeManager(this._fileManager, this._logger, this.stringCodec,
      this.contextCodec, this.elementCodec, this._relationshipCodec);

  @override
  int get locationCount => _locationCount;

  @override
  void clear() {
    _fileManager.clear();
  }

  @override
  Future<IndexNode> getNode(String name) {
    return _fileManager.read(name).then((List<int> bytes) {
      if (bytes == null) {
        return null;
      }
      _DataInputStream stream = new _DataInputStream(bytes);
      return _readNode(stream);
    }).catchError((exception, stackTrace) {
      _logger.logError('Exception during reading index file ${name}',
          new CaughtException(exception, stackTrace));
    });
  }

  /**
   * Returns names of all known nodes.
   */
  List<String> inspect_getAllNodeNames() {
    return _fileManager.inspect_getAllNodeNames();
  }

  @override
  IndexNode newNode(AnalysisContext context) =>
      new IndexNode(context, elementCodec, _relationshipCodec);

  @override
  Future putNode(String name, IndexNode node) {
    // update location count
    {
      _locationCount -= _getLocationCount(name);
      int nodeLocationCount = node.locationCount;
      _nodeLocationCounts[name] = nodeLocationCount;
      _locationCount += nodeLocationCount;
    }
    // write the node
    return new Future.microtask(() {
      return ServerPerformanceStatistics.splitStore.makeCurrentWhile(() {
        _DataOutputStream stream = new _DataOutputStream();
        _writeNode(node, stream);
        var bytes = stream.getBytes();
        return _fileManager.write(name, bytes);
      });
    }).catchError((exception, stackTrace) {
      _logger.logError('Exception during reading index file ${name}',
          new CaughtException(exception, stackTrace));
    });
  }

  @override
  void removeNode(String name) {
    // update location count
    _locationCount -= _getLocationCount(name);
    _nodeLocationCounts.remove(name);
    // remove node
    _fileManager.delete(name);
  }

  int _getLocationCount(String name) {
    int locationCount = _nodeLocationCounts[name];
    return locationCount != null ? locationCount : 0;
  }

  RelationKeyData _readElementRelationKey(_DataInputStream stream) {
    int elementId1 = stream.readInt();
    int elementId2 = stream.readInt();
    int elementId3 = stream.readInt();
    int relationshipId = stream.readInt();
    return new RelationKeyData.forData(
        elementId1, elementId2, elementId3, relationshipId);
  }

  LocationData _readLocationData(_DataInputStream stream) {
    int elementId1 = stream.readInt();
    int elementId2 = stream.readInt();
    int elementId3 = stream.readInt();
    int offset = stream.readInt();
    int length = stream.readInt();
    int flags = stream.readInt();
    return new LocationData.forData(
        elementId1, elementId2, elementId3, offset, length, flags);
  }

  IndexNode _readNode(_DataInputStream stream) {
    // check version
    {
      int version = stream.readInt();
      if (version != _VERSION) {
        throw new StateError(
            'Version ${_VERSION} expected, but ${version} found.');
      }
    }
    // context
    int contextId = stream.readInt();
    AnalysisContext context = contextCodec.decode(contextId);
    if (context == null) {
      return null;
    }
    // relations
    Map<RelationKeyData, List<LocationData>> relations =
        new HashMap<RelationKeyData, List<LocationData>>();
    int numRelations = stream.readInt();
    for (int i = 0; i < numRelations; i++) {
      RelationKeyData key = _readElementRelationKey(stream);
      int numLocations = stream.readInt();
      List<LocationData> locations = new List<LocationData>();
      for (int j = 0; j < numLocations; j++) {
        locations.add(_readLocationData(stream));
      }
      relations[key] = locations;
    }
    // create IndexNode
    IndexNode node = new IndexNode(context, elementCodec, _relationshipCodec);
    node.relations = relations;
    return node;
  }

  void _writeElementRelationKey(_DataOutputStream stream, RelationKeyData key) {
    stream.writeInt(key.elementId1);
    stream.writeInt(key.elementId2);
    stream.writeInt(key.elementId3);
    stream.writeInt(key.relationshipId);
  }

  void _writeNode(IndexNode node, _DataOutputStream stream) {
    // version
    stream.writeInt(_VERSION);
    // context
    {
      AnalysisContext context = node.context;
      int contextId = contextCodec.encode(context);
      stream.writeInt(contextId);
    }
    // relations
    Map<RelationKeyData, List<LocationData>> relations = node.relations;
    stream.writeInt(relations.length);
    relations.forEach((key, locations) {
      _writeElementRelationKey(stream, key);
      stream.writeInt(locations.length);
      for (LocationData location in locations) {
        stream.writeInt(location.elementId1);
        stream.writeInt(location.elementId2);
        stream.writeInt(location.elementId3);
        stream.writeInt(location.offset);
        stream.writeInt(location.length);
        stream.writeInt(location.flags);
      }
    });
  }
}

/**
 * A single index file in-memory presentation.
 */
class IndexNode {
  final AnalysisContext context;

  final ElementCodec _elementCodec;
  final RelationshipCodec _relationshipCodec;

  Map<RelationKeyData, List<LocationData>> _relations =
      new HashMap<RelationKeyData, List<LocationData>>();

  IndexNode(this.context, this._elementCodec, this._relationshipCodec);

  /**
   * Returns number of locations in this node.
   */
  int get locationCount {
    int locationCount = 0;
    for (List<LocationData> locations in _relations.values) {
      locationCount += locations.length;
    }
    return locationCount;
  }

  /**
   * Returns the recorded relations.
   */
  Map<RelationKeyData, List<LocationData>> get relations => _relations;

  /**
   * Sets relations data.
   * This method is used during loading data from a storage.
   */
  void set relations(Map<RelationKeyData, List<LocationData>> relations) {
    _relations = relations;
  }

  /**
   * Returns the locations of the elements that have the given relationship with
   * the given element.
   *
   * [element] - the the element that has the relationship with the locations to
   *    be returned.
   * [relationship] - the [RelationshipImpl] between the given [element] and the
   *    locations to be returned
   */
  List<LocationImpl> getRelationships(
      IndexableObject indexable, RelationshipImpl relationship) {
    // prepare key
    RelationKeyData key = new RelationKeyData.forObject(
        _elementCodec, _relationshipCodec, indexable, relationship);
    // find LocationData(s)
    List<LocationData> locationDatas = _relations[key];
    if (locationDatas == null) {
      return LocationImpl.EMPTY_LIST;
    }
    // convert to Location(s)
    List<LocationImpl> locations = <LocationImpl>[];
    for (LocationData locationData in locationDatas) {
      LocationImpl location = locationData.getLocation(context, _elementCodec);
      if (location != null) {
        locations.add(location);
      }
    }
    return locations;
  }

  /**
   * Returns [InspectLocation]s for the element with the given ID.
   */
  List<InspectLocation> inspect_getRelations(String name, int elementId) {
    List<InspectLocation> result = <InspectLocation>[];
    // TODO(scheglov) restore index inspections?
//    _relations.forEach((RelationKeyData key, locations) {
//      if (key.elementId == elementId) {
//        for (LocationData location in locations) {
//          Relationship relationship =
//              _relationshipCodec.decode(key.relationshipId);
//          List<String> path =
//              _elementCodec.inspect_decodePath(location.elementId);
//          result.add(new InspectLocation(name, relationship, path,
//              location.offset, location.length, location.flags));
//        }
//      }
//    });
    return result;
  }

  /**
   * Records that the given [element] and [location] have the given [relationship].
   *
   * [element] - the [Element] that is related to the location.
   * [relationship] - the [RelationshipImpl] between [element] and [location].
   * [location] - the [LocationImpl] where relationship happens.
   */
  void recordRelationship(IndexableObject indexable,
      RelationshipImpl relationship, LocationImpl location) {
    RelationKeyData key = new RelationKeyData.forObject(
        _elementCodec, _relationshipCodec, indexable, relationship);
    // prepare LocationData(s)
    List<LocationData> locationDatas = _relations[key];
    if (locationDatas == null) {
      locationDatas = <LocationData>[];
      _relations[key] = locationDatas;
    }
    // add new LocationData
    locationDatas.add(new LocationData.forObject(_elementCodec, location));
  }
}

/**
 * [SplitIndexStore] uses instances of this class to manager index nodes.
 */
abstract class IndexObjectManager {
  SplitIndexStoreSite site;

  /**
   * Notifies the manager that the given [object] is to be indexed.
   * Returns the name of the index node to put information into.
   */
  String aboutToIndex(AnalysisContext context, Object object);

  /**
   * Notifies the manager that the given [context] is disposed.
   */
  void removeContext(AnalysisContext context);

  /**
   * Notifies the manager that the given [source] is no longer part of
   * the given [context].
   */
  void removeSource(AnalysisContext context, Source source);

  /**
   * Notifies the manager that the sources described by the given [container]
   * are no longer part of the given [context].
   */
  void removeSources(AnalysisContext context, SourceContainer container);
}

class InspectLocation {
  final String nodeName;
  final RelationshipImpl relationship;
  final List<String> path;
  final int offset;
  final int length;
  final int flags;

  InspectLocation(this.nodeName, this.relationship, this.path, this.offset,
      this.length, this.flags);
}

/**
 * A container with information about a [LocationImpl].
 */
class LocationData {
  static const int _FLAG_QUALIFIED = 1 << 0;
  static const int _FLAG_RESOLVED = 1 << 1;

  final int elementId1;
  final int elementId2;
  final int elementId3;
  final int offset;
  final int length;
  final int flags;

  LocationData.forData(this.elementId1, this.elementId2, this.elementId3,
      this.offset, this.length, this.flags);

  LocationData.forObject(ElementCodec elementCodec, LocationImpl location)
      : elementId1 = elementCodec.encode1(location.indexable),
        elementId2 = elementCodec.encode2(location.indexable),
        elementId3 = elementCodec.encode3(location.indexable),
        offset = location.offset,
        length = location.length,
        flags = (location.isQualified ? _FLAG_QUALIFIED : 0) |
            (location.isResolved ? _FLAG_RESOLVED : 0);

  @override
  int get hashCode {
    int hash = 0;
    hash = JenkinsSmiHash.combine(hash, elementId1);
    hash = JenkinsSmiHash.combine(hash, elementId2);
    hash = JenkinsSmiHash.combine(hash, elementId3);
    hash = JenkinsSmiHash.combine(hash, offset);
    hash = JenkinsSmiHash.combine(hash, length);
    return JenkinsSmiHash.finish(hash);
  }

  @override
  bool operator ==(Object obj) {
    if (obj is! LocationData) {
      return false;
    }
    LocationData other = obj;
    return other.elementId1 == elementId1 &&
        other.elementId2 == elementId2 &&
        other.elementId3 == elementId3 &&
        other.offset == offset &&
        other.length == length &&
        other.flags == flags;
  }

  /**
   * Returns a {@link Location} that is represented by this {@link LocationData}.
   */
  LocationImpl getLocation(AnalysisContext context, ElementCodec elementCodec) {
    IndexableObject indexable =
        elementCodec.decode(context, elementId1, elementId2, elementId3);
    if (indexable == null) {
      return null;
    }
    bool isQualified = (flags & _FLAG_QUALIFIED) != 0;
    bool isResovled = (flags & _FLAG_RESOLVED) != 0;
    return new LocationImpl(indexable, offset, length,
        isQualified: isQualified, isResolved: isResovled);
  }
}

/**
 * A manager for [IndexNode]s.
 */
abstract class NodeManager {
  /**
   * The shared {@link ContextCodec} instance.
   */
  ContextCodec get contextCodec;

  /**
   * The shared {@link ElementCodec} instance.
   */
  ElementCodec get elementCodec;

  /**
   * A number of locations in all nodes.
   */
  int get locationCount;

  /**
   * The shared {@link StringCodec} instance.
   */
  StringCodec get stringCodec;

  /**
   * Removes all nodes.
   */
  void clear();

  /**
   * Returns the {@link IndexNode} with the given name, {@code null} if not found.
   */
  Future<IndexNode> getNode(String name);

  /**
   * Returns a new {@link IndexNode}.
   */
  IndexNode newNode(AnalysisContext context);

  /**
   * Associates the given {@link IndexNode} with the given name.
   */
  void putNode(String name, IndexNode node);

  /**
   * Removes the {@link IndexNode} with the given name.
   */
  void removeNode(String name);
}

/**
 * An [Element] to [LocationImpl] relation key.
 */
class RelationKeyData {
  final int elementId1;
  final int elementId2;
  final int elementId3;
  final int relationshipId;

  RelationKeyData.forData(
      this.elementId1, this.elementId2, this.elementId3, this.relationshipId);

  RelationKeyData.forObject(
      ElementCodec elementCodec,
      RelationshipCodec relationshipCodec,
      IndexableObject indexable,
      RelationshipImpl relationship)
      : elementId1 = elementCodec.encode1(indexable),
        elementId2 = elementCodec.encode2(indexable),
        elementId3 = elementCodec.encode3(indexable),
        relationshipId = relationshipCodec.encode(relationship);

  @override
  int get hashCode {
    int hash = 0;
    hash = JenkinsSmiHash.combine(hash, elementId1);
    hash = JenkinsSmiHash.combine(hash, elementId2);
    hash = JenkinsSmiHash.combine(hash, elementId3);
    hash = JenkinsSmiHash.combine(hash, relationshipId);
    return JenkinsSmiHash.finish(hash);
  }

  @override
  bool operator ==(Object obj) {
    if (obj is! RelationKeyData) {
      return false;
    }
    RelationKeyData other = obj;
    return other.elementId1 == elementId1 &&
        other.elementId2 == elementId2 &&
        other.elementId3 == elementId3 &&
        other.relationshipId == relationshipId;
  }

  @override
  String toString() {
    return 'Key($elementId2, $elementId2, $elementId3, $relationshipId)';
  }
}

/**
 * An [InternalIndexStore] which keeps index information in separate nodes for
 * each unit.
 */
class SplitIndexStore implements InternalIndexStore {
  /**
   * The [NodeManager] to get/put [IndexNode]s.
   */
  final NodeManager _nodeManager;

  final List<IndexObjectManager> _objectManagers;

  /**
   * The [ContextCodec] to encode/decode [AnalysisContext]s.
   */
  final ContextCodec _contextCodec;

  /**
   * The [ElementCodec] to encode/decode [Element]s.
   */
  final ElementCodec _elementCodec;

  /**
   * The [StringCodec] to encode/decode [String]s.
   */
  final StringCodec _stringCodec;

  /**
   * Information about top-level elements.
   * We need to keep them together to avoid loading of all index nodes.
   *
   * Order of keys: contextId, nodeId.
   */
  final Map<int, Map<int, List<_TopElementData>>> _topDeclarations =
      new Map<int, Map<int, List<_TopElementData>>>();

  int _currentContextId;
  String _currentNodeName;
  int _currentNodeNameId;
  IndexNode _currentNode;

  /**
   * A table mapping element names to the node names that may have relations with elements with
   * these names.
   */
  final Map<RelationshipImpl, IntToIntSetMap> _relToNameMap =
      new HashMap<RelationshipImpl, IntToIntSetMap>();

  /**
   * The set of known [Source]s.
   */
  final Set<Source> _sources = new HashSet<Source>();

  SplitIndexStore(NodeManager _nodeManager, this._objectManagers)
      : _nodeManager = _nodeManager,
        _contextCodec = _nodeManager.contextCodec,
        _elementCodec = _nodeManager.elementCodec,
        _stringCodec = _nodeManager.stringCodec {
    SplitIndexStoreSiteImpl site = new SplitIndexStoreSiteImpl(this);
    for (IndexObjectManager manager in _objectManagers) {
      manager.site = site;
    }
  }

  @override
  String get statistics {
    StringBuffer buf = new StringBuffer();
    buf.write('[');
    buf.write(_nodeManager.locationCount);
    buf.write(' locations, ');
    buf.write(_sources.length);
    buf.write(' sources, ');
    int namesCount = _relToNameMap.values.fold(0, (c, m) => c + m.length);
    buf.write(namesCount);
    buf.write(' names');
    buf.write(']');
    return buf.toString();
  }

  @override
  bool aboutToIndex(AnalysisContext context, Object object) {
    if (context.isDisposed) {
      return false;
    }
    // try to find a node name
    _currentNodeName = null;
    for (IndexObjectManager manager in _objectManagers) {
      _currentNodeName = manager.aboutToIndex(context, object);
      if (_currentNodeName != null) {
        break;
      }
    }
    if (_currentNodeName == null) {
      return false;
    }
    // prepare node
    _currentNodeNameId = _stringCodec.encode(_currentNodeName);
    _currentNode = _nodeManager.newNode(context);
    _currentContextId = _contextCodec.encode(context);
    // remove top-level information for the current node
    for (Map<int, dynamic> nodeRelations in _topDeclarations.values) {
      nodeRelations.remove(_currentNodeNameId);
    }
    // done
    return true;
  }

  @override
  void cancelIndex() {
    if (_currentNode != null) {
      // remove top-level information for the current node
      for (Map<int, dynamic> nodeRelations in _topDeclarations.values) {
        nodeRelations.remove(_currentNodeNameId);
      }
      // clear fields
      _currentNodeName = null;
      _currentNodeNameId = -1;
      _currentNode = null;
      _currentContextId = -1;
    }
  }

  @override
  void clear() {
    _topDeclarations.clear();
    _nodeManager.clear();
    _relToNameMap.clear();
  }

  @override
  void doneIndex() {
    if (_currentNode != null) {
      _nodeManager.putNode(_currentNodeName, _currentNode);
      _currentNodeName = null;
      _currentNodeNameId = -1;
      _currentNode = null;
      _currentContextId = -1;
    }
  }

  Future<List<LocationImpl>> getRelationships(
      IndexableObject indexable, RelationshipImpl relationship) {
    // prepare node names
    List<int> nodeNameIds;
    {
      int nameId = _elementCodec.encodeHash(indexable);
      IntToIntSetMap nameToNodeNames = _relToNameMap[relationship];
      if (nameToNodeNames != null) {
        nodeNameIds = nameToNodeNames.get(nameId);
      } else {
        nodeNameIds = <int>[];
      }
    }
    // prepare Future(s) for reading each IndexNode
    List<Future<List<LocationImpl>>> nodeFutures =
        <Future<List<LocationImpl>>>[];
    for (int nodeNameId in nodeNameIds) {
      String nodeName = _stringCodec.decode(nodeNameId);
      Future<IndexNode> nodeFuture = _nodeManager.getNode(nodeName);
      Future<List<LocationImpl>> locationsFuture = nodeFuture.then((node) {
        if (node == null) {
          // TODO(scheglov) remove node
          return LocationImpl.EMPTY_LIST;
        }
        return node.getRelationships(indexable, relationship);
      });
      nodeFutures.add(locationsFuture);
    }
    // return Future that merges separate IndexNode Location(s)
    return Future
        .wait(nodeFutures)
        .then((List<List<LocationImpl>> locationsList) {
      List<LocationImpl> allLocations = <LocationImpl>[];
      for (List<LocationImpl> locations in locationsList) {
        allLocations.addAll(locations);
      }
      return allLocations;
    });
  }

  List<Element> getTopLevelDeclarations(ElementNameFilter nameFilter) {
    List<Element> elements = <Element>[];
    _topDeclarations.forEach((contextId, contextLocations) {
      AnalysisContext context = _contextCodec.decode(contextId);
      if (context != null) {
        for (List<_TopElementData> topDataList in contextLocations.values) {
          for (_TopElementData topData in topDataList) {
            if (nameFilter(topData.name)) {
              IndexableObject indexable =
                  topData.getElement(context, _elementCodec);
              if (indexable is IndexableElement) {
                elements.add(indexable.element);
              }
            }
          }
        }
      }
    });
    return elements;
  }

  /**
   * Returns all relations with [Element]s with the given [name].
   */
  Future<Map<List<String>, List<InspectLocation>>> inspect_getElementRelations(
      String name) {
    Map<List<String>, List<InspectLocation>> result =
        <List<String>, List<InspectLocation>>{};
    // TODO(scheglov) restore index inspections?
    return new Future.value(result);
//    // prepare elements
//    Map<int, List<String>> elementMap = _elementCodec.inspect_getElements(name);
//    // prepare relations with each element
//    List<Future> futures = <Future>[];
//    if (_nodeManager is FileNodeManager) {
//      List<String> nodeNames =
//          (_nodeManager as FileNodeManager).inspect_getAllNodeNames();
//      nodeNames.forEach((nodeName) {
//        Future<IndexNode> nodeFuture = _nodeManager.getNode(nodeName);
//        Future relationsFuture = nodeFuture.then((node) {
//          if (node != null) {
//            elementMap.forEach((int elementId, List<String> elementPath) {
//              List<InspectLocation> relations =
//                  node.inspect_getRelations(nodeName, elementId);
//              List<InspectLocation> resultLocations = result[elementPath];
//              if (resultLocations == null) {
//                resultLocations = <InspectLocation>[];
//                result[elementPath] = resultLocations;
//              }
//              resultLocations.addAll(relations);
//            });
//          }
//        });
//        futures.add(relationsFuture);
//      });
//    }
//    // wait for all nodex
//    return Future.wait(futures).then((_) {
//      return result;
//    });
  }

  @override
  void recordRelationship(IndexableObject indexable,
      RelationshipImpl relationship, LocationImpl location) {
    if (indexable == null ||
        (indexable is IndexableElement &&
            indexable.element is MultiplyDefinedElement)) {
      return;
    }
    if (location == null) {
      return;
    }
    // other elements
    _recordNodeNameForElement(indexable, relationship);
    _currentNode.recordRelationship(indexable, relationship, location);
  }

  void recordTopLevelDeclaration(Element element) {
    // in current context
    Map<int, List<_TopElementData>> nodeDeclarations =
        _topDeclarations[_currentContextId];
    if (nodeDeclarations == null) {
      nodeDeclarations = new Map<int, List<_TopElementData>>();
      _topDeclarations[_currentContextId] = nodeDeclarations;
    }
    // in current node
    List<_TopElementData> declarations = nodeDeclarations[_currentNodeNameId];
    if (declarations == null) {
      declarations = <_TopElementData>[];
      nodeDeclarations[_currentNodeNameId] = declarations;
    }
    // record LocationData
    declarations.add(new _TopElementData(
        _elementCodec, element.displayName, new IndexableElement(element)));
  }

  @override
  void removeContext(AnalysisContext context) {
    if (context == null) {
      return;
    }
    // remove sources
    removeSources(context, null);
    // remove context information
    for (IndexObjectManager manager in _objectManagers) {
      manager.removeContext(context);
    }
    _topDeclarations.remove(_contextCodec.encode(context));
    // remove context from codec
    _contextCodec.remove(context);
  }

  @override
  void removeSource(AnalysisContext context, Source source) {
    if (context == null) {
      return;
    }
    for (IndexObjectManager manager in _objectManagers) {
      manager.removeSource(context, source);
    }
  }

  @override
  void removeSources(AnalysisContext context, SourceContainer container) {
    if (context == null) {
      return;
    }
    for (IndexObjectManager manager in _objectManagers) {
      manager.removeSources(context, container);
    }
  }

  void _recordNodeNameForElement(
      IndexableObject indexable, RelationshipImpl relationship) {
    IntToIntSetMap nameToNodeNames = _relToNameMap[relationship];
    if (nameToNodeNames == null) {
      nameToNodeNames = new IntToIntSetMap();
      _relToNameMap[relationship] = nameToNodeNames;
    }
    int nameId = _elementCodec.encodeHash(indexable);
    nameToNodeNames.add(nameId, _currentNodeNameId);
  }

  void _removeNodeByName(AnalysisContext context, String nodeName) {
    int nodeNameId = _stringCodec.encode(nodeName);
    _nodeManager.removeNode(nodeName);
    // remove top-level relations
    {
      int contextId = _contextCodec.encode(context);
      Map<int, dynamic> nodeRelations = _topDeclarations[contextId];
      if (nodeRelations != null) {
        nodeRelations.remove(nodeNameId);
      }
    }
  }
}

/**
 * Interface to [SplitIndexStore] for [IndexObjectManager] implementations.
 */
abstract class SplitIndexStoreSite {
  void addSource(Source source);
  int encodeString(String str);
  void removeNodeByName(AnalysisContext context, String nodeName);
  void removeSource(Source source);
}

/**
 * The implementaiton of [SplitIndexStoreSite].
 */
class SplitIndexStoreSiteImpl implements SplitIndexStoreSite {
  final SplitIndexStore store;

  SplitIndexStoreSiteImpl(this.store);

  @override
  void addSource(Source source) {
    store._sources.add(source);
  }

  @override
  int encodeString(String str) {
    return store._stringCodec.encode(str);
  }

  @override
  void removeNodeByName(AnalysisContext context, String nodeName) {
    store._removeNodeByName(context, nodeName);
  }

  @override
  void removeSource(Source source) {
    store._sources.remove(source);
  }
}

class _DataInputStream {
  ByteData _byteData;
  int _byteOffset = 0;

  _DataInputStream(List<int> bytes) {
    ByteBuffer buffer = new Uint8List.fromList(bytes).buffer;
    _byteData = new ByteData.view(buffer);
  }

  int readInt() {
    int result = _byteData.getInt32(_byteOffset, Endianness.HOST_ENDIAN);
    _byteOffset += 4;
    return result;
  }
}

class _DataOutputStream {
  static const LIST_SIZE = 1024;
  int _size = LIST_SIZE;
  Uint32List _buf = new Uint32List(LIST_SIZE);
  int _pos = 0;

  Uint8List getBytes() {
    return new Uint8List.view(_buf.buffer, 0, _size << 2);
  }

  void writeInt(int value) {
    if (_pos == _size) {
      int newSize = _size << 1;
      Uint32List newBuf = new Uint32List(newSize);
      newBuf.setRange(0, _size, _buf);
      _size = newSize;
      _buf = newBuf;
    }
    _buf[_pos++] = value;
  }
}

class _TopElementData {
  final String name;
  final int elementId1;
  final int elementId2;
  final int elementId3;

  factory _TopElementData(
      ElementCodec elementCodec, String name, IndexableObject indexable) {
    return new _TopElementData._(name, elementCodec.encode1(indexable),
        elementCodec.encode2(indexable), elementCodec.encode3(indexable));
  }

  _TopElementData._(
      this.name, this.elementId1, this.elementId2, this.elementId3);

  IndexableObject getElement(
      AnalysisContext context, ElementCodec elementCodec) {
    return elementCodec.decode(context, elementId1, elementId2, elementId3);
  }
}
