// Protocol Buffers - Google's data interchange format
// Copyright 2008 Google Inc.  All rights reserved.
// https://developers.google.com/protocol-buffers/
//
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions are
// met:
//
//     * Redistributions of source code must retain the above copyright
// notice, this list of conditions and the following disclaimer.
//     * Redistributions in binary form must reproduce the above
// copyright notice, this list of conditions and the following disclaimer
// in the documentation and/or other materials provided with the
// distribution.
//     * Neither the name of Google Inc. nor the names of its
// contributors may be used to endorse or promote products derived from
// this software without specific prior written permission.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.

goog.provide('jspb.Map');

goog.require('goog.asserts');

goog.forwardDeclare('jspb.BinaryReader');
goog.forwardDeclare('jspb.BinaryWriter');



/**
 * Constructs a new Map. A Map is a container that is used to implement map
 * fields on message objects. It closely follows the ES6 Map API; however,
 * it is distinct because we do not want to depend on external polyfills or
 * on ES6 itself.
 *
 * This constructor should only be called from generated message code. It is not
 * intended for general use by library consumers.
 *
 * @template K, V
 *
 * @param {!Array<!Array<!Object>>} arr
 *
 * @param {?function(new:V)|function(new:V,?)=} opt_valueCtor
 *    The constructor for type V, if type V is a message type.
 *
 * @constructor
 * @struct
 */
jspb.Map = function(arr, opt_valueCtor) {
  /** @const @private */
  this.arr_ = arr;
  /** @const @private */
  this.valueCtor_ = opt_valueCtor;

  /** @type {!Object<string, !jspb.Map.Entry_<K,V>>} @private */
  this.map_ = {};

  /**
   * Is `this.arr_ updated with respect to `this.map_`?
   * @type {boolean}
   */
  this.arrClean = true;

  if (this.arr_.length > 0) {
    this.loadFromArray_();
  }
};


/**
 * Load initial content from underlying array.
 * @private
 */
jspb.Map.prototype.loadFromArray_ = function() {
  for (var i = 0; i < this.arr_.length; i++) {
    var record = this.arr_[i];
    var key = record[0];
    var value = record[1];
    this.map_[key.toString()] = new jspb.Map.Entry_(key, value);
  }
  this.arrClean = true;
};


/**
 * Synchronize content to underlying array, if needed, and return it.
 * @return {!Array<!Array<!Object>>}
 */
jspb.Map.prototype.toArray = function() {
  if (this.arrClean) {
    if (this.valueCtor_) {
      // We need to recursively sync maps in submessages to their arrays.
      var m = this.map_;
      for (var p in m) {
        if (Object.prototype.hasOwnProperty.call(m, p)) {
          var valueWrapper = /** @type {?jspb.Message} */ (m[p].valueWrapper);
          if (valueWrapper) {
            valueWrapper.toArray();
          }
        }
      }
    }
  } else {
    // Delete all elements.
    this.arr_.length = 0;
    var strKeys = this.stringKeys_();
    // Output keys in deterministic (sorted) order.
    strKeys.sort();
    for (var i = 0; i < strKeys.length; i++) {
      var entry = this.map_[strKeys[i]];
      var valueWrapper = /** @type {!Object} */ (entry.valueWrapper);
      if (valueWrapper) {
        valueWrapper.toArray();
      }
      this.arr_.push([entry.key, entry.value]);
    }
    this.arrClean = true;
  }
  return this.arr_;
};


/**
 * Returns the map formatted as an array of key-value pairs, suitable for the
 * toObject() form of a message.
 *
 * @param {boolean=} includeInstance Whether to include the JSPB instance for
 *    transitional soy proto support: http://goto/soy-param-migration
 * @param {!function((boolean|undefined),!V):!Object=} valueToObject
 *    The static toObject() method, if V is a message type.
 * @return {!Array<!Array<!Object>>}
 */
jspb.Map.prototype.toObject = function(includeInstance, valueToObject) {
  var rawArray = this.toArray();
  var entries = [];
  for (var i = 0; i < rawArray.length; i++) {
    var entry = this.map_[rawArray[i][0].toString()];
    this.wrapEntry_(entry);
    var valueWrapper = /** @type {!V|undefined} */ (entry.valueWrapper);
    if (valueWrapper) {
      goog.asserts.assert(valueToObject);
      entries.push([entry.key, valueToObject(includeInstance, valueWrapper)]);
    } else {
      entries.push([entry.key, entry.value]);
    }
  }
  return entries;
};


/**
 * Returns a Map from the given array of key-value pairs when the values are of
 * message type. The values in the array must match the format returned by their
 * message type's toObject() method.
 *
 * @template K, V
 * @param {!Array<!Array<!Object>>} entries
 * @param {!function(new:V)|function(new:V,?)} valueCtor
 *    The constructor for type V.
 * @param {!function(!Object):V} valueFromObject
 *    The fromObject function for type V.
 * @return {!jspb.Map<K, V>}
 */
jspb.Map.fromObject = function(entries, valueCtor, valueFromObject) {
  var result = new jspb.Map([], valueCtor);
  for (var i = 0; i < entries.length; i++) {
    var key = entries[i][0];
    var value = valueFromObject(entries[i][1]);
    result.set(key, value);
  }
  return result;
};


/**
 * Helper: an IteratorIterable over an array.
 * @template T
 * @param {!Array<T>} arr the array
 * @implements {IteratorIterable<T>}
 * @constructor @struct
 * @private
 */
jspb.Map.ArrayIteratorIterable_ = function(arr) {
  /** @type {number} @private */
  this.idx_ = 0;

  /** @const @private */
  this.arr_ = arr;
};


/** @override @final */
jspb.Map.ArrayIteratorIterable_.prototype.next = function() {
  if (this.idx_ < this.arr_.length) {
    return {done: false, value: this.arr_[this.idx_++]};
  } else {
    return {done: true, value: undefined};
  }
};

if (typeof(Symbol) != 'undefined') {
  /** @override */
  jspb.Map.ArrayIteratorIterable_.prototype[Symbol.iterator] = function() {
    return this;
  };
}


/**
 * Returns the map's length (number of key/value pairs).
 * @return {number}
 */
jspb.Map.prototype.getLength = function() {
  return this.stringKeys_().length;
};


/**
 * Clears the map.
 */
jspb.Map.prototype.clear = function() {
  this.map_ = {};
  this.arrClean = false;
};


/**
 * Deletes a particular key from the map.
 * N.B.: differs in name from ES6 Map's `delete` because IE8 does not support
 * reserved words as property names.
 * @this {jspb.Map}
 * @param {K} key
 * @return {boolean} Whether any entry with this key was deleted.
 */
jspb.Map.prototype.del = function(key) {
  var keyValue = key.toString();
  var hadKey = this.map_.hasOwnProperty(keyValue);
  delete this.map_[keyValue];
  this.arrClean = false;
  return hadKey;
};


/**
 * Returns an array of [key, value] pairs in the map.
 *
 * This is redundant compared to the plain entries() method, but we provide this
 * to help out Angular 1.x users.  Still evaluating whether this is the best
 * option.
 *
 * @return {!Array<!Array<K|V>>}
 */
jspb.Map.prototype.getEntryList = function() {
  var entries = [];
  var strKeys = this.stringKeys_();
  strKeys.sort();
  for (var i = 0; i < strKeys.length; i++) {
    var entry = this.map_[strKeys[i]];
    entries.push([entry.key, entry.value]);
  }
  return entries;
};


/**
 * Returns an iterator-iterable over [key, value] pairs in the map.
 * Closure compiler sadly doesn't support tuples, ie. Iterator<[K,V]>.
 * @return {!IteratorIterable<!Array<K|V>>} The iterator-iterable.
 */
jspb.Map.prototype.entries = function() {
  var entries = [];
  var strKeys = this.stringKeys_();
  strKeys.sort();
  for (var i = 0; i < strKeys.length; i++) {
    var entry = this.map_[strKeys[i]];
    entries.push([entry.key, this.wrapEntry_(entry)]);
  }
  return new jspb.Map.ArrayIteratorIterable_(entries);
};


/**
 * Returns an iterator-iterable over keys in the map.
 * @return {!IteratorIterable<K>} The iterator-iterable.
 */
jspb.Map.prototype.keys = function() {
  var keys = [];
  var strKeys = this.stringKeys_();
  strKeys.sort();
  for (var i = 0; i < strKeys.length; i++) {
    var entry = this.map_[strKeys[i]];
    keys.push(entry.key);
  }
  return new jspb.Map.ArrayIteratorIterable_(keys);
};


/**
 * Returns an iterator-iterable over values in the map.
 * @return {!IteratorIterable<V>} The iterator-iterable.
 */
jspb.Map.prototype.values = function() {
  var values = [];
  var strKeys = this.stringKeys_();
  strKeys.sort();
  for (var i = 0; i < strKeys.length; i++) {
    var entry = this.map_[strKeys[i]];
    values.push(this.wrapEntry_(entry));
  }
  return new jspb.Map.ArrayIteratorIterable_(values);
};


/**
 * Iterates over entries in the map, calling a function on each.
 * @template T
 * @param {function(this:T, V, K, ?jspb.Map<K, V>)} cb
 * @param {T=} opt_thisArg
 */
jspb.Map.prototype.forEach = function(cb, opt_thisArg) {
  var strKeys = this.stringKeys_();
  strKeys.sort();
  for (var i = 0; i < strKeys.length; i++) {
    var entry = this.map_[strKeys[i]];
    cb.call(opt_thisArg, this.wrapEntry_(entry), entry.key, this);
  }
};


/**
 * Sets a key in the map to the given value.
 * @param {K} key The key
 * @param {V} value The value
 * @return {!jspb.Map<K,V>}
 */
jspb.Map.prototype.set = function(key, value) {
  var entry = new jspb.Map.Entry_(key);
  if (this.valueCtor_) {
    entry.valueWrapper = value;
    // .toArray() on a message returns a reference to the underlying array
    // rather than a copy.
    entry.value = value.toArray();
  } else {
    entry.value = value;
  }
  this.map_[key.toString()] = entry;
  this.arrClean = false;
  return this;
};


/**
 * Helper: lazily construct a wrapper around an entry, if needed, and return the
 * user-visible type.
 * @param {!jspb.Map.Entry_<K,V>} entry
 * @return {V}
 * @private
 */
jspb.Map.prototype.wrapEntry_ = function(entry) {
  if (this.valueCtor_) {
    if (!entry.valueWrapper) {
      entry.valueWrapper = new this.valueCtor_(entry.value);
    }
    return /** @type {V} */ (entry.valueWrapper);
  } else {
    return entry.value;
  }
};


/**
 * Gets the value corresponding to a key in the map.
 * @param {K} key
 * @return {V|undefined} The value, or `undefined` if key not present
 */
jspb.Map.prototype.get = function(key) {
  var keyValue = key.toString();
  var entry = this.map_[keyValue];
  if (entry) {
    return this.wrapEntry_(entry);
  } else {
    return undefined;
  }
};


/**
 * Determines whether the given key is present in the map.
 * @param {K} key
 * @return {boolean} `true` if the key is present
 */
jspb.Map.prototype.has = function(key) {
  var keyValue = key.toString();
  return (keyValue in this.map_);
};


/**
 * Write this Map field in wire format to a BinaryWriter, using the given field
 * number.
 * @param {number} fieldNumber
 * @param {!jspb.BinaryWriter} writer
 * @param {!function(this:jspb.BinaryWriter,number,K)} keyWriterFn
 *     The method on BinaryWriter that writes type K to the stream.
 * @param {!function(this:jspb.BinaryWriter,number,V)|
 *          function(this:jspb.BinaryReader,V,?)} valueWriterFn
 *     The method on BinaryWriter that writes type V to the stream.  May be
 *     writeMessage, in which case the second callback arg form is used.
 * @param {function(V,!jspb.BinaryWriter)=} opt_valueWriterCallback
 *    The BinaryWriter serialization callback for type V, if V is a message
 *    type.
 */
jspb.Map.prototype.serializeBinary = function(
    fieldNumber, writer, keyWriterFn, valueWriterFn, opt_valueWriterCallback) {
  var strKeys = this.stringKeys_();
  strKeys.sort();
  for (var i = 0; i < strKeys.length; i++) {
    var entry = this.map_[strKeys[i]];
    writer.beginSubMessage(fieldNumber);
    keyWriterFn.call(writer, 1, entry.key);
    if (this.valueCtor_) {
      valueWriterFn.call(writer, 2, this.wrapEntry_(entry),
                         opt_valueWriterCallback);
    } else {
      valueWriterFn.call(writer, 2, entry.value);
    }
    writer.endSubMessage();
  }
};


/**
 * Read one key/value message from the given BinaryReader. Compatible as the
 * `reader` callback parameter to jspb.BinaryReader.readMessage, to be called
 * when a key/value pair submessage is encountered.
 * @template K, V
 * @param {!jspb.Map} map
 * @param {!jspb.BinaryReader} reader
 * @param {!function(this:jspb.BinaryReader):K} keyReaderFn
 *     The method on BinaryReader that reads type K from the stream.
 *
 * @param {!function(this:jspb.BinaryReader):V|
 *          function(this:jspb.BinaryReader,V,
 *                  function(V,!jspb.BinaryReader))} valueReaderFn
 *    The method on BinaryReader that reads type V from the stream. May be
 *    readMessage, in which case the second callback arg form is used.
 *
 * @param {?function(V,!jspb.BinaryReader)=} opt_valueReaderCallback
 *    The BinaryReader parsing callback for type V, if V is a message type.
 *
 */
jspb.Map.deserializeBinary = function(map, reader, keyReaderFn, valueReaderFn,
                                      opt_valueReaderCallback) {
  var key = undefined;
  var value = undefined;

  while (reader.nextField()) {
    if (reader.isEndGroup()) {
      break;
    }
    var field = reader.getFieldNumber();
    if (field == 1) {
      // Key.
      key = keyReaderFn.call(reader);
    } else if (field == 2) {
      // Value.
      if (map.valueCtor_) {
        value = new map.valueCtor_();
        valueReaderFn.call(reader, value, opt_valueReaderCallback);
      } else {
        value = valueReaderFn.call(reader);
      }
    }
  }

  goog.asserts.assert(key != undefined);
  goog.asserts.assert(value != undefined);
  map.set(key, value);
};


/**
 * Helper: compute the list of all stringified keys in the underlying Object
 * map.
 * @return {!Array<string>}
 * @private
 */
jspb.Map.prototype.stringKeys_ = function() {
  var m = this.map_;
  var ret = [];
  for (var p in m) {
    if (Object.prototype.hasOwnProperty.call(m, p)) {
      ret.push(p);
    }
  }
  return ret;
};



/**
 * @param {!K} key The entry's key.
 * @param {V=} opt_value The entry's value wrapper.
 * @constructor
 * @struct
 * @template K, V
 * @private
 */
jspb.Map.Entry_ = function(key, opt_value) {
  /** @const {K} */
  this.key = key;

  // The JSPB-serializable value.  For primitive types this will be of type V.
  // For message types it will be an array.
  /** @type {V} */
  this.value = opt_value;

  // Only used for submessage values.
  /** @type {V} */
  this.valueWrapper = undefined;
};
