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

import "dart:async";
import "dart:io";
import "dart:typed_data";

import "package:async_helper/async_helper.dart";
import "package:expect/expect.dart";

class FutureExpect {
  static Future check(Future result, check) =>
      result.then((value) => check(value));
  static Future throws(Future result) =>
      result.then((value) {
        throw new ExpectException(
            "FutureExpect.throws received $value instead of an exception");
        }, onError: (_) => null);
}

testDatagramBroadcastOptions() {
  test(address) {
    asyncStart();
    RawDatagramSocket.bind(address, 0).then((socket) {
      Expect.isFalse(socket.broadcastEnabled);
      socket.broadcastEnabled = true;
      if (!Platform.isMacOS) {
        Expect.isTrue(socket.broadcastEnabled);
      }
      socket.broadcastEnabled = false;
      Expect.isFalse(socket.broadcastEnabled);
      asyncEnd();
    });
  }

  test(InternetAddress.LOOPBACK_IP_V4);
  test(InternetAddress.ANY_IP_V4);
}

testDatagramMulticastOptions() {
  test(address) {
    asyncStart();
    RawDatagramSocket.bind(address, 0).then((socket) {
      Expect.isTrue(socket.multicastLoopback);
      Expect.equals(1, socket.multicastHops);
      Expect.throws(() => socket.multicastInterface);

      socket.multicastLoopback = false;
      socket.multicastHops = 4;
      Expect.isFalse(socket.multicastLoopback);
      Expect.equals(4, socket.multicastHops);
      Expect.throws(() => socket.multicastInterface = null);

      socket.multicastLoopback = true;
      socket.multicastHops = 1;
      Expect.isTrue(socket.multicastLoopback);
      Expect.equals(1, socket.multicastHops);
      Expect.throws(() => socket.multicastInterface);

      asyncEnd();
    });
  }

  test(InternetAddress.LOOPBACK_IP_V4);
  test(InternetAddress.ANY_IP_V4);
  test(InternetAddress.LOOPBACK_IP_V6);
  test(InternetAddress.ANY_IP_V6);
}

testDatagramSocketReuseAddress() {
  test(address, reuseAddress) {
    asyncStart();
    RawDatagramSocket.bind(
        address, 0, reuseAddress: reuseAddress).then((socket) {
            if (reuseAddress) {
              RawDatagramSocket.bind(address, socket.port)
                  .then((s) => Expect.isTrue(s is RawDatagramSocket))
                  .then(asyncSuccess);
            } else {
              FutureExpect.throws(RawDatagramSocket.bind(address, socket.port))
                  .then(asyncSuccess);
            }
    });
  }

  test(InternetAddress.LOOPBACK_IP_V4, true);
  test(InternetAddress.LOOPBACK_IP_V4, false);
  test(InternetAddress.LOOPBACK_IP_V6, true);
  test(InternetAddress.LOOPBACK_IP_V6, false);
}

testBroadcast() {
  test(bindAddress, broadcastAddress, enabled) {
    asyncStart();
    Future.wait([RawDatagramSocket.bind(bindAddress, 0),
                 RawDatagramSocket.bind(bindAddress, 0)]).then((values) {
      var broadcastTimer;
      var sender = values[0];
      var receiver = values[1];
      // On Windows at least the receiver needs to have broadcast
      // enabled whereas on Linux at least the sender needs to.
      receiver.broadcastEnabled = enabled;
      sender.broadcastEnabled = enabled;
      receiver.listen((event) {
        if (event == RawSocketEvent.READ) {
          Expect.isTrue(enabled);
          sender.close();
          receiver.close();
          broadcastTimer.cancel();
          asyncEnd();
        }
      });

      int sendCount = 0;
      send(_) {
        int bytes =
            sender.send(new Uint8List(1), broadcastAddress, receiver.port);
        Expect.isTrue(bytes == 0 || bytes == 1);
        sendCount++;
        if (!enabled && sendCount == 50) {
          sender.close();
          receiver.close();
          broadcastTimer.cancel();
          asyncEnd();
        }
      }
      broadcastTimer = new Timer.periodic(new Duration(milliseconds: 10), send);
    });
  }

  var broadcast = new InternetAddress("255.255.255.255");
  test(InternetAddress.ANY_IP_V4, broadcast, false);
  test(InternetAddress.ANY_IP_V4, broadcast, true);
}

testLoopbackMulticast() {
  test(bindAddress, multicastAddress, enabled) {
    asyncStart();
    Future.wait([RawDatagramSocket.bind(bindAddress, 0),
                 RawDatagramSocket.bind(bindAddress, 0)]).then((values) {
      var senderTimer;
      var sender = values[0];
      var receiver = values[1];

      sender.joinMulticast(multicastAddress);
      receiver.joinMulticast(multicastAddress);
      // On Windows at least the receiver needs to have multicast
      // loop enabled whereas on Linux at least the sender needs to.
      receiver.multicastLoopback = enabled;
      sender.multicastLoopback = enabled;

      receiver.listen((event) {
        if (event == RawSocketEvent.READ) {
          Expect.isTrue(enabled);
          sender.close();
          receiver.close();
          senderTimer.cancel();
          asyncEnd();
        }
      });

      int sendCount = 0;
      send(_) {
        int bytes =
            sender.send(new Uint8List(1), multicastAddress, receiver.port);
        Expect.isTrue(bytes == 0 || bytes == 1);
        sendCount++;
        if (!enabled && sendCount == 50) {
          sender.close();
          receiver.close();
          senderTimer.cancel();
          asyncEnd();
        }
      }
      senderTimer = new Timer.periodic(new Duration(milliseconds: 10), send);
    });
  }

  test(InternetAddress.ANY_IP_V4, new InternetAddress("228.0.0.4"), true);
  test(InternetAddress.ANY_IP_V4, new InternetAddress("224.0.0.0"), false);
  if (!Platform.isMacOS) {
    test(InternetAddress.ANY_IP_V6, new InternetAddress("ff11::0"), true);
    test(InternetAddress.ANY_IP_V6, new InternetAddress("ff11::0"), false);
  }
}

testSendReceive(InternetAddress bindAddress) {
  asyncStart();

  var total = 1000;

  int receivedSeq = 0;

  var ackSeq = 0;
  Timer ackTimer;

  Future.wait([RawDatagramSocket.bind(bindAddress, 0),
               RawDatagramSocket.bind(bindAddress, 0)]).then((values) {
  var sender = values[0];
  var receiver = values[1];
  if (bindAddress.isMulticast) {
    sender.multicastLoopback = true;
    receiver.multicastLoopback = true;
    sender.joinMulticast(bindAddress);
    receiver.joinMulticast(bindAddress);
  }

  Uint8List createDataPackage(int seq) {
    var data = new Uint8List(1000);
    (new ByteData.view(data.buffer, 0, 4)).setUint32(0, seq);
    return data;
  }

  Uint8List createAckPackage(int seq) {
    var data = new Uint8List(4);
    new ByteData.view(data.buffer, 0, 4).setUint32(0, seq);
    return data;
  }

  int packageSeq(Datagram datagram) =>
      new ByteData.view((datagram.data as Uint8List).buffer).getUint32(0);

  void sendData(int seq) {
    // Send a datagram acknowledging the received sequence.
    int bytes = sender.send(createDataPackage(seq), bindAddress, receiver.port);
    Expect.isTrue(bytes == 0 || bytes == 1000);
  }

  void sendAck(address, port) {
    // Send a datagram acknowledging the received sequence.
    int bytes = receiver.send(createAckPackage(receivedSeq), address, port);
    Expect.isTrue(bytes == 0 || bytes == 4);
    // Start a "long" timer for more data.
    if (ackTimer != null) ackTimer.cancel();
    ackTimer = new Timer.periodic(
        new Duration(milliseconds: 100), (_) => sendAck(address, port));
  }

  sender.listen((event) {
    switch (event) {
      case RawSocketEvent.READ:
        var datagram = sender.receive();
        if (datagram != null) {
          Expect.equals(datagram.port, receiver.port);
          if (!bindAddress.isMulticast) {
            Expect.equals(receiver.address, datagram.address);
          }
          ackSeq = packageSeq(datagram);
          if (ackSeq < total) {
            sender.writeEventsEnabled = true;
          } else {
            sender.close();
            receiver.close();
            ackTimer.cancel();
            asyncEnd();
          }
        }
        break;
      case RawSocketEvent.WRITE:
        // Send the next package.
        sendData(ackSeq + 1);
        break;
      case RawSocketEvent.CLOSED:
        break;
      default:
        throw "Unexpected event $event";
    }
  });

  receiver.writeEventsEnabled = false;
  receiver.listen((event) {
    switch (event) {
      case RawSocketEvent.READ:
        var datagram = receiver.receive();
        if (datagram != null) {
          Expect.equals(datagram.port, sender.port);
          if (!bindAddress.isMulticast) {
            Expect.equals(receiver.address, datagram.address);
          }
          var seq = packageSeq(datagram);
          if (seq == receivedSeq + 1) {
            receivedSeq = seq;
            sendAck(bindAddress, sender.port);
          }
        }
        break;
      case RawSocketEvent.WRITE:
        throw "Unexpected WRITE";
        break;
      case RawSocketEvent.CLOSED:
        break;
      default:
        throw "Unexpected event $event";
    }
  });
  });
}


main() {
  testDatagramBroadcastOptions();
  testDatagramMulticastOptions();
  if (!Platform.isMacOS) {
    testDatagramSocketReuseAddress();
  }
  testBroadcast();
  testLoopbackMulticast();
  testSendReceive(InternetAddress.LOOPBACK_IP_V4);
  testSendReceive(InternetAddress.LOOPBACK_IP_V6);
}
