// 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.require('goog.testing.asserts');
goog.require('goog.userAgent');

// CommonJS-LoadFromFile: testbinary_pb proto.jspb.test
goog.require('proto.jspb.test.MapValueEnum');
goog.require('proto.jspb.test.MapValueMessage');
goog.require('proto.jspb.test.TestMapFields');
goog.require('proto.jspb.test.TestMapFieldsOptionalKeys');
goog.require('proto.jspb.test.MapEntryOptionalKeysStringKey');
goog.require('proto.jspb.test.MapEntryOptionalKeysInt32Key');
goog.require('proto.jspb.test.MapEntryOptionalKeysInt64Key');
goog.require('proto.jspb.test.MapEntryOptionalKeysBoolKey');

// CommonJS-LoadFromFile: test_pb proto.jspb.test
goog.require('proto.jspb.test.MapValueMessageNoBinary');
goog.require('proto.jspb.test.TestMapFieldsNoBinary');

/**
 * Helper: check that the given map has exactly this set of (sorted) entries.
 * @param {!jspb.Map} map
 * @param {!Array<!Array<?>>} entries
 */
function checkMapEquals(map, entries) {
  var arr = map.toArray();
  assertEquals(arr.length, entries.length);
  for (var i = 0; i < arr.length; i++) {
    assertElementsEquals(arr[i], entries[i]);
  }
}

/**
 * Converts an ES6 iterator to an array.
 * @template T
 * @param {!Iterator<T>} iter an iterator
 * @return {!Array<T>}
 */
function toArray(iter) {
  var arr = [];
  while (true) {
    var val = iter.next();
    if (val.done) {
      break;
    }
    arr.push(val.value);
  }
  return arr;
}


/**
 * Helper: generate test methods for this TestMapFields class.
 * @param {?} msgInfo
 * @param {?} submessageCtor
 * @param {string} suffix
 */
function makeTests(msgInfo, submessageCtor, suffix) {
  /**
   * Helper: fill all maps on a TestMapFields.
   * @param {?} msg
   */
  var fillMapFields = function(msg) {
    msg.getMapStringStringMap().set('asdf', 'jkl;').set('key 2', 'hello world');
    msg.getMapStringInt32Map().set('a', 1).set('b', -2);
    msg.getMapStringInt64Map().set('c', 0x100000000).set('d', 0x200000000);
    msg.getMapStringBoolMap().set('e', true).set('f', false);
    msg.getMapStringDoubleMap().set('g', 3.14159).set('h', 2.71828);
    msg.getMapStringEnumMap()
        .set('i', proto.jspb.test.MapValueEnum.MAP_VALUE_BAR)
        .set('j', proto.jspb.test.MapValueEnum.MAP_VALUE_BAZ);
    msg.getMapStringMsgMap()
        .set('k', new submessageCtor())
        .set('l', new submessageCtor());
    msg.getMapStringMsgMap().get('k').setFoo(42);
    msg.getMapStringMsgMap().get('l').setFoo(84);
    msg.getMapInt32StringMap().set(-1, 'a').set(42, 'b');
    msg.getMapInt64StringMap().set(0x123456789abc, 'c').set(0xcba987654321, 'd');
    msg.getMapBoolStringMap().set(false, 'e').set(true, 'f');
  };

  /**
   * Helper: check all maps on a TestMapFields.
   * @param {?} msg
   */
  var checkMapFields = function(msg) {
    checkMapEquals(msg.getMapStringStringMap(), [
          ['asdf', 'jkl;'],
          ['key 2', 'hello world']
    ]);
    checkMapEquals(msg.getMapStringInt32Map(), [
          ['a', 1],
          ['b', -2]
    ]);
    checkMapEquals(msg.getMapStringInt64Map(), [
          ['c', 0x100000000],
          ['d', 0x200000000]
    ]);
    checkMapEquals(msg.getMapStringBoolMap(), [
          ['e', true],
          ['f', false]
    ]);
    checkMapEquals(msg.getMapStringDoubleMap(), [
          ['g', 3.14159],
          ['h', 2.71828]
    ]);
    checkMapEquals(msg.getMapStringEnumMap(), [
          ['i', proto.jspb.test.MapValueEnum.MAP_VALUE_BAR],
          ['j', proto.jspb.test.MapValueEnum.MAP_VALUE_BAZ]
    ]);
    checkMapEquals(msg.getMapInt32StringMap(), [
          [-1, 'a'],
          [42, 'b']
    ]);
    checkMapEquals(msg.getMapInt64StringMap(), [
          [0x123456789abc, 'c'],
          [0xcba987654321, 'd']
    ]);
    checkMapEquals(msg.getMapBoolStringMap(), [
          [false, 'e'],
          [true, 'f']
    ]);

    assertEquals(msg.getMapStringMsgMap().getLength(), 2);
    assertEquals(msg.getMapStringMsgMap().get('k').getFoo(), 42);
    assertEquals(msg.getMapStringMsgMap().get('l').getFoo(), 84);

    var entries = toArray(msg.getMapStringMsgMap().entries());
    assertEquals(entries.length, 2);
    entries.forEach(function(entry) {
      var key = entry[0];
      var val = entry[1];
      assert(val === msg.getMapStringMsgMap().get(key));
    });

    msg.getMapStringMsgMap().forEach(function(val, key) {
      assert(val === msg.getMapStringMsgMap().get(key));
    });
  };

  it('testMapStringStringField' + suffix, function() {
    var msg = new msgInfo.constructor();
    assertEquals(msg.getMapStringStringMap().getLength(), 0);
    assertEquals(msg.getMapStringInt32Map().getLength(), 0);
    assertEquals(msg.getMapStringInt64Map().getLength(), 0);
    assertEquals(msg.getMapStringBoolMap().getLength(), 0);
    assertEquals(msg.getMapStringDoubleMap().getLength(), 0);
    assertEquals(msg.getMapStringEnumMap().getLength(), 0);
    assertEquals(msg.getMapStringMsgMap().getLength(), 0);

    // Re-create to clear out any internally-cached wrappers, etc.
    msg = new msgInfo.constructor();
    var m = msg.getMapStringStringMap();
    assertEquals(m.has('asdf'), false);
    assertEquals(m.get('asdf'), undefined);
    m.set('asdf', 'hello world');
    assertEquals(m.has('asdf'), true);
    assertEquals(m.get('asdf'), 'hello world');
    m.set('jkl;', 'key 2');
    assertEquals(m.has('jkl;'), true);
    assertEquals(m.get('jkl;'), 'key 2');
    assertEquals(m.getLength(), 2);
    var it = m.entries();
    assertElementsEquals(it.next().value, ['asdf', 'hello world']);
    assertElementsEquals(it.next().value, ['jkl;', 'key 2']);
    assertEquals(it.next().done, true);
    checkMapEquals(m, [
        ['asdf', 'hello world'],
        ['jkl;', 'key 2']
    ]);
    m.del('jkl;');
    assertEquals(m.has('jkl;'), false);
    assertEquals(m.get('jkl;'), undefined);
    assertEquals(m.getLength(), 1);
    it = m.keys();
    assertEquals(it.next().value, 'asdf');
    assertEquals(it.next().done, true);
    it = m.values();
    assertEquals(it.next().value, 'hello world');
    assertEquals(it.next().done, true);

    var count = 0;
    m.forEach(function(value, key, map) {
      assertEquals(map, m);
      assertEquals(key, 'asdf');
      assertEquals(value, 'hello world');
      count++;
    });
    assertEquals(count, 1);

    m.clear();
    assertEquals(m.getLength(), 0);
  });


  /**
   * Tests operations on maps with all key and value types.
   */
  it('testAllMapTypes' + suffix, function() {
    var msg = new msgInfo.constructor();
    fillMapFields(msg);
    checkMapFields(msg);
  });


  if (msgInfo.deserializeBinary) {
    /**
     * Tests serialization and deserialization in binary format.
     */
    it('testBinaryFormat' + suffix, function() {
      if (goog.userAgent.IE && !goog.userAgent.isDocumentModeOrHigher(10)) {
        // IE8/9 currently doesn't support binary format because they lack
        // TypedArray.
        return;
      }

      // Check that the format is correct.
      var msg = new msgInfo.constructor();
      msg.getMapStringStringMap().set('A', 'a');
      var serialized = msg.serializeBinary();
      var expectedSerialized = [
          0x0a, 0x6, // field 1 (map_string_string), delimited, length 6
          0x0a, 0x1, // field 1 in submessage (key), delimited, length 1
          0x41,      // ASCII 'A'
          0x12, 0x1, // field 2 in submessage (value), delimited, length 1
          0x61       // ASCII 'a'
      ];
      assertEquals(serialized.length, expectedSerialized.length);
      for (var i = 0; i < serialized.length; i++) {
        assertEquals(serialized[i], expectedSerialized[i]);
      }

      // Check that all map fields successfully round-trip.
      msg = new msgInfo.constructor();
      fillMapFields(msg);
      serialized = msg.serializeBinary();
      var decoded = msgInfo.deserializeBinary(serialized);
      checkMapFields(decoded);
    });
    /**
     * Tests deserialization of undefined map keys go to default values in binary format.
     */
    it('testMapDeserializationForUndefinedKeys', function() {
      var testMessageOptionalKeys = new proto.jspb.test.TestMapFieldsOptionalKeys();
      var mapEntryStringKey = new proto.jspb.test.MapEntryOptionalKeysStringKey();
      mapEntryStringKey.setValue("a");
      testMessageOptionalKeys.setMapStringString(mapEntryStringKey);
      var mapEntryInt32Key = new proto.jspb.test.MapEntryOptionalKeysInt32Key();
      mapEntryInt32Key.setValue("b");
      testMessageOptionalKeys.setMapInt32String(mapEntryInt32Key);
      var mapEntryInt64Key = new proto.jspb.test.MapEntryOptionalKeysInt64Key();
      mapEntryInt64Key.setValue("c");
      testMessageOptionalKeys.setMapInt64String(mapEntryInt64Key);
      var mapEntryBoolKey = new proto.jspb.test.MapEntryOptionalKeysBoolKey();
      mapEntryBoolKey.setValue("d");
      testMessageOptionalKeys.setMapBoolString(mapEntryBoolKey);
      var deserializedMessage = msgInfo.deserializeBinary(
        testMessageOptionalKeys.serializeBinary()
       );
      checkMapEquals(deserializedMessage.getMapStringStringMap(), [
        ['', 'a']
      ]);
      checkMapEquals(deserializedMessage.getMapInt32StringMap(), [
        [0, 'b']
      ]);
      checkMapEquals(deserializedMessage.getMapInt64StringMap(), [
        [0, 'c']
      ]);
      checkMapEquals(deserializedMessage.getMapBoolStringMap(), [
        [false, 'd']
      ]);
    });
  }


  /**
   * Exercises the lazy map<->underlying array sync.
   */
  it('testLazyMapSync' + suffix, function() {
    // Start with a JSPB array containing a few map entries.
    var entries = [
        ['a', 'entry 1'],
        ['c', 'entry 2'],
        ['b', 'entry 3']
    ];
    var msg = new msgInfo.constructor([entries]);
    assertEquals(entries.length, 3);
    assertEquals(entries[0][0], 'a');
    assertEquals(entries[1][0], 'c');
    assertEquals(entries[2][0], 'b');
    msg.getMapStringStringMap().del('a');
    assertEquals(entries.length, 3);  // not yet sync'd
    msg.toArray();                // force a sync
    assertEquals(entries.length, 2);
    assertEquals(entries[0][0], 'b'); // now in sorted order
    assertEquals(entries[1][0], 'c');

    var a = msg.toArray();
    assertEquals(a[0], entries);  // retains original reference
  });

  /**
   * Returns IteratorIterables for entries(), keys() and values().
   */
  it('testIteratorIterables' + suffix, function() {
    var msg = new msgInfo.constructor();
    var m = msg.getMapStringStringMap();
    m.set('key1', 'value1');
    m.set('key2', 'value2');
    var entryIterator = m.entries();
    assertElementsEquals(entryIterator.next().value, ['key1', 'value1']);
    assertElementsEquals(entryIterator.next().value, ['key2', 'value2']);
    assertEquals(entryIterator.next().done, true);

    if (typeof(Symbol) != 'undefined') {
      var entryIterable = m.entries()[Symbol.iterator]();
      assertElementsEquals(entryIterable.next().value, ['key1', 'value1']);
      assertElementsEquals(entryIterable.next().value, ['key2', 'value2']);
      assertEquals(entryIterable.next().done, true);
    }

    var keyIterator = m.keys();
    assertEquals(keyIterator.next().value, 'key1');
    assertEquals(keyIterator.next().value, 'key2');
    assertEquals(keyIterator.next().done, true);

    if (typeof(Symbol) != 'undefined') {
      var keyIterable = m.keys()[Symbol.iterator]();
      assertEquals(keyIterable.next().value, 'key1');
      assertEquals(keyIterable.next().value, 'key2');
      assertEquals(keyIterable.next().done, true);
    }
    var valueIterator = m.values();
    assertEquals(valueIterator.next().value, 'value1');
    assertEquals(valueIterator.next().value, 'value2');
    assertEquals(valueIterator.next().done, true);

    if (typeof(Symbol) != 'undefined') {
      var valueIterable = m.values()[Symbol.iterator]();
      assertEquals(valueIterable.next().value, 'value1');
      assertEquals(valueIterable.next().value, 'value2');
      assertEquals(valueIterable.next().done, true);
    }
  });
}

describe('mapsTest', function() {
  makeTests(
      {
        constructor: proto.jspb.test.TestMapFields,
        deserializeBinary: proto.jspb.test.TestMapFields.deserializeBinary
      },
      proto.jspb.test.MapValueMessage, '_Binary');
  makeTests(
      {
        constructor: proto.jspb.test.TestMapFieldsNoBinary,
        deserializeBinary: null
      },
      proto.jspb.test.MapValueMessageNoBinary, '_NoBinary');
});
