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

// VMOptions=--no-enable-fast-object-copy
// VMOptions=--enable-fast-object-copy

import "dart:async";
import "dart:collection";
import "dart:isolate";
import "dart:typed_data";
import "package:expect/expect.dart";

const large = 2 * 1024 * 1024;

void child(replyPort) {
  print("Child start");

  print("Child ByteData");
  dynamic x = new ByteData(large);
  for (int i = 0; i < 4; i++) {
    x.setInt8(i, i);
  }
  replyPort.send(TransferableTypedData.fromList([x.buffer.asUint8List()]));

  print("Child Uint8List");
  x = new Uint8List(large);
  for (int i = 0; i < 4; i++) {
    x[i] = i;
  }
  replyPort.send(TransferableTypedData.fromList([x]));

  print("Child Uint8List.view");
  x = new Uint8List.view(x.buffer, 1, 2);
  replyPort.send(TransferableTypedData.fromList([x]));

  print("Child Int8List");
  x = new Int8List(large);
  for (int i = 0; i < 4; i++) {
    x[i] = i;
  }
  replyPort.send(TransferableTypedData.fromList([x]));

  print("Child Uint16List");
  x = new Uint16List(large);
  for (int i = 0; i < 4; i++) {
    x[i] = i;
  }
  replyPort.send(TransferableTypedData.fromList([x]));

  print("Child Int16List");
  x = new Int16List(large);
  for (int i = 0; i < 4; i++) {
    x[i] = i;
  }
  replyPort.send(TransferableTypedData.fromList([x]));

  print("Child Uint32List");
  x = new Uint32List(large);
  for (int i = 0; i < 4; i++) {
    x[i] = i;
  }
  replyPort.send(TransferableTypedData.fromList([x]));

  print("Child Int32List");
  x = new Int32List(large);
  for (int i = 0; i < 4; i++) {
    x[i] = i;
  }
  replyPort.send(TransferableTypedData.fromList([x]));

  print("Child Uint64List");
  x = new Uint64List(large);
  for (int i = 0; i < 4; i++) {
    x[i] = i;
  }
  replyPort.send(TransferableTypedData.fromList([x]));

  print("Child Int64List");
  x = new Int64List(large);
  for (int i = 0; i < 4; i++) {
    x[i] = i;
  }
  replyPort.send(TransferableTypedData.fromList([x]));

  print("Child two Uint8Lists");
  x = new Uint8List(large);
  for (int i = 0; i < 4; i++) {
    x[i] = i;
  }
  replyPort.send([
    TransferableTypedData.fromList([x]),
    TransferableTypedData.fromList([x]),
  ]);

  print("Child same Uint8List twice - materialize first");
  x = new Uint8List(large);
  for (int i = 0; i < 4; i++) {
    x[i] = i;
  }
  var tr = TransferableTypedData.fromList([x]);
  replyPort.send([tr, tr]);

  print("Child same Uint8List twice - materialize second");
  x = new Uint8List(large);
  for (int i = 0; i < 4; i++) {
    x[i] = i;
  }
  tr = TransferableTypedData.fromList([x]);
  replyPort.send([tr, tr]);

  print("Child done");
}

Future<void> main(List<String> args) async {
  print("Parent start");

  ReceivePort port = new ReceivePort();
  Isolate.spawn(child, port.sendPort);
  StreamIterator<dynamic> incoming = new StreamIterator<dynamic>(port);

  print("Parent ByteData");
  Expect.isTrue(await incoming.moveNext());
  dynamic x = incoming.current.materialize().asByteData();
  Expect.isTrue(x is ByteData);
  Expect.equals(large, x.length);
  for (int i = 0; i < 4; i++) {
    Expect.equals(i, x.getUint8(i));
  }

  print("Parent Uint8List");
  Expect.isTrue(await incoming.moveNext());
  x = incoming.current.materialize();
  Expect.isTrue(x is ByteBuffer);
  x = x.asUint8List();
  Expect.equals(large, x.length);
  for (int i = 0; i < 4; i++) {
    Expect.equals(i, x[i]);
  }

  print("Parent Uint8List view");
  Expect.isTrue(await incoming.moveNext());
  x = incoming.current.materialize().asUint8List();
  Expect.equals(1, x[0]);
  Expect.equals(2, x[1]);

  print("Parent Int8");
  Expect.isTrue(await incoming.moveNext());
  x = incoming.current.materialize().asInt8List();
  Expect.equals(large, x.length);
  for (int i = 0; i < 4; i++) {
    Expect.equals(i, x[i]);
  }

  print("Parent Uint16");
  Expect.isTrue(await incoming.moveNext());
  x = incoming.current.materialize().asUint16List();
  Expect.equals(large, x.length);
  for (int i = 0; i < 4; i++) {
    Expect.equals(i, x[i]);
  }

  print("Parent Int16");
  Expect.isTrue(await incoming.moveNext());
  x = incoming.current.materialize().asInt16List();
  Expect.equals(large, x.length);
  for (int i = 0; i < 4; i++) {
    Expect.equals(i, x[i]);
  }

  print("Parent Uint32");
  Expect.isTrue(await incoming.moveNext());
  x = incoming.current.materialize().asUint32List();
  Expect.equals(large, x.length);
  for (int i = 0; i < 4; i++) {
    Expect.equals(i, x[i]);
  }

  print("Parent Int32");
  Expect.isTrue(await incoming.moveNext());
  x = incoming.current.materialize().asInt32List();
  Expect.equals(large, x.length);
  for (int i = 0; i < 4; i++) {
    Expect.equals(i, x[i]);
  }

  print("Parent Uint64");
  Expect.isTrue(await incoming.moveNext());
  x = incoming.current.materialize().asUint64List();
  Expect.equals(large, x.length);
  for (int i = 0; i < 4; i++) {
    Expect.equals(i, x[i]);
  }

  print("Parent Int64");
  Expect.isTrue(await incoming.moveNext());
  x = incoming.current.materialize().asInt64List();
  Expect.equals(large, x.length);
  for (int i = 0; i < 4; i++) {
    Expect.equals(i, x[i]);
  }

  print("Parent two Uint8Lists");
  Expect.isTrue(await incoming.moveNext());
  final x1 = incoming.current[0].materialize().asUint8List();
  final x2 = incoming.current[1].materialize().asUint8List();
  Expect.equals(large, x1.length);
  Expect.equals(large, x2.length);
  for (int i = 0; i < 4; i++) {
    Expect.equals(i, x1[i]);
    Expect.equals(i, x2[i]);
  }

  print("Parent same Uint8Lists twice, materialize first");
  Expect.isTrue(await incoming.moveNext());
  final tr0 = incoming.current[0].materialize().asUint8List();
  Expect.throwsArgumentError(() => incoming.current[1].materialize());
  Expect.equals(large, tr0.length);
  for (int i = 0; i < 4; i++) {
    Expect.equals(i, tr0[i]);
  }

  print("Parent same Uint8Lists twice, materialize second");
  Expect.isTrue(await incoming.moveNext());
  final tr1 = incoming.current[1].materialize().asUint8List();
  Expect.throwsArgumentError(() => incoming.current[0].materialize());
  Expect.equals(large, tr1.length);
  for (int i = 0; i < 4; i++) {
    Expect.equals(i, tr1[i]);
  }

  port.close();
  print("Parent done");

  testCreateMaterializeInSameIsolate();
  testIterableToList();
  testUserExtendedList();
}

testCreateMaterializeInSameIsolate() {
  // Test same-isolate operation of TransferableTypedData.
  final Uint8List bytes = new Uint8List(large);
  for (int i = 0; i < bytes.length; ++i) {
    bytes[i] = i % 256;
  }
  final tr = TransferableTypedData.fromList([bytes]);
  Expect.listEquals(bytes, tr.materialize().asUint8List());
}

testIterableToList() {
  // Test that iterable.toList() can be used as an argument.
  final list1 = Uint8List(10);
  for (int i = 0; i < list1.length; i++) {
    list1[i] = i;
  }
  final list2 = Uint8List(20);
  for (int i = 0; i < list2.length; i++) {
    list2[i] = i + list1.length;
  }
  final map = {list1: true, list2: true};
  Iterable<Uint8List> iterable = map.keys;
  final result = TransferableTypedData.fromList(
    iterable.toList(),
  ).materialize().asUint8List();
  for (int i = 0; i < result.length; i++) {
    Expect.equals(i, result[i]);
  }
}

class MyList<E> extends ListBase<E> {
  List<E> _source;
  MyList(this._source);
  int get length => _source.length;
  void set length(int length) {
    _source.length = length;
  }

  E operator [](int index) => _source[index];
  void operator []=(int index, E value) {
    _source[index] = value;
  }
}

testUserExtendedList() {
  final list = MyList<TypedData>([Uint8List(10)]);
  TransferableTypedData.fromList(list);
}
