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

/// http and web sockets utils
/// @author a.semenov@unipro.ru

library http_utils;

import "dart:io";
import "dart:async";
import "../../Utils/expect.dart";

/**
 * Spawns a HttpServer instance
 */
Future<HttpServer> spawnHttpServer(void requestHandler(HttpRequest request)) async {
  HttpServer server = await HttpServer.bind(InternetAddress.loopbackIPv4, 0);
  server.listen(requestHandler);
  return server;
}

/**
 * Spawns a HttpServer instance that is intended to handle web sockets.
 */
Future<HttpServer> spawnWebSocketServer(void wsHandler(WebSocket webSocket)) {
  return spawnHttpServer((HttpRequest request) {
    WebSocketTransformer.upgrade(request).then(wsHandler);
  });
}

/**
 * Spawns a HttpServer instance that is intended to handle web sockets.
 * Each new connection receives the same [content] and then closed.
 */
Future<HttpServer> spawnStaticContentWebSocketServer(content) {
  return spawnWebSocketServer((WebSocket webSocket) {
    webSocket.add(content);
    webSocket.close();
  });
}

/**
 * Spawns a HttpServer instance that is intended to handle web sockets.
 * Each new connection is listened for first message and send it back,
 * then web socket is closed.
 */
Future<HttpServer> spawnEchoWebSocketServer() {
  return spawnWebSocketServer((WebSocket webSocket) async {
    webSocket.add(await webSocket.first);
    webSocket.close();
  });
}

List<int> _bigData = [];

List<int> get bigData  {
 if (_bigData.isEmpty) {
   _bigData = getList(8187);
 }
 return _bigData;
}

List<int> getList(int size) {
  List<int> l = [];
  for (int j = 0; j < size; j++) {
    l.add(j);
  }
  return l;
}

Future<List<int>> sendDatagramOnce(RawDatagramSocket producer,
    List<List<int>> data, InternetAddress address, int port,
    {Duration period = const Duration(milliseconds: 1)}) {
  List<int> sent = [];
  Completer<List<int>> completer = new Completer<List<int>>();
  Future<List<int>> f = completer.future;
  int i = 0;
  new Timer.periodic(period, (timer) {
    if (i < data.length) {
      sent.add(producer.send(data[i++], address, port));
    } else {
      timer.cancel();
      completer.complete(sent);
    }
  });
  return f;
}

Future<bool> sendDatagram(RawDatagramSocket producer, List<List<int>> data,
    InternetAddress address, int port,
    {Duration period = const Duration(milliseconds: 1), int attempts = 5,
      bool closeProducer = true}) async {
  for (int attempt = 0; attempt < attempts; attempt++) {
    List<int> bytesWritten = await sendDatagramOnce(producer, data, address, port,
        period: period);
    if (wasSent(bytesWritten)) {
      compareSentData(data, bytesWritten);
      if (closeProducer) {
        producer.close();
      }
      return true;
    }
  }
  producer.close();
  return false;
}

/***
 * Check that there is any buffer size > 0
 */
bool wasSent(List<int> bytesWritten) {
  for (int i = 0; i < bytesWritten.length; i++) {
    if (bytesWritten[i] > 0) {
      return true;
    }
  }
  return false;
}

compareSentData(List<List<int>> data, List<int> sentStatus) {
  Expect.equals(sentStatus.length, data.length, "Wrong sizes of sent and sentResult");
  for (int i = 0; i < data.length; i++) {
    if (sentStatus[i] == 0) {
      continue;
    }
    Expect.equals(data[i].length, sentStatus[i]);
  }
}

Future<List<List<int>>> receiveDatagram(RawDatagramSocket receiver,
    {Duration delay = const Duration(seconds: 2), RawSocketEvent? event}) {
  List<List<int>> received = [];
  Completer<List<List<int>>> completer = new Completer<List<List<int>>>();
  Future<List<List<int>>> f = completer.future;
  receiver.listen((_event) {
    var datagram = receiver.receive();
    if (event == null || _event == event) {
      var d = datagram?.data.toList();
      if (d != null) {
        received.add(d);
      }
    }
    if (_event == RawSocketEvent.closed) {
      if(!completer.isCompleted) {
        completer.complete(received);
      }
    }
  });
  new Future.delayed(delay, () {
    if(!completer.isCompleted) {
      receiver.close();
      completer.complete(received);
    }
  });
  return f;
}

/**
 * If we receive datagram we check if received data can be found among sent ones
 */
compareReceivedData(List<List<int>> sent, List<List<int>> received) {
  Expect.isTrue(received.length <= sent.length, "${received.length} <= ${sent.length}");
  for (int i = 0; i < received.length; i++) {
    bool found = false;
    for (int j = 0; j < sent.length; j++) {
      if (_listEquals(received[i], sent[j])) {
        found = true;
        break;
      }
    }
    Expect.isTrue(found, "${received[i]} not found among $sent");
  }
}

bool _listEquals(List<int> list1, List<int> list2) {
  if (list1.length == list2.length) {
    for (int i = 0; i < list1.length; i++) {
      if (list1[i] != list2[i]) {
        return false;
      }
    }
    return true;
  }
  return false;
}

Future<List<RawSocketEvent>> anyElement(RawDatagramSocket receiver,
    RawSocketEvent expectedEvent, bool shouldFind,
    {Duration delay = const Duration(seconds: 2)}) {
  List<RawSocketEvent> tested = [];
  Completer<List<RawSocketEvent>> completer =
      new Completer<List<RawSocketEvent>>();
  Future<List<RawSocketEvent>> f = completer.future;

  bool test(x) {
    tested.add(x);
    receiver.receive();
    if (x == RawSocketEvent.closed) {
      if (!completer.isCompleted) {
        completer.complete(tested);
      }
    }
    return x == expectedEvent;
  }

  receiver.any((event) => test(event)).then((value) {
    if (shouldFind) {
      Expect.equals(true, value);
    } else {
      Expect.equals(false, value);
    }
    if (!completer.isCompleted) {
      receiver.close();
      completer.complete(tested);
    }
  });

  new Future.delayed(delay, () {
    if (!completer.isCompleted) {
      receiver.close();
    }
  });
  return f;
}

checkTested<T>(List<T> tested, T expected) {
  for (int i = tested.length - 2; i >= 0; i--) {
    Expect.notEquals(expected, tested[i]);
  }
}

checkReceived(check, List<RawSocketEvent> expectedValues, int expectedLen,
    {int attempts = 5}) async {
  for (int i = 0; i < attempts; i++) {
    List list = await check();
    int listLen = list.length;
    if (listLen == 0) {
      continue;
    }
    if (listLen > 0 && listLen <= expectedLen) {
      for (int i = 0; i < list.length; i++) {
        Expect.isTrue(
            expectedValues.contains(list[i]), "Unexpected value ${list[i]}");
      }
      break;
    }
    if (listLen > expectedLen) {
      Expect.fail("$listLen elements found instead of $expectedLen.");
    }
    if (i == attempts - 1) {
      print('$listLen elements found. Look like test failed.');
    }
  }
}
