// 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.

/// Tests priority queue implementations utilities.

import 'package:test/test.dart';

import 'package:collection/src/priority_queue.dart';

void main() {
  testDefault();
  testInt(() => HeapPriorityQueue<int>());
  testCustom((comparator) => HeapPriorityQueue<C>(comparator));
  testDuplicates();
  testNullable();
}

void testDefault() {
  test('PriorityQueue() returns a HeapPriorityQueue', () {
    expect(PriorityQueue<int>(), TypeMatcher<HeapPriorityQueue<int>>());
  });
  testInt(() => PriorityQueue<int>());
  testCustom((comparator) => PriorityQueue<C>(comparator));
}

void testInt(PriorityQueue<int> Function() create) {
  for (var count in [1, 5, 127, 128]) {
    testQueue('int:$count', create, List<int>.generate(count, (x) => x), count);
  }
}

void testCustom(
    PriorityQueue<C> Function(int Function(C, C)? comparator) create) {
  for (var count in [1, 5, 127, 128]) {
    testQueue('Custom:$count/null', () => create(null),
        List<C>.generate(count, (x) => C(x)), C(count));
    testQueue('Custom:$count/compare', () => create(compare),
        List<C>.generate(count, (x) => C(x)), C(count));
    testQueue('Custom:$count/compareNeg', () => create(compareNeg),
        List<C>.generate(count, (x) => C(count - x)), C(0));
  }
}

/// Test that a queue behaves correctly.
///
/// The elements must be in priority order, from highest to lowest.
void testQueue(
    String name, PriorityQueue Function() create, List elements, notElement) {
  test(name, () => testQueueBody(create, elements, notElement));
}

void testQueueBody<T>(
    PriorityQueue<T> Function() create, List<T> elements, notElement) {
  var q = create();
  expect(q.isEmpty, isTrue);
  expect(q, hasLength(0));
  expect(() {
    q.first;
  }, throwsStateError);
  expect(() {
    q.removeFirst();
  }, throwsStateError);

  // Tests removeFirst, first, contains, toList and toSet.
  void testElements() {
    expect(q.isNotEmpty, isTrue);
    expect(q, hasLength(elements.length));

    expect(q.toList(), equals(elements));
    expect(q.toSet().toList(), equals(elements));

    for (var i = 0; i < elements.length; i++) {
      expect(q.contains(elements[i]), isTrue);
    }
    expect(q.contains(notElement), isFalse);

    var all = [];
    while (q.isNotEmpty) {
      var expected = q.first;
      var actual = q.removeFirst();
      expect(actual, same(expected));
      all.add(actual);
    }

    expect(all.length, elements.length);
    for (var i = 0; i < all.length; i++) {
      expect(all[i], same(elements[i]));
    }

    expect(q.isEmpty, isTrue);
  }

  q.addAll(elements);
  testElements();

  q.addAll(elements.reversed);
  testElements();

  // Add elements in a non-linear order (gray order).
  for (var i = 0, j = 0; i < elements.length; i++) {
    int gray;
    do {
      gray = j ^ (j >> 1);
      j++;
    } while (gray >= elements.length);
    q.add(elements[gray]);
  }
  testElements();

  // Add elements by picking the middle element first, and then recursing
  // on each side.
  void addRec(int min, int max) {
    var mid = min + ((max - min) >> 1);
    q.add(elements[mid]);
    if (mid + 1 < max) addRec(mid + 1, max);
    if (mid > min) addRec(min, mid);
  }

  addRec(0, elements.length);
  testElements();

  // Test removeAll.
  q.addAll(elements);
  expect(q, hasLength(elements.length));
  var all = q.removeAll();
  expect(q.isEmpty, isTrue);
  expect(all, hasLength(elements.length));
  for (var i = 0; i < elements.length; i++) {
    expect(all, contains(elements[i]));
  }

  // Test the same element more than once in queue.
  q.addAll(elements);
  q.addAll(elements.reversed);
  expect(q, hasLength(elements.length * 2));
  for (var i = 0; i < elements.length; i++) {
    var element = elements[i];
    expect(q.contains(element), isTrue);
    expect(q.removeFirst(), element);
    expect(q.removeFirst(), element);
  }

  // Test queue with all same element.
  var a = elements[0];
  for (var i = 0; i < elements.length; i++) {
    q.add(a);
  }
  expect(q, hasLength(elements.length));
  expect(q.contains(a), isTrue);
  expect(q.contains(notElement), isFalse);
  q.removeAll().forEach((x) => expect(x, same(a)));

  // Test remove.
  q.addAll(elements);
  for (var element in elements.reversed) {
    expect(q.remove(element), isTrue);
  }
  expect(q.isEmpty, isTrue);
}

void testDuplicates() {
  // Check how the heap handles duplicate, or equal-but-not-identical, values.
  test('duplicates', () {
    var q = HeapPriorityQueue<C>(compare);
    var c1 = C(0);
    var c2 = C(0);

    // Can contain the same element more than once.
    expect(c1, equals(c2));
    expect(c1, isNot(same(c2)));
    q.add(c1);
    q.add(c1);
    expect(q.length, 2);
    expect(q.contains(c1), true);
    expect(q.contains(c2), true);
    expect(q.remove(c2), true);
    expect(q.length, 1);
    expect(q.removeFirst(), same(c1));

    // Can contain equal elements.
    q.add(c1);
    q.add(c2);
    expect(q.length, 2);
    expect(q.contains(c1), true);
    expect(q.contains(c2), true);
    expect(q.remove(c1), true);
    expect(q.length, 1);
    expect(q.first, anyOf(same(c1), same(c2)));
  });
}

void testNullable() {
  // Check that the queue works with a nullable type, and a comparator
  // which accepts `null`.
  // Compares `null` before instances of `C`.
  int nullCompareFirst(C? a, C? b) => a == null
      ? b == null
          ? 0
          : -1
      : b == null
          ? 1
          : compare(a, b);

  int nullCompareLast(C? a, C? b) => a == null
      ? b == null
          ? 0
          : 1
      : b == null
          ? -1
          : compare(a, b);

  var c1 = C(1);
  var c2 = C(2);
  var c3 = C(3);

  test('nulls first', () {
    var q = HeapPriorityQueue<C?>(nullCompareFirst);
    q.add(c2);
    q.add(c1);
    q.add(null);
    expect(q.length, 3);
    expect(q.contains(null), true);
    expect(q.contains(c1), true);
    expect(q.contains(c3), false);

    expect(q.removeFirst(), null);
    expect(q.length, 2);
    expect(q.contains(null), false);
    q.add(null);
    expect(q.length, 3);
    expect(q.contains(null), true);
    q.add(null);
    expect(q.length, 4);
    expect(q.contains(null), true);
    expect(q.remove(null), true);
    expect(q.length, 3);
    expect(q.toList(), [null, c1, c2]);
  });

  test('nulls last', () {
    var q = HeapPriorityQueue<C?>(nullCompareLast);
    q.add(c2);
    q.add(c1);
    q.add(null);
    expect(q.length, 3);
    expect(q.contains(null), true);
    expect(q.contains(c1), true);
    expect(q.contains(c3), false);
    expect(q.first, c1);

    q.add(null);
    expect(q.length, 4);
    expect(q.contains(null), true);
    q.add(null);
    expect(q.length, 5);
    expect(q.contains(null), true);
    expect(q.remove(null), true);
    expect(q.length, 4);
    expect(q.toList(), [c1, c2, null, null]);
  });
}

// Custom class.
// Class is comparable, comparators match normal and inverse order.
int compare(C c1, C c2) => c1.value - c2.value;
int compareNeg(C c1, C c2) => c2.value - c1.value;

class C implements Comparable<C> {
  final int value;
  const C(this.value);
  @override
  int get hashCode => value;
  @override
  bool operator ==(Object other) => other is C && value == other.value;
  @override
  int compareTo(C other) => value - other.value;
  @override
  String toString() => 'C($value)';
}
