// Copyright (c) 2015, 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.serialization;

import '../elements/elements.dart';
import '../constants/expressions.dart';
import '../dart_types.dart';
import '../util/enumset.dart';

import 'constant_serialization.dart';
import 'element_serialization.dart';
import 'json_serializer.dart';
import 'keys.dart';
import 'type_serialization.dart';
import 'values.dart';

export 'task.dart' show LibraryDeserializer;

/// An object that supports the encoding an [ObjectValue] for serialization.
///
/// The [ObjectEncoder] ensures that nominality and circularities of
/// non-primitive values like [Element], [DartType] and [ConstantExpression] are
/// handled.
class ObjectEncoder extends AbstractEncoder<Key> {
  /// Creates an [ObjectEncoder] in the scope of [serializer] that uses [map]
  /// as its internal storage.
  ObjectEncoder(Serializer serializer, Map<dynamic, Value> map)
        : super(serializer, map);

  String get _name => 'Object';
}

/// An object that supports the encoding a [MapValue] for serialization.
///
/// The [MapEncoder] ensures that nominality and circularities of
/// non-primitive values like [Element], [DartType] and [ConstantExpression] are
/// handled.
class MapEncoder extends AbstractEncoder<String> {
  /// Creates an [MapEncoder] in the scope of [serializer] that uses [map]
  /// as its internal storage.
  MapEncoder(Serializer serializer, Map<String, Value> map)
      : super(serializer, map);

  String get _name => 'Map';
}

/// An object that supports the encoding a [ListValue] containing [ObjectValue]s
/// or [MapValue]s.
///
/// The [ListEncoder] ensures that nominality and circularities of
/// non-primitive values like [Element], [DartType] and [ConstantExpression] are
/// handled.
class ListEncoder {
  final Serializer _serializer;
  final List<Value> _list;

  /// Creates an [ListEncoder] in the scope of [_serializer] that uses [_list]
  /// as its internal storage.
  ListEncoder(this._serializer, this._list);

  /// Creates an [ObjectEncoder] and adds it to the encoded list.
  ObjectEncoder createObject() {
    Map<Key, Value> map = <Key, Value>{};
    _list.add(new ObjectValue(map));
    return new ObjectEncoder(_serializer, map);
  }

  /// Creates an [ObjectEncoder] and adds it to the encoded list.
  MapEncoder createMap() {
    Map<String, Value> map = {};
    _list.add(new MapValue(map));
    return new MapEncoder(_serializer, map);
  }
}

/// Abstract base implementation for [ObjectEncoder] and [MapEncoder].
abstract class AbstractEncoder<K> {
  final Serializer _serializer;
  final Map<K, Value> _map;

  AbstractEncoder(this._serializer, this._map);

  /// The name of the encoder kind. Use for error reporting.
  String get _name;

  void _checkKey(K key) {
    if (_map.containsKey(key)) {
      throw new StateError("$_name value '$key' already in $_map.");
    }
  }

  /// Maps the [key] entry to the [value] in the encoded object.
  void setValue(K key, Value value) {
    _checkKey(key);
    _map[key] = value;
  }


  /// Maps the [key] entry to the enum [value] in the encoded object.
  void setEnum(K key, var value) {
    _checkKey(key);
    _map[key] = new EnumValue(value);
  }

  /// Maps the [key] entry to the set of enum [values] in the encoded object.
  void setEnums(K key, Iterable values) {
    setEnumSet(key, new EnumSet.fromValues(values));
  }

  /// Maps the [key] entry to the enum [set] in the encoded object.
  void setEnumSet(K key, EnumSet set) {
    _checkKey(key);
    _map[key] = new IntValue(set.value);
  }

  /// Maps the [key] entry to the [element] in the encoded object.
  void setElement(K key, Element element) {
    _checkKey(key);
    _map[key] = _serializer.createElementValue(element);
  }

  /// Maps the [key] entry to the [elements] in the encoded object.
  ///
  /// If [elements] is empty, it is skipped.
  void setElements(K key, Iterable<Element> elements) {
    _checkKey(key);
    if (elements.isNotEmpty) {
      _map[key] = new ListValue(
          elements.map(_serializer.createElementValue).toList());
    }
  }

  /// Maps the [key] entry to the [constant] in the encoded object.
  void setConstant(K key, ConstantExpression constant) {
    _checkKey(key);
    _map[key] = _serializer.createConstantValue(constant);
  }

  /// Maps the [key] entry to the [constants] in the encoded object.
  ///
  /// If [constants] is empty, it is skipped.
  void setConstants(K key, Iterable<ConstantExpression> constants) {
    _checkKey(key);
    if (constants.isNotEmpty) {
      _map[key] = new ListValue(
          constants.map(_serializer.createConstantValue).toList());
    }
  }

  /// Maps the [key] entry to the [type] in the encoded object.
  void setType(K key, DartType type) {
    _checkKey(key);
    _map[key] = _serializer.createTypeValue(type);
  }

  /// Maps the [key] entry to the [types] in the encoded object.
  ///
  /// If [types] is empty, it is skipped.
  void setTypes(K key, Iterable<DartType> types) {
    _checkKey(key);
    if (types.isNotEmpty) {
      _map[key] =
          new ListValue(types.map(_serializer.createTypeValue).toList());
    }
  }

  /// Maps the [key] entry to the [uri] in the encoded object using [baseUri] to
  /// relatives the encoding.
  ///
  /// For instance, a source file like `sdk/lib/core/string.dart` should be
  /// serialized relative to the library root.
  void setUri(K key, Uri baseUri, Uri uri) {
    _checkKey(key);
    _map[key] = new UriValue(baseUri, uri);
  }

  /// Maps the [key] entry to the string [value] in the encoded object.
  void setString(K key, String value) {
    _checkKey(key);
    _map[key] = new StringValue(value);
  }

  /// Maps the [key] entry to the string [values] in the encoded object.
  ///
  /// If [values] is empty, it is skipped.
  void setStrings(K key, Iterable<String> values) {
    _checkKey(key);
    if (values.isNotEmpty) {
      _map[key] = new ListValue(values.map((v) => new StringValue(v)).toList());
    }
  }

  /// Maps the [key] entry to the bool [value] in the encoded object.
  void setBool(K key, bool value) {
    _checkKey(key);
    _map[key] = new BoolValue(value);
  }

  /// Maps the [key] entry to the int [value] in the encoded object.
  void setInt(K key, int value) {
    _checkKey(key);
    _map[key] = new IntValue(value);
  }

  /// Maps the [key] entry to the int [values] in this serializer.
  ///
  /// If [values] is empty, it is skipped.
  void setInts(K key, Iterable<int> values) {
    _checkKey(key);
    if (values.isNotEmpty) {
      _map[key] = new ListValue(values.map((v) => new IntValue(v)).toList());
    }
  }

  /// Maps the [key] entry to the double [value] in the encoded object.
  void setDouble(K key, double value) {
    _checkKey(key);
    _map[key] = new DoubleValue(value);
  }

  /// Creates and returns an [ObjectEncoder] that is mapped to the [key]
  /// entry in the encoded object.
  ObjectEncoder createObject(K key) {
    Map<Key, Value> map = <Key, Value>{};
    _map[key] = new ObjectValue(map);
    return new ObjectEncoder(_serializer, map);
  }

  /// Creates and returns a [MapEncoder] that is mapped to the [key] entry
  /// in the encoded object.
  MapEncoder createMap(K key) {
    Map<String, Value> map = <String, Value>{};
    _map[key] = new MapValue(map);
    return new MapEncoder(_serializer, map);
  }

  /// Creates and returns a [ListEncoder] that is mapped to the [key] entry
  /// in the encoded object.
  ListEncoder createList(K key) {
    List<Value> list = <Value>[];
    _map[key] = new ListValue(list);
    return new ListEncoder(_serializer, list);
  }

  String toString() => _map.toString();
}

/// [ObjectDecoder] reads serialized values from a [Map] encoded from an
/// [ObjectValue] where properties are stored using [Key] values as keys.
class ObjectDecoder extends AbstractDecoder<Key> {
  /// Creates an [ObjectDecoder] that decodes [map] into deserialized values
  /// using [deserializer] to create canonicalized values.
  ObjectDecoder(Deserializer deserializer, Map map)
      : super(deserializer, map);

  @override
  _getKeyValue(Key key) => _deserializer.decoder.getObjectPropertyValue(key);
}

/// [MapDecoder] reads serialized values from a [Map] encoded from an
/// [MapValue] where entries are stored using [String] values as keys.
class MapDecoder extends AbstractDecoder<String> {
  /// Creates an [MapDecoder] that decodes [map] into deserialized values
  /// using [deserializer] to create canonicalized values.
  MapDecoder(Deserializer deserializer, Map<String, dynamic> map)
      : super(deserializer, map);

  @override
  _getKeyValue(String key) => key;

  /// Applies [f] to every key in the decoded [Map].
  void forEachKey(f(String key)) {
    _map.keys.forEach(f);
  }
}

/// [ListDecoder] reads serialized map or object values from a [List].
class ListDecoder {
  final Deserializer _deserializer;
  final List _list;

  /// Creates a [ListDecoder] that decodes [_list] using [_deserializer] to
  /// create canonicalized values.
  ListDecoder(this._deserializer, this._list);

  /// The number of values in the decoded list.
  int get length => _list.length;

  /// Returns an [ObjectDecoder] for the [index]th object value in the decoded
  /// list.
  ObjectDecoder getObject(int index) {
    return new ObjectDecoder(_deserializer, _list[index]);
  }

  /// Returns an [MapDecoder] for the [index]th map value in the decoded list.
  MapDecoder getMap(int index) {
    return new MapDecoder(_deserializer, _list[index]);
  }
}

/// Abstract base implementation for [ObjectDecoder] and [MapDecoder].
abstract class AbstractDecoder<K> {
  final Deserializer _deserializer;
  final Map<K, dynamic> _map;

  AbstractDecoder(this._deserializer, this._map) {
    assert(_deserializer != null);
    assert(_map != null);
  }

  /// Returns the value for [key] defined by the [SerializationDecoder] in used
  /// [_deserializer].
  _getKeyValue(K key);

  /// Returns `true` if [key] has an associated value in the decoded object.
  bool containsKey(K key) => _map.containsKey(_getKeyValue(key));

  /// Returns the enum value from the [enumValues] associated with [key] in the
  /// decoded object.
  ///
  /// If no value is associated with [key], then if [isOptional] is `true`,
  /// [defaultValue] is returned, otherwise an exception is thrown.
  getEnum(K key, List enumValues, {bool isOptional: false, defaultValue}) {
    int value = _map[_getKeyValue(key)];
    if (value == null) {
      if (isOptional || defaultValue != null) {
        return defaultValue;
      }
      throw new StateError("enum value '$key' not found in $_map.");
    }
    return enumValues[value];
  }

  /// Returns the set of enum values associated with [key] in the decoded
  /// object.
  ///
  /// If no value is associated with [key], then if [isOptional] is `true`,
  /// [defaultValue] is returned, otherwise an exception is thrown.
  EnumSet getEnums(K key, {bool isOptional: false}) {
    int value = _map[_getKeyValue(key)];
    if (value == null) {
      if (isOptional) {
        return const EnumSet.fixed(0);
      }
      throw new StateError("enum values '$key' not found in $_map.");
    }
    return new EnumSet.fixed(value);
  }

  /// Returns the [Element] value associated with [key] in the decoded object.
  ///
  /// If no value is associated with [key], then if [isOptional] is `true`,
  /// `null` is returned, otherwise an exception is thrown.
  Element getElement(K key, {bool isOptional: false}) {
    int id = _map[_getKeyValue(key)];
    if (id == null) {
      if (isOptional) {
        return null;
      }
      throw new StateError("Element value '$key' not found in $_map.");
    }
    return _deserializer.deserializeElement(id);
  }

  /// Returns the list of [Element] values associated with [key] in the decoded
  /// object.
  ///
  /// If no value is associated with [key], then if [isOptional] is `true`,
  /// and empty [List] is returned, otherwise an exception is thrown.
  List<Element> getElements(K key, {bool isOptional: false}) {
    List list = _map[_getKeyValue(key)];
    if (list == null) {
      if (isOptional) {
        return const [];
      }
      throw new StateError("Elements value '$key' not found in $_map.");
    }
    return list.map(_deserializer.deserializeElement).toList();
  }

  /// Returns the [ConstantExpression] value associated with [key] in the
  /// decoded object.
  ///
  /// If no value is associated with [key], then if [isOptional] is `true`,
  /// `null` is returned, otherwise an exception is thrown.
  ConstantExpression getConstant(K key, {bool isOptional: false}) {
    int id = _map[_getKeyValue(key)];
    if (id == null) {
      if (isOptional) {
        return null;
      }
      throw new StateError("Constant value '$key' not found in $_map.");
    }
    return _deserializer.deserializeConstant(id);
  }

  /// Returns the list of [ConstantExpression] values associated with [key] in
  /// the decoded object.
  ///
  /// If no value is associated with [key], then if [isOptional] is `true`,
  /// and empty [List] is returned, otherwise an exception is thrown.
  List<ConstantExpression> getConstants(K key, {bool isOptional: false}) {
    List list = _map[_getKeyValue(key)];
    if (list == null) {
      if (isOptional) {
        return const [];
      }
      throw new StateError("Constants value '$key' not found in $_map.");
    }
    return list.map(_deserializer.deserializeConstant).toList();
  }

  /// Returns the [DartType] value associated with [key] in the decoded object.
  ///
  /// If no value is associated with [key], then if [isOptional] is `true`,
  /// `null` is returned, otherwise an exception is thrown.
  DartType getType(K key, {bool isOptional: false}) {
    int id = _map[_getKeyValue(key)];
    if (id == null) {
      if (isOptional) {
        return null;
      }
      throw new StateError("Type value '$key' not found in $_map.");
    }
    return _deserializer.deserializeType(id);
  }

  /// Returns the list of [DartType] values associated with [key] in the decoded
  /// object.
  ///
  /// If no value is associated with [key], then if [isOptional] is `true`,
  /// and empty [List] is returned, otherwise an exception is thrown.
  List<DartType> getTypes(K key, {bool isOptional: false}) {
    List list = _map[_getKeyValue(key)];
    if (list == null) {
      if (isOptional) {
        return const [];
      }
      throw new StateError("Types value '$key' not found in $_map.");
    }
    return list.map(_deserializer.deserializeType).toList();
  }

  /// Returns the [Uri] value associated with [key] in the decoded object.
  ///
  /// If no value is associated with [key], then if [isOptional] is `true`,
  /// [defaultValue] is returned, otherwise an exception is thrown.
  Uri getUri(K key, {bool isOptional: false, Uri defaultValue}) {
    String value = _map[_getKeyValue(key)];
    if (value == null) {
      if (isOptional || defaultValue != null) {
        return defaultValue;
      }
      throw new StateError("Uri value '$key' not found in $_map.");
    }
    return Uri.parse(value);
  }

  /// Returns the [String] value associated with [key] in the decoded object.
  ///
  /// If no value is associated with [key], then if [isOptional] is `true`,
  /// [defaultValue] is returned, otherwise an exception is thrown.
  String getString(K key, {bool isOptional: false, String defaultValue}) {
    String value = _map[_getKeyValue(key)];
    if (value == null) {
      if (isOptional || defaultValue != null) {
        return defaultValue;
      }
      throw new StateError("String value '$key' not found in $_map.");
    }
    return value;
  }

  /// Returns the list of [String] values associated with [key] in the decoded
  /// object.
  ///
  /// If no value is associated with [key], then if [isOptional] is `true`,
  /// and empty [List] is returned, otherwise an exception is thrown.
  List<String> getStrings(K key, {bool isOptional: false}) {
    List list = _map[_getKeyValue(key)];
    if (list == null) {
      if (isOptional) {
        return const [];
      }
      throw new StateError("Strings value '$key' not found in $_map.");
    }
    return list;
  }

  /// Returns the [bool] value associated with [key] in the decoded object.
  ///
  /// If no value is associated with [key], then if [isOptional] is `true`,
  /// [defaultValue] is returned, otherwise an exception is thrown.
  bool getBool(K key, {bool isOptional: false, bool defaultValue}) {
    bool value = _map[_getKeyValue(key)];
    if (value == null) {
      if (isOptional || defaultValue != null) {
        return defaultValue;
      }
      throw new StateError("bool value '$key' not found in $_map.");
    }
    return value;
  }

  /// Returns the [int] value associated with [key] in the decoded object.
  ///
  /// If no value is associated with [key], then if [isOptional] is `true`,
  /// [defaultValue] is returned, otherwise an exception is thrown.
  int getInt(K key, {bool isOptional: false, int defaultValue}) {
    int value = _map[_getKeyValue(key)];
    if (value == null) {
      if (isOptional || defaultValue != null) {
        return defaultValue;
      }
      throw new StateError("int value '$key' not found in $_map.");
    }
    return value;
  }

  /// Returns the list of [int] values associated with [key] in the decoded
  /// object.
  ///
  /// If no value is associated with [key], then if [isOptional] is `true`,
  /// and empty [List] is returned, otherwise an exception is thrown.
  List<int> getInts(K key, {bool isOptional: false}) {
    List list = _map[_getKeyValue(key)];
    if (list == null) {
      if (isOptional) {
        return const [];
      }
      throw new StateError("Ints value '$key' not found in $_map.");
    }
    return list;
  }

  /// Returns the [double] value associated with [key] in the decoded object.
  ///
  /// If no value is associated with [key], then if [isOptional] is `true`,
  /// [defaultValue] is returned, otherwise an exception is thrown.
  double getDouble(K key, {bool isOptional: false, double defaultValue}) {
    double value = _map[_getKeyValue(key)];
    if (value == null) {
      if (isOptional || defaultValue != null) {
        return defaultValue;
      }
      throw new StateError("double value '$key' not found in $_map.");
    }
    return value;
  }

  /// Returns an [ObjectDecoder] for the map value associated with [key] in the
  /// decoded object.
  ///
  /// If no value is associated with [key], then if [isOptional] is `true`,
  /// `null` is returned, otherwise an exception is thrown.
  ObjectDecoder getObject(K key, {bool isOptional: false}) {
    Map map = _map[_getKeyValue(key)];
    if (map == null) {
      if (isOptional) {
        return null;
      }
      throw new StateError("Object value '$key' not found in $_map.");
    }
    return new ObjectDecoder(_deserializer, map);
  }

  /// Returns an [MapDecoder] for the map value associated with [key] in the
  /// decoded object.
  ///
  /// If no value is associated with [key], then if [isOptional] is `true`,
  /// `null` is returned, otherwise an exception is thrown.
  MapDecoder getMap(K key, {bool isOptional: false}) {
    Map map = _map[_getKeyValue(key)];
    if (map == null) {
      if (isOptional) {
        return null;
      }
      throw new StateError("Map value '$key' not found in $_map.");
    }
    return new MapDecoder(_deserializer, map);
  }

  /// Returns an [ListDecoder] for the list value associated with [key] in the
  /// decoded object.
  ///
  /// If no value is associated with [key], then if [isOptional] is `true`,
  /// `null` is returned, otherwise an exception is thrown.
  ListDecoder getList(K key, {bool isOptional: false}) {
    List list = _map[_getKeyValue(key)];
    if (list == null) {
      if (isOptional) {
        return null;
      }
      throw new StateError("List value '$key' not found in $_map.");
    }
    return new ListDecoder(_deserializer, list);
  }
}

/// A nominal object containing its serialized value.
class DataObject {
  /// The id for the object.
  final Value id;

  /// The serialized value of the object.
  final ObjectValue objectValue;

  DataObject(Value id, EnumValue kind)
      : this.id = id,
        this.objectValue =
            new ObjectValue(<Key, Value>{Key.ID: id, Key.KIND: kind});

  Map<Key, Value> get map => objectValue.map;
}

/// Function used to filter which element serialized.
typedef bool ElementMatcher(Element element);

bool includeAllElements(Element element) => true;

/// Serializer for the transitive closure of a collection of libraries.
///
/// The serializer creates an [ObjectValue] model of the [Element], [DartType]
/// and [ConstantExpression] values in the transitive closure of the serialized
/// libraries.
///
/// The model layout of the produced [objectValue] is:
///
///     { // Header object
///       Key.ELEMENTS: [
///         {...}, // [ObjectValue] of the 0th [Element].
///         ...
///         {...}, // [ObjectValue] of the n-th [Element].
///       ],
///       Key.TYPES: [
///         {...}, // [ObjectValue] of the 0th [DartType].
///         ...
///         {...}, // [ObjectValue] of the n-th [DartType].
///       ],
///       Key.CONSTANTS: [
///         {...}, // [ObjectValue] of the 0th [ConstantExpression].
///         ...
///         {...}, // [ObjectValue] of the n-th [ConstantExpression].
///       ],
///     }
///
// TODO(johnniwinther): Support dependencies between serialized subcomponent.
class Serializer {
  List<SerializerPlugin> plugins = <SerializerPlugin>[];

  Map<Uri, dynamic> _dependencyMap = <Uri, dynamic>{};
  Map<Element, DataObject> _elementMap = <Element, DataObject>{};
  Map<ConstantExpression, DataObject> _constantMap =
      <ConstantExpression, DataObject>{};
  Map<DartType, DataObject> _typeMap = <DartType, DataObject>{};
  List _pendingList = [];
  ElementMatcher shouldInclude;

  // TODO(johnniwinther): Replace [includeElement] with a general strategy.
  Serializer({this.shouldInclude: includeAllElements});

  /// Add the transitive closure of [library] to this serializer.
  void serialize(LibraryElement library) {
    // Call [_getElementId] for its side-effect: To create a
    // [DataObject] for [library]. If not already created, this will
    // put the serialization of [library] in the work queue.
    _getElementId(library);
  }

  void _emptyWorklist() {
    while (_pendingList.isNotEmpty) {
      _pendingList.removeLast()();
    }
  }

  /// Returns the id [Value] for [element].
  ///
  /// If [element] has no [DataObject], a new [DataObject] is created and
  /// encoding the [ObjectValue] for [element] is put into the work queue of
  /// this serializer.
  Value _getElementId(Element element) {
    if (element == null) {
      throw new ArgumentError('Serializer._getElementDataObject(null)');
    }
    DataObject dataObject = _elementMap[element];
    if (dataObject == null) {
      if (!shouldInclude(element)) {
        if (element.isLibrary) {
          LibraryElement library = element;
          _elementMap[element] = dataObject = new DataObject(
              new IntValue(_elementMap.length),
              new EnumValue(SerializedElementKind.EXTERNAL_LIBRARY));
          ObjectEncoder encoder = new ObjectEncoder(this, dataObject.map);
          encoder.setUri(Key.URI, library.canonicalUri, library.canonicalUri);
        } else if (element.isStatic) {
          Value classId =_getElementId(element.enclosingClass);
          _elementMap[element] = dataObject = new DataObject(
              new IntValue(_elementMap.length),
              new EnumValue(SerializedElementKind.EXTERNAL_STATIC_MEMBER));
          ObjectEncoder encoder = new ObjectEncoder(this, dataObject.map);
          encoder.setValue(Key.CLASS, classId);
          encoder.setString(Key.NAME, element.name);
        } else if (element.isConstructor) {
          Value classId =_getElementId(element.enclosingClass);
          _elementMap[element] = dataObject = new DataObject(
              new IntValue(_elementMap.length),
              new EnumValue(SerializedElementKind.EXTERNAL_CONSTRUCTOR));
          ObjectEncoder encoder = new ObjectEncoder(this, dataObject.map);
          encoder.setValue(Key.CLASS, classId);
          encoder.setString(Key.NAME, element.name);
        } else {
          Value libraryId =_getElementId(element.library);
          _elementMap[element] = dataObject = new DataObject(
              new IntValue(_elementMap.length),
              new EnumValue(SerializedElementKind.EXTERNAL_LIBRARY_MEMBER));
          ObjectEncoder encoder = new ObjectEncoder(this, dataObject.map);
          encoder.setValue(Key.LIBRARY, libraryId);
          encoder.setString(Key.NAME, element.name);
        }
      } else {
        // Run through [ELEMENT_SERIALIZERS] sequentially to find the one that
        // deals with [element].
        for (ElementSerializer serializer in ELEMENT_SERIALIZERS) {
          SerializedElementKind kind = serializer.getSerializedKind(element);
          if (kind != null) {
            _elementMap[element] = dataObject = new DataObject(
                new IntValue(_elementMap.length), new EnumValue(kind));
            // Delay the serialization of the element itself to avoid loops, and
            // to keep the call stack small.
            _pendingList.add(() {
              ObjectEncoder encoder = new ObjectEncoder(this, dataObject.map);
              serializer.serialize(element, encoder, kind);

              MapEncoder pluginData;
              for (SerializerPlugin plugin in plugins) {
                plugin.onElement(element, (String tag) {
                  if (pluginData == null) {
                    pluginData = encoder.createMap(Key.DATA);
                  }
                  return pluginData.createObject(tag);
                });
              }
            });
          }
        }
      }
    }
    if (dataObject == null) {
      throw new UnsupportedError(
          'Unsupported element: $element (${element.kind})');
    }
    return dataObject.id;
  }

  /// Creates the [ElementValue] for [element].
  ///
  /// If [element] has not already been serialized, it is added to the work
  /// queue of this serializer.
  ElementValue createElementValue(Element element) {
    return new ElementValue(element, _getElementId(element));
  }

  /// Returns the id [Value] for [constant].
  ///
  /// If [constant] has no [DataObject], a new [DataObject] is created and
  /// encoding the [ObjectValue] for [constant] is put into the work queue of
  /// this serializer.
  Value _getConstantId(ConstantExpression constant) {
    return _constantMap.putIfAbsent(constant, () {
      DataObject dataObject = new DataObject(
          new IntValue(_constantMap.length), new EnumValue(constant.kind));
      // Delay the serialization of the constant itself to avoid loops, and to
      // keep the call stack small.
      _pendingList.add(() => _encodeConstant(constant, dataObject));
      return dataObject;
    }).id;
  }

  /// Encodes [constant] into the [ObjectValue] of [dataObject].
  void _encodeConstant(ConstantExpression constant, DataObject dataObject) {
    const ConstantSerializer().visit(constant,
        new ObjectEncoder(this, dataObject.map));
  }

  /// Creates the [ConstantValue] for [constant].
  ///
  /// If [constant] has not already been serialized, it is added to the work
  /// queue of this serializer.
  ConstantValue createConstantValue(ConstantExpression constant) {
    return new ConstantValue(constant, _getConstantId(constant));
  }

  /// Returns the id [Value] for [type].
  ///
  /// If [type] has no [DataObject], a new [DataObject] is created and
  /// encoding the [ObjectValue] for [type] is put into the work queue of this
  /// serializer.
  Value _getTypeId(DartType type) {
    DataObject dataObject = _typeMap[type];
    if (dataObject == null) {
      _typeMap[type] = dataObject = new DataObject(
          new IntValue(_typeMap.length), new EnumValue(type.kind));
      // Delay the serialization of the type itself to avoid loops, and to keep
      // the call stack small.
      _pendingList.add(() => _encodeType(type, dataObject));
    }
    return dataObject.id;
  }

  /// Encodes [type] into the [ObjectValue] of [dataObject].
  void _encodeType(DartType type, DataObject dataObject) {
    const TypeSerializer().visit(type, new ObjectEncoder(this, dataObject.map));
  }

  /// Creates the [TypeValue] for [type].
  ///
  /// If [type] has not already been serialized, it is added to the work
  /// queue of this serializer.
  TypeValue createTypeValue(DartType type) {
    return new TypeValue(type, _getTypeId(type));
  }

  ObjectValue get objectValue {
    _emptyWorklist();

    Map<Key, Value> map = <Key, Value>{};
    map[Key.ELEMENTS] =
        new ListValue(_elementMap.values.map((l) => l.objectValue).toList());
    if (_typeMap.isNotEmpty) {
      map[Key.TYPES] =
          new ListValue(_typeMap.values.map((l) => l.objectValue).toList());
    }
    if (_constantMap.isNotEmpty) {
      map[Key.CONSTANTS] =
          new ListValue(_constantMap.values.map((l) => l.objectValue).toList());
    }
    return new ObjectValue(map);
  }

  String toText(SerializationEncoder encoder) {
    return encoder.encode(objectValue);
  }

  String prettyPrint() {
    PrettyPrintEncoder encoder = new PrettyPrintEncoder();
    return encoder.toText(objectValue);
  }
}

/// Plugin for serializing additional data for an [Element].
class SerializerPlugin {
  const SerializerPlugin();

  /// Called upon the serialization of [element].
  ///
  /// Use [creatorEncoder] to create a data object with id [tag] for storing
  /// additional data for [element].
  void onElement(Element element, ObjectEncoder createEncoder(String tag)) {}
}

/// Plugin for deserializing additional data for an [Element].
class DeserializerPlugin {
  const DeserializerPlugin();

  /// Called upon the deserialization of [element].
  ///
  /// Use [getDecoder] to retrieve the data object with id [tag] stored for
  /// [element]. If not object is stored for [tag], [getDecoder] returns `null`.
  void onElement(Element element, ObjectDecoder getDecoder(String tag)) {}
}

/// Context for parallel deserialization.
class DeserializationContext {
  Map<Uri, LibraryElement> _uriMap = <Uri, LibraryElement>{};
  List<Deserializer> deserializers = <Deserializer>[];

  LibraryElement lookupLibrary(Uri uri) {
    return _uriMap.putIfAbsent(uri, () {
      for (Deserializer deserializer in deserializers) {
        LibraryElement library = deserializer.lookupLibrary(uri);
        if (library != null) {
          return library;
        }
      }
      return null;
    });
  }
}

/// Deserializer for a closed collection of libraries.
// TODO(johnniwinther): Support per-library deserialization and dependencies
// between deserialized subcomponent.
class Deserializer {
  final DeserializationContext context;
  final SerializationDecoder decoder;
  List<DeserializerPlugin> plugins = <DeserializerPlugin>[];
  ObjectDecoder _headerObject;
  ListDecoder _elementList;
  ListDecoder _typeList;
  ListDecoder _constantList;
  Map<int, Element> _elementMap = {};
  Map<int, DartType> _typeMap = {};
  Map<int, ConstantExpression> _constantMap = {};

  Deserializer.fromText(this.context, String text, this.decoder) {
    _headerObject = new ObjectDecoder(this, decoder.decode(text));
    context.deserializers.add(this);
  }

  /// Returns the [ListDecoder] for the [Element]s in this deserializer.
  ListDecoder get elements {
    if (_elementList == null) {
      _elementList = _headerObject.getList(Key.ELEMENTS);
    }
    return _elementList;
  }

  /// Returns the [ListDecoder] for the [DartType]s in this deserializer.
  ListDecoder get types {
    if (_typeList == null) {
      _typeList = _headerObject.getList(Key.TYPES);
    }
    return _typeList;
  }

  /// Returns the [ListDecoder] for the [ConstantExpression]s in this
  /// deserializer.
  ListDecoder get constants {
    if (_constantList == null) {
      _constantList = _headerObject.getList(Key.CONSTANTS);
    }
    return _constantList;
  }

  /// Returns the [LibraryElement] for [uri] if part of the deserializer.
  LibraryElement lookupLibrary(Uri uri) {
    // TODO(johnniwinther): Libraries should be stored explicitly in the header.
    ListDecoder list = elements;
    for (int i = 0; i < list.length; i++) {
      ObjectDecoder object = list.getObject(i);
      SerializedElementKind kind =
          object.getEnum(Key.KIND, SerializedElementKind.values);
      if (kind == SerializedElementKind.LIBRARY) {
        Uri libraryUri = object.getUri(Key.CANONICAL_URI);
        if (libraryUri == uri) {
          return deserializeElement(object.getInt(Key.ID));
        }
      }
    }
    return null;
  }

  /// Returns the deserialized [Element] for [id].
  Element deserializeElement(int id) {
    if (id == null) throw new ArgumentError('Deserializer.getElement(null)');
    Element element = _elementMap[id];
    if (element == null) {
      ObjectDecoder decoder = elements.getObject(id);
      SerializedElementKind elementKind =
          decoder.getEnum(Key.KIND, SerializedElementKind.values);
      if (elementKind == SerializedElementKind.EXTERNAL_LIBRARY) {
        Uri uri = decoder.getUri(Key.URI);
        element = context.lookupLibrary(uri);
        if (element == null) {
          throw new StateError("Missing library for $uri.");
        }
      } else if (elementKind == SerializedElementKind.EXTERNAL_LIBRARY_MEMBER) {
        LibraryElement library = decoder.getElement(Key.LIBRARY);
        String name = decoder.getString(Key.NAME);
        element = library.find(name);
        if (element == null) {
          throw new StateError("Missing library member for $name in $library.");
        }
      } else if (elementKind == SerializedElementKind.EXTERNAL_STATIC_MEMBER) {
        ClassElement cls = decoder.getElement(Key.CLASS);
        String name = decoder.getString(Key.NAME);
        element = cls.lookupLocalMember(name);
        if (element == null) {
          throw new StateError("Missing static member for $name in $cls.");
        }
      } else if (elementKind == SerializedElementKind.EXTERNAL_CONSTRUCTOR) {
        ClassElement cls = decoder.getElement(Key.CLASS);
        String name = decoder.getString(Key.NAME);
        element = cls.lookupConstructor(name);
        if (element == null) {
          throw new StateError("Missing constructor for $name in $cls.");
        }
      } else {
        element = ElementDeserializer.deserialize(decoder, elementKind);
      }
      _elementMap[id] = element;

      MapDecoder pluginData = decoder.getMap(Key.DATA, isOptional: true);
      // Call plugins even when there is no data, so they can take action in
      // this case.
      for (DeserializerPlugin plugin in plugins) {
        plugin.onElement(element,
          (String tag) => pluginData?.getObject(tag, isOptional: true));
      }
    }
    return element;
  }

  /// Returns the deserialized [DartType] for [id].
  DartType deserializeType(int id) {
    if (id == null) throw new ArgumentError('Deserializer.getType(null)');
    return _typeMap.putIfAbsent(id, () {
      return TypeDeserializer.deserialize(types.getObject(id));
    });
  }

  /// Returns the deserialized [ConstantExpression] for [id].
  ConstantExpression deserializeConstant(int id) {
    if (id == null) throw new ArgumentError('Deserializer.getConstant(null)');
    return _constantMap.putIfAbsent(id, () {
      return ConstantDeserializer.deserialize(constants.getObject(id));
    });
  }
}

/// Strategy used by [Serializer] to define the memory and output encoding.
abstract class SerializationEncoder {
  /// Encode [objectValue] into text.
  String encode(ObjectValue objectValue);
}

/// Strategy used by [Deserializer] for decoding and reading data from a
/// serialized output.
abstract class SerializationDecoder {
  /// Decode [text] into [Map] containing the data corresponding to an encoding
  /// of the serializer header object.
  Map decode(String text);

  /// Returns the value used to store [key] as a property in the encoding an
  /// [ObjectValue].
  ///
  /// Different encodings have different restrictions and capabilities as how
  /// to store a [Key] value. For instance: A JSON encoding needs to convert
  /// [Key] to a [String] to store it in a JSON object; a Dart encoding can
  /// choose to store a [Key] as an [int] or as the [Key] itself.
  getObjectPropertyValue(Key key);
}
