/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
/*
 * Copyright (c) 2014-2022,  Regents of the University of California,
 *                           Arizona Board of Regents,
 *                           Colorado State University,
 *                           University Pierre & Marie Curie, Sorbonne University,
 *                           Washington University in St. Louis,
 *                           Beijing Institute of Technology,
 *                           The University of Memphis.
 *
 * This file is part of NFD (Named Data Networking Forwarding Daemon).
 * See AUTHORS.md for complete list of NFD authors and contributors.
 *
 * NFD is free software: you can redistribute it and/or modify it under the terms
 * of the GNU General Public License as published by the Free Software Foundation,
 * either version 3 of the License, or (at your option) any later version.
 *
 * NFD is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY;
 * without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
 * PURPOSE.  See the GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License along with
 * NFD, e.g., in COPYING.md file.  If not, see <http://www.gnu.org/licenses/>.
 */

#ifndef NFD_TESTS_DAEMON_FACE_WEBSOCKET_TRANSPORT_FIXTURE_HPP
#define NFD_TESTS_DAEMON_FACE_WEBSOCKET_TRANSPORT_FIXTURE_HPP

#include "face/websocket-transport.hpp"
#include "face/face.hpp"

#include "tests/test-common.hpp"
#include "tests/daemon/limited-io.hpp"
#include "tests/daemon/face/dummy-link-service.hpp"
#include "tests/daemon/face/transport-test-common.hpp"

namespace nfd::tests {

namespace ip = boost::asio::ip;
using face::WebSocketTransport;

/** \brief a fixture that accepts a single WebSocket connection from a client
 */
class WebSocketTransportFixture : public GlobalIoFixture
{
protected:
  /** \brief initialize server and start listening
   */
  void
  serverListen(const ip::tcp::endpoint& ep,
               const time::milliseconds& pongTimeout = 1_s)
  {
    server.clear_access_channels(websocketpp::log::alevel::all);
    server.clear_error_channels(websocketpp::log::elevel::all);

    server.init_asio(&g_io);
    server.set_open_handler(std::bind(&WebSocketTransportFixture::serverHandleOpen, this, _1));
    server.set_close_handler(std::bind(&WebSocketTransportFixture::serverHandleClose, this));
    server.set_message_handler(std::bind(&WebSocketTransportFixture::serverHandleMessage, this, _2));
    server.set_pong_handler(std::bind(&WebSocketTransportFixture::serverHandlePong, this));
    server.set_pong_timeout_handler(std::bind(&WebSocketTransportFixture::serverHandlePongTimeout, this));
    server.set_pong_timeout(pongTimeout.count());

    server.set_reuse_addr(true);

    server.listen(ep);
    server.start_accept();
  }

  /** \brief initialize client and connect to server
   */
  void
  clientConnect(const std::string& uri)
  {
    client.clear_access_channels(websocketpp::log::alevel::all);
    client.clear_error_channels(websocketpp::log::elevel::all);

    client.init_asio(&g_io);
    client.set_open_handler(std::bind(&WebSocketTransportFixture::clientHandleOpen, this, _1));
    client.set_message_handler(std::bind(&WebSocketTransportFixture::clientHandleMessage, this, _2));
    client.set_ping_handler(std::bind(&WebSocketTransportFixture::clientHandlePing, this));

    websocketpp::lib::error_code ec;
    auto con = client.get_connection(uri, ec);
    BOOST_REQUIRE_EQUAL(ec, websocketpp::lib::error_code());

    client.connect(con);
  }

  /**
   * \brief Initialize both server and client, and have each other connected, create Transport
   */
  void
  initialize(const shared_ptr<const ndn::net::NetworkInterface>&,
             const ip::address& address,
             time::milliseconds pingInterval = 10_s,
             time::milliseconds pongTimeout = 1_s)
  {
    ip::tcp::endpoint ep(address, 20070);
    serverListen(ep, pongTimeout);
    clientConnect(FaceUri(ep, "ws").toString());

    BOOST_REQUIRE_EQUAL(limitedIo.run(2, // serverHandleOpen, clientHandleOpen
                                      1_s), LimitedIo::EXCEED_OPS);

    face = make_unique<Face>(make_unique<DummyLinkService>(),
                             make_unique<WebSocketTransport>(serverHdl, server, pingInterval));
    transport = static_cast<WebSocketTransport*>(face->getTransport());
    serverReceivedPackets = &static_cast<DummyLinkService*>(face->getLinkService())->receivedPackets;

    BOOST_REQUIRE_EQUAL(transport->getState(), face::TransportState::UP);
  }

private:
  void
  serverHandleOpen(websocketpp::connection_hdl hdl)
  {
    websocketpp::lib::error_code ec;
    auto con = server.get_con_from_hdl(hdl, ec);
    BOOST_REQUIRE_EQUAL(ec, websocketpp::lib::error_code());
    BOOST_REQUIRE(con);
    remoteEp = con->get_socket().remote_endpoint();

    serverHdl = hdl;
    limitedIo.afterOp();
  }

  void
  serverHandleClose()
  {
    if (transport == nullptr) {
      return;
    }

    transport->close();
    limitedIo.afterOp();
  }

  void
  serverHandleMessage(websocket::Server::message_ptr msg)
  {
    if (transport == nullptr) {
      return;
    }

    transport->receiveMessage(msg->get_payload());
    limitedIo.afterOp();
  }

  void
  serverHandlePong()
  {
    if (transport == nullptr) {
      return;
    }

    transport->handlePong();
    limitedIo.afterOp();
  }

  void
  serverHandlePongTimeout()
  {
    if (transport == nullptr) {
      return;
    }

    transport->handlePongTimeout();
    limitedIo.afterOp();
  }

  void
  clientHandleOpen(websocketpp::connection_hdl hdl)
  {
    clientHdl = hdl;
    limitedIo.afterOp();
  }

  void
  clientHandleMessage(websocket::Client::message_ptr msg)
  {
    clientReceivedMessages.push_back(msg->get_payload());
    limitedIo.afterOp();
  }

  bool
  clientHandlePing()
  {
    limitedIo.afterOp();
    return clientShouldPong;
  }

protected:
  LimitedIo limitedIo;

  websocket::Server server;
  websocketpp::connection_hdl serverHdl;
  ip::tcp::endpoint remoteEp;
  WebSocketTransport* transport = nullptr;
  std::vector<RxPacket>* serverReceivedPackets = nullptr;

  websocket::Client client;
  websocketpp::connection_hdl clientHdl;
  bool clientShouldPong = true;
  std::vector<std::string> clientReceivedMessages;

private:
  unique_ptr<Face> face;
};

} // namespace nfd::tests

#endif // NFD_TESTS_DAEMON_FACE_WEBSOCKET_TRANSPORT_FIXTURE_HPP
