// Copyright (c) 2018, 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 protobuf;

class PbMap<K, V> extends MapBase<K, V> {
  final int keyFieldType;
  final int valueFieldType;

  static const int _keyFieldNumber = 1;
  static const int _valueFieldNumber = 2;

  final Map<K, V> _wrappedMap;
  final BuilderInfo _entryBuilderInfo;

  bool _isReadonly = false;
  _FieldSet _entryFieldSet() => _FieldSet(null, _entryBuilderInfo, null);

  PbMap(this.keyFieldType, this.valueFieldType, this._entryBuilderInfo)
      : _wrappedMap = <K, V>{};

  PbMap.unmodifiable(PbMap other)
      : keyFieldType = other.keyFieldType,
        valueFieldType = other.valueFieldType,
        _wrappedMap = Map.unmodifiable(other._wrappedMap),
        _entryBuilderInfo = other._entryBuilderInfo,
        _isReadonly = other._isReadonly;

  @override
  V operator [](Object key) => _wrappedMap[key];

  @override
  void operator []=(K key, V value) {
    if (_isReadonly)
      throw UnsupportedError('Attempted to change a read-only map field');
    _checkNotNull(key);
    _checkNotNull(value);
    _wrappedMap[key] = value;
  }

  /// A [PbMap] is equal to another [PbMap] with equal key/value
  /// pairs in any order.
  @override
  bool operator ==(other) {
    if (identical(other, this)) {
      return true;
    }
    if (other is! PbMap) {
      return false;
    }
    if (other.length != length) {
      return false;
    }
    for (final key in keys) {
      if (!other.containsKey(key)) {
        return false;
      }
    }
    for (final key in keys) {
      if (other[key] != this[key]) {
        return false;
      }
    }
    return true;
  }

  /// A [PbMap] is equal to another [PbMap] with equal key/value
  /// pairs in any order. Then, the `hashCode` is guaranteed to be the same.
  @override
  int get hashCode {
    return _wrappedMap.entries
        .fold(0, (h, entry) => h ^ _HashUtils._hash2(entry.key, entry.value));
  }

  @override
  void clear() {
    if (_isReadonly)
      throw UnsupportedError('Attempted to change a read-only map field');
    _wrappedMap.clear();
  }

  @override
  Iterable<K> get keys => _wrappedMap.keys;

  @override
  V remove(Object key) {
    if (_isReadonly)
      throw UnsupportedError('Attempted to change a read-only map field');
    return _wrappedMap.remove(key);
  }

  @Deprecated("This function was not intended to be public. "
      "It will be removed from the public api in next major version. ")
  void add(CodedBufferReader input, [ExtensionRegistry registry]) {
    _mergeEntry(input, registry);
  }

  void _mergeEntry(CodedBufferReader input, [ExtensionRegistry registry]) {
    int length = input.readInt32();
    int oldLimit = input._currentLimit;
    input._currentLimit = input._bufferPos + length;
    _FieldSet entryFieldSet = _entryFieldSet();
    _mergeFromCodedBufferReader(entryFieldSet, input, registry);
    input.checkLastTagWas(0);
    input._currentLimit = oldLimit;
    K key = entryFieldSet._$get(0, null);
    V value = entryFieldSet._$get(1, null);
    _wrappedMap[key] = value;
  }

  void _checkNotNull(Object val) {
    if (val == null) {
      throw ArgumentError("Can't add a null to a map field");
    }
  }

  PbMap freeze() {
    _isReadonly = true;
    if (_isGroupOrMessage(valueFieldType)) {
      for (var subMessage in values as Iterable<GeneratedMessage>) {
        subMessage.freeze();
      }
    }
    return this;
  }
}
