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

/// A [DictionaryTypeMask] is a [TypeMask] for a specific allocation
/// site of a map (currently only internal Map class) that is used as
/// a dictionary, i.e. a mapping from a set of statically known strings
/// to values. These typemasks only come into existence after the
/// [TypeGraphInferrer] has successfully identified such a usage. Otherwise,
/// the more general [MapTypeMask] is used.
class DictionaryTypeMask extends MapTypeMask {
  /// Tag used for identifying serialized [DictionaryTypeMask] objects in a
  /// debugging data stream.
  static const String tag = 'dictionary-type-mask';

  // The underlying key/value map of this dictionary.
  final Map<String, TypeMask> _typeMap;

  const DictionaryTypeMask(
      TypeMask forwardTo,
      ir.Node allocationNode,
      MemberEntity allocationElement,
      TypeMask keyType,
      TypeMask valueType,
      this._typeMap)
      : super(forwardTo, allocationNode, allocationElement, keyType, valueType);

  /// Deserializes a [DictionaryTypeMask] object from [source].
  factory DictionaryTypeMask.readFromDataSource(
      DataSourceReader source, CommonMasks domain) {
    source.begin(tag);
    TypeMask forwardTo = TypeMask.readFromDataSource(source, domain);
    ir.TreeNode allocationNode = source.readTreeNodeOrNull();
    MemberEntity allocationElement = source.readMemberOrNull();
    TypeMask keyType = TypeMask.readFromDataSource(source, domain);
    TypeMask valueType = TypeMask.readFromDataSource(source, domain);
    Map<String, TypeMask> typeMap =
        source.readStringMap(() => TypeMask.readFromDataSource(source, domain));
    source.end(tag);
    return DictionaryTypeMask(forwardTo, allocationNode, allocationElement,
        keyType, valueType, typeMap);
  }

  /// Serializes this [DictionaryTypeMask] to [sink].
  @override
  void writeToDataSink(DataSinkWriter sink) {
    sink.writeEnum(TypeMaskKind.dictionary);
    sink.begin(tag);
    forwardTo.writeToDataSink(sink);
    sink.writeTreeNodeOrNull(allocationNode);
    sink.writeMemberOrNull(allocationElement);
    keyType.writeToDataSink(sink);
    valueType.writeToDataSink(sink);
    sink.writeStringMap(_typeMap, (TypeMask typeMask) {
      typeMask.writeToDataSink(sink);
    });
    sink.end(tag);
  }

  @override
  DictionaryTypeMask withFlags({bool isNullable, bool hasLateSentinel}) {
    isNullable ??= this.isNullable;
    hasLateSentinel ??= this.hasLateSentinel;
    if (isNullable == this.isNullable &&
        hasLateSentinel == this.hasLateSentinel) {
      return this;
    }
    return DictionaryTypeMask(
        forwardTo.withFlags(
            isNullable: isNullable, hasLateSentinel: hasLateSentinel),
        allocationNode,
        allocationElement,
        keyType,
        valueType,
        _typeMap);
  }

  @override
  bool get isDictionary => true;
  @override
  bool get isExact => true;

  bool containsKey(String key) => _typeMap.containsKey(key);

  TypeMask getValueForKey(String key) => _typeMap[key];

  @override
  TypeMask _unionSpecialCases(TypeMask other, CommonMasks domain,
      {bool isNullable, bool hasLateSentinel}) {
    assert(isNullable != null);
    assert(hasLateSentinel != null);
    if (other is DictionaryTypeMask) {
      TypeMask newForwardTo = forwardTo.union(other.forwardTo, domain);
      TypeMask newKeyType = keyType.union(other.keyType, domain);
      TypeMask newValueType = valueType.union(other.valueType, domain);
      Map<String, TypeMask> mappings = {};
      _typeMap.forEach((k, v) {
        if (!other._typeMap.containsKey(k)) {
          mappings[k] = v.nullable();
        }
      });
      other._typeMap.forEach((k, v) {
        if (_typeMap.containsKey(k)) {
          mappings[k] = v.union(_typeMap[k], domain);
        } else {
          mappings[k] = v.nullable();
        }
      });
      return DictionaryTypeMask(
          newForwardTo, null, null, newKeyType, newValueType, mappings);
    }
    if (other is MapTypeMask &&
        (other.keyType != null) &&
        (other.valueType != null)) {
      TypeMask newForwardTo = forwardTo.union(other.forwardTo, domain);
      TypeMask newKeyType = keyType.union(other.keyType, domain);
      TypeMask newValueType = valueType.union(other.valueType, domain);
      return MapTypeMask(newForwardTo, null, null, newKeyType, newValueType);
    }
    return null;
  }

  @override
  bool operator ==(other) {
    if (identical(this, other)) return true;
    if (other is! DictionaryTypeMask) return false;
    return super == other &&
        _typeMap.keys.every((k) => other._typeMap.containsKey(k)) &&
        other._typeMap.keys.every(
            (k) => _typeMap.containsKey(k) && _typeMap[k] == other._typeMap[k]);
  }

  @override
  int get hashCode => Hashing.objectHash(_typeMap, super.hashCode);

  @override
  String toString() {
    return 'Dictionary($forwardTo, key: $keyType, '
        'value: $valueType, map: $_typeMap)';
  }
}
