// Copyright 2018 The Chromium Authors
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#include "osp/impl/quic/quic_server.h"

#include <functional>
#include <memory>

#include "platform/api/task_runner.h"
#include "platform/api/time.h"
#include "util/osp_logging.h"

namespace openscreen::osp {

// static
QuicAgentCertificate& QuicServer::GetAgentCertificate() {
  static QuicAgentCertificate agent_certificate;
  return agent_certificate;
}

QuicServer::QuicServer(
    const EndpointConfig& config,
    MessageDemuxer& demuxer,
    std::unique_ptr<QuicConnectionFactoryServer> connection_factory,
    ProtocolConnectionServiceObserver& observer,
    ClockNowFunctionPtr now_function,
    TaskRunner& task_runner)
    : ProtocolConnectionServer(demuxer, observer),
      connection_endpoints_(config.connection_endpoints),
      connection_factory_(std::move(connection_factory)),
      cleanup_alarm_(now_function, task_runner) {}

QuicServer::~QuicServer() {
  CloseAllConnections();
}

bool QuicServer::Start() {
  if (state_ != State::kStopped)
    return false;
  state_ = State::kRunning;
  connection_factory_->SetServerDelegate(this, connection_endpoints_);
  Cleanup();  // Start periodic clean-ups.
  observer_.OnRunning();
  return true;
}

bool QuicServer::Stop() {
  if (state_ != State::kRunning && state_ != State::kSuspended)
    return false;
  connection_factory_->SetServerDelegate(nullptr, {});
  CloseAllConnections();
  state_ = State::kStopped;
  Cleanup();  // Final clean-up.
  observer_.OnStopped();
  return true;
}

bool QuicServer::Suspend() {
  // TODO(btolsch): QuicStreams should either buffer or reject writes.
  if (state_ != State::kRunning)
    return false;
  state_ = State::kSuspended;
  observer_.OnSuspended();
  return true;
}

bool QuicServer::Resume() {
  if (state_ != State::kSuspended)
    return false;
  state_ = State::kRunning;
  observer_.OnRunning();
  return true;
}

std::string QuicServer::GetAgentFingerprint() {
  return GetAgentCertificate().GetAgentFingerprint();
}

void QuicServer::Cleanup() {
  for (auto& entry : connections_)
    entry.second.delegate->DestroyClosedStreams();

  for (uint64_t instance_id : delete_connections_) {
    auto it = connections_.find(instance_id);
    if (it != connections_.end()) {
      connections_.erase(it);
    }
  }
  delete_connections_.clear();

  constexpr Clock::duration kQuicCleanupPeriod = std::chrono::milliseconds(500);
  if (state_ != State::kStopped) {
    cleanup_alarm_.ScheduleFromNow([this] { Cleanup(); }, kQuicCleanupPeriod);
  }
}

std::unique_ptr<ProtocolConnection> QuicServer::CreateProtocolConnection(
    uint64_t instance_id) {
  if (state_ != State::kRunning) {
    return nullptr;
  }
  auto connection_entry = connections_.find(instance_id);
  if (connection_entry == connections_.end()) {
    return nullptr;
  }
  return QuicProtocolConnection::FromExisting(
      *this, connection_entry->second.connection.get(),
      connection_entry->second.delegate.get(), instance_id);
}

void QuicServer::OnConnectionDestroyed(QuicProtocolConnection* connection) {
  if (!connection->stream())
    return;

  auto connection_entry = connections_.find(connection->instance_id());
  if (connection_entry == connections_.end())
    return;

  connection_entry->second.delegate->DropProtocolConnection(connection);
}

uint64_t QuicServer::OnCryptoHandshakeComplete(
    ServiceConnectionDelegate* delegate,
    std::string connection_id) {
  OSP_CHECK_EQ(state_, State::kRunning);
  const std::string& instance_name = delegate->instance_name();
  auto pending_entry = pending_connections_.find(instance_name);
  if (pending_entry == pending_connections_.end())
    return 0;
  ServiceConnectionData connection_data = std::move(pending_entry->second);
  pending_connections_.erase(pending_entry);
  uint64_t instance_id = next_instance_id_++;
  instance_map_[instance_name] = instance_id;
  connections_.emplace(instance_id, std::move(connection_data));
  return instance_id;
}

void QuicServer::OnIncomingStream(
    std::unique_ptr<QuicProtocolConnection> connection) {
  OSP_CHECK_EQ(state_, State::kRunning);
  observer_.OnIncomingConnection(std::move(connection));
}

void QuicServer::OnConnectionClosed(uint64_t instance_id,
                                    std::string connection_id) {
  OSP_CHECK_EQ(state_, State::kRunning);
  auto connection_entry = connections_.find(instance_id);
  if (connection_entry == connections_.end())
    return;
  delete_connections_.push_back(instance_id);

  instance_request_ids_.ResetRequestId(instance_id);
}

void QuicServer::OnDataReceived(uint64_t instance_id,
                                uint64_t protocol_connection_id,
                                const ByteView& bytes) {
  OSP_CHECK_EQ(state_, State::kRunning);
  demuxer_.OnStreamData(instance_id, protocol_connection_id, bytes.data(),
                        bytes.size());
}

void QuicServer::CloseAllConnections() {
  for (auto& conn : pending_connections_) {
    conn.second.connection->Close();
  }
  pending_connections_.clear();

  for (auto& conn : connections_) {
    conn.second.connection->Close();
  }
  connections_.clear();

  instance_map_.clear();
  next_instance_id_ = 1u;
  instance_request_ids_.Reset();
}

QuicConnection::Delegate* QuicServer::NextConnectionDelegate(
    const IPEndpoint& source) {
  OSP_CHECK_EQ(state_, State::kRunning);
  OSP_CHECK(!pending_connection_delegate_);
  // NOTE: There is no corresponding instance name for IPEndpoint on the client
  // side. So IPEndpoint is converted into a string and used as instance name.
  pending_connection_delegate_ =
      std::make_unique<ServiceConnectionDelegate>(*this, source.ToString());
  return pending_connection_delegate_.get();
}

void QuicServer::OnIncomingConnection(
    std::unique_ptr<QuicConnection> connection) {
  OSP_CHECK_EQ(state_, State::kRunning);
  const std::string& instance_name =
      pending_connection_delegate_->instance_name();
  pending_connections_.emplace(
      instance_name,
      ServiceConnectionData(std::move(connection),
                            std::move(pending_connection_delegate_)));
}

}  // namespace openscreen::osp
