// Copyright (c) 2013, 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.

// @dart = 2.9

import "package:expect/expect.dart";

void testListMapCorrespondence(List list, Map map) {
  Expect.equals(list.length, map.length);
  for (int i = 0; i < list.length; i++) {
    Expect.equals(list[i], map[i]);
  }
  Expect.isNull(map[list.length]);
  Expect.isNull(map[-1]);

  Iterable keys = map.keys;
  Iterable values = map.values;
  Expect.isFalse(keys is List);
  Expect.isFalse(values is List);
  Expect.equals(list.length, keys.length);
  Expect.equals(list.length, values.length);
  for (int i = 0; i < list.length; i++) {
    Expect.equals(i, keys.elementAt(i));
    Expect.equals(list[i], values.elementAt(i));
  }

  int forEachCount = 0;
  map.forEach((key, value) {
    Expect.equals(forEachCount, key);
    Expect.equals(list[key], value);
    forEachCount++;
  });

  for (int i = 0; i < list.length; i++) {
    Expect.isTrue(map.containsKey(i));
    Expect.isTrue(map.containsValue(list[i]));
  }
  Expect.isFalse(map.containsKey(-1));
  Expect.isFalse(map.containsKey(list.length));

  Expect.equals(list.length, forEachCount);

  Expect.equals(list.isEmpty, map.isEmpty);
}

void testConstAsMap(List list) {
  Map<int, dynamic> map = list.asMap();

  testListMapCorrespondence(list, map);

  Expect.throwsUnsupportedError(() => map[0] = 499);
  Expect.throwsUnsupportedError(() => map.putIfAbsent(0, () => 499));
  Expect.throwsUnsupportedError(() => map.clear());
}

void testFixedAsMap(List list) {
  testConstAsMap(list);

  Map<int, dynamic> map = list.asMap();

  if (!list.isEmpty) {
    list[0] = 499;
    // Check again to make sure the map is backed by the list.
    testListMapCorrespondence(list, map);
  }
}

void testAsMap(List list) {
  testFixedAsMap(list);

  Map<int, dynamic> map = list.asMap();

  Iterable keys = map.keys;
  Iterable values = map.values;

  list.add(42);
  // Check again to make sure the map is backed by the list and that the
  // length is not cached.
  testListMapCorrespondence(list, map);
  // Also check that the keys and values iterable from the map are backed by
  // the list.
  Expect.equals(list.length, keys.length);
  Expect.equals(values.length, values.length);
}

main() {
  testConstAsMap(const [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]);
  testAsMap([1, 2, 3, 4, 5, 6, 7, 8, 9, 10]);
  List list = new List(10);
  for (int i = 0; i < 10; i++) list[i] = i + 1;
  testFixedAsMap(list);

  testConstAsMap(const []);
  testAsMap([]);
  testFixedAsMap(new List(0));
}
