// 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 'dart:collection';
import "package:expect/expect.dart";

class MyEntry extends LinkedListEntry<MyEntry> {
  final int value;

  MyEntry(int this.value);

  String toString() => value.toString();

  int get hashCode => value.hashCode;
  bool operator ==(Object o) => o is MyEntry && value == o.value;
}

void testPreviousNext() {
  var list = LinkedList<MyEntry>();
  Expect.throws(() => list.first);
  Expect.throws(() => list.last);
  Expect.equals(0, list.length);

  for (int i = 0; i < 3; i++) {
    list.add(MyEntry(i));
  }
  Expect.equals(3, list.length);

  var entry = list.first;
  Expect.isNull(entry.previous);
  Expect.equals(0, entry.value);
  entry = entry.next;
  Expect.equals(1, entry.value);
  entry = entry.next;
  Expect.equals(2, entry.value);
  Expect.isNull(entry.next);
  entry = entry.previous;
  Expect.equals(1, entry.value);
  entry = entry.previous;
  Expect.equals(0, entry.value);
  Expect.isNull(entry.previous);
}

void testUnlinked() {
  var unlinked = MyEntry(0);
  Expect.isNull(unlinked.previous);
  Expect.isNull(unlinked.next);
  var list = LinkedList<MyEntry>();
  list.add(unlinked);
  Expect.isNull(unlinked.previous);
  Expect.isNull(unlinked.next);
  list.remove(unlinked);
  Expect.isNull(unlinked.previous);
  Expect.isNull(unlinked.next);
  list.add(unlinked);
  list.add(MyEntry(1));
  Expect.isNull(unlinked.previous);
  Expect.equals(1, unlinked.next.value);
  list.remove(unlinked);
  Expect.isNull(unlinked.previous);
  Expect.isNull(unlinked.next);
  list.add(unlinked);
  Expect.isNull(unlinked.next);
  Expect.equals(1, unlinked.previous.value);
}

void testInsert() {
  // Insert last.
  var list = LinkedList<MyEntry>();
  for (int i = 0; i < 10; i++) {
    list.add(MyEntry(i));
  }

  Expect.equals(10, list.length);

  int i = 0;
  for (var entry in list) {
    Expect.equals(i, entry.value);
    i++;
  }

  Expect.equals(10, i);

  list.clear();

  // Insert first.
  for (int i = 0; i < 10; i++) {
    list.addFirst(MyEntry(i));
  }

  Expect.equals(10, list.length);

  i = 10;
  for (var entry in list) {
    Expect.equals(--i, entry.value);
  }
  Expect.equals(0, i);

  list.clear();

  // Insert after.
  list.addFirst(MyEntry(0));
  for (int i = 1; i < 10; i++) {
    list.last.insertAfter(MyEntry(i));
  }

  Expect.equals(10, list.length);

  i = 0;
  for (var entry in list) {
    Expect.equals(i, entry.value);
    i++;
  }

  Expect.equals(10, i);

  list.clear();

  // Insert before.
  list.addFirst(MyEntry(0));
  for (int i = 1; i < 10; i++) {
    list.first.insertBefore(MyEntry(i));
  }

  Expect.equals(10, list.length);

  i = 10;
  for (var entry in list) {
    Expect.equals(--i, entry.value);
  }
  Expect.equals(0, i);

  list.clear();
}

void testRemove() {
  var list = LinkedList<MyEntry>();
  for (int i = 0; i < 10; i++) {
    list.add(MyEntry(i));
  }

  Expect.equals(10, list.length);

  list.remove(list.skip(5).first);

  Expect.equals(9, list.length);

  int i = 0;
  for (var entry in list) {
    if (i == 5) i++;
    Expect.equals(i, entry.value);
    i++;
  }

  Expect.listEquals(
      [0, 1, 2, 3, 4, 6, 7, 8, 9], list.map((e) => e.value).toList());

  for (int i = 0; i < 9; i++) {
    list.first.unlink();
  }

  Expect.throws(() => list.first);

  Expect.equals(0, list.length);
}

void testContains() {
  var list = LinkedList<MyEntry>();
  var entry5 = MyEntry(5);

  // Empty lists contains nothing.
  Expect.isFalse(list.contains(null));
  Expect.isFalse(list.contains(Object()));
  Expect.isFalse(list.contains(entry5));

  // Works for singleton lists.
  list.add(MyEntry(0));
  Expect.isTrue(list.contains(list.first));
  Expect.isFalse(list.contains(null));
  Expect.isFalse(list.contains(Object()));
  Expect.isFalse(list.contains(entry5));

  // Works for larger lists.
  for (int i = 1; i < 10; i++) {
    list.add(MyEntry(i));
  }
  for (var entry in list) {
    Expect.isTrue(list.contains(entry));
  }
  Expect.isFalse(list.contains(Object()));
  Expect.isFalse(list.contains(null));
  Expect.isFalse(list.contains(entry5));
  // Based on identity, not equality.
  Expect.isTrue(list.elementAt(5) == entry5);
}

void testBadAdd() {
  var list1 = LinkedList<MyEntry>();
  list1.addFirst(MyEntry(0));

  var list2 = LinkedList<MyEntry>();
  Expect.throws(() => list2.addFirst(list1.first));

  Expect.throws(() => MyEntry(0).unlink());
}

void testConcurrentModificationError() {
  test(function(LinkedList<MyEntry> ll)) {
    var ll = LinkedList<MyEntry>();
    for (int i = 0; i < 10; i++) {
      ll.add(MyEntry(i));
    }
    Expect.throws(() => function(ll), (e) => e is ConcurrentModificationError);
  }

  test((ll) {
    for (var x in ll) {
      ll.remove(x);
    }
  });
  test((ll) {
    ll.forEach((x) {
      ll.remove(x);
    });
  });
  test((ll) {
    ll.any((x) {
      ll.remove(x);
      return false;
    });
  });
  test((ll) {
    ll.every((x) {
      ll.remove(x);
      return true;
    });
  });
  test((ll) {
    ll.fold(0, (x, y) {
      ll.remove(y);
      return x;
    });
  });
  test((ll) {
    ll.reduce((x, y) {
      ll.remove(y);
      return x;
    });
  });
  test((ll) {
    ll.where((x) {
      ll.remove(x);
      return true;
    }).forEach((_) {});
  });
  test((ll) {
    ll.map((x) {
      ll.remove(x);
      return x;
    }).forEach((_) {});
  });
  test((ll) {
    ll.expand((x) {
      ll.remove(x);
      return [x];
    }).forEach((_) {});
  });
  test((ll) {
    ll.takeWhile((x) {
      ll.remove(x);
      return true;
    }).forEach((_) {});
  });
  test((ll) {
    ll.skipWhile((x) {
      ll.remove(x);
      return true;
    }).forEach((_) {});
  });
  test((ll) {
    bool first = true;
    ll.firstWhere((x) {
      ll.remove(x);
      if (!first) return true;
      return first = false;
    });
  });
  test((ll) {
    ll.lastWhere((x) {
      ll.remove(x);
      return true;
    });
  });
  test((ll) {
    bool first = true;
    ll.singleWhere((x) {
      ll.remove(x);
      if (!first) return false;
      return !(first = false);
    });
  });
}

void main() {
  testPreviousNext();
  testUnlinked();
  testInsert();
  testRemove();
  testContains();
  testBadAdd();
  testConcurrentModificationError();
}
