/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
/*
 * Copyright (c) 2014-2020,  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/>.
 */

#include "transport.hpp"
#include "face.hpp"

namespace nfd {
namespace face {

NFD_LOG_INIT(Transport);

const ssize_t Transport::MIN_MTU;

std::ostream&
operator<<(std::ostream& os, TransportState state)
{
  switch (state) {
  case TransportState::UP:
    return os << "UP";
  case TransportState::DOWN:
    return os << "DOWN";
  case TransportState::CLOSING:
    return os << "CLOSING";
  case TransportState::FAILED:
    return os << "FAILED";
  case TransportState::CLOSED:
    return os << "CLOSED";
  default:
    return os << "NONE";
  }
}

Transport::Transport()
  : m_face(nullptr)
  , m_service(nullptr)
  , m_scope(ndn::nfd::FACE_SCOPE_NONE)
  , m_persistency(ndn::nfd::FACE_PERSISTENCY_NONE)
  , m_linkType(ndn::nfd::LINK_TYPE_NONE)
  , m_mtu(MTU_INVALID)
  , m_sendQueueCapacity(QUEUE_UNSUPPORTED)
  , m_state(TransportState::UP)
  , m_expirationTime(time::steady_clock::TimePoint::max())
{
}

Transport::~Transport() = default;

void
Transport::setFaceAndLinkService(Face& face, LinkService& service)
{
  BOOST_ASSERT(m_face == nullptr);
  BOOST_ASSERT(m_service == nullptr);

  m_face = &face;
  m_service = &service;
}

void
Transport::close()
{
  if (m_state != TransportState::UP && m_state != TransportState::DOWN) {
    return;
  }

  this->setState(TransportState::CLOSING);
  this->doClose();
  // warning: don't access any members after this:
  // the Transport may be deallocated if doClose changes state to CLOSED
}

void
Transport::send(const Block& packet, const EndpointId& endpoint)
{
  BOOST_ASSERT(packet.isValid());
  BOOST_ASSERT(this->getMtu() == MTU_UNLIMITED ||
               packet.size() <= static_cast<size_t>(this->getMtu()));

  TransportState state = this->getState();
  if (state != TransportState::UP && state != TransportState::DOWN) {
    NFD_LOG_FACE_TRACE("send ignored in " << state << " state");
    return;
  }

  if (state == TransportState::UP) {
    ++this->nOutPackets;
    this->nOutBytes += packet.size();
  }

  this->doSend(packet, endpoint);
}

void
Transport::receive(const Block& packet, const EndpointId& endpoint)
{
  BOOST_ASSERT(packet.isValid());
  BOOST_ASSERT(this->getMtu() == MTU_UNLIMITED ||
               packet.size() <= static_cast<size_t>(this->getMtu()));

  ++this->nInPackets;
  this->nInBytes += packet.size();

  m_service->receivePacket(packet, endpoint);
}

void
Transport::setMtu(ssize_t mtu)
{
  BOOST_ASSERT(mtu == MTU_UNLIMITED || mtu >= 0);

  if (mtu == m_mtu) {
    return;
  }

  if (m_mtu != MTU_INVALID) {
    NFD_LOG_FACE_INFO("setMtu " << m_mtu << " -> " << mtu);
  }

  m_mtu = mtu;
}

bool
Transport::canChangePersistencyTo(ndn::nfd::FacePersistency newPersistency) const
{
  // not changing, or setting initial persistency in subclass constructor
  if (m_persistency == newPersistency || m_persistency == ndn::nfd::FACE_PERSISTENCY_NONE) {
    return true;
  }

  if (newPersistency == ndn::nfd::FACE_PERSISTENCY_NONE) {
    NFD_LOG_FACE_TRACE("cannot change persistency to NONE");
    return false;
  }

  return this->canChangePersistencyToImpl(newPersistency);
}

bool
Transport::canChangePersistencyToImpl(ndn::nfd::FacePersistency newPersistency) const
{
  return false;
}

void
Transport::setPersistency(ndn::nfd::FacePersistency newPersistency)
{
  BOOST_ASSERT(canChangePersistencyTo(newPersistency));

  if (m_persistency == newPersistency) {
    return;
  }

  auto oldPersistency = m_persistency;
  m_persistency = newPersistency;

  if (oldPersistency != ndn::nfd::FACE_PERSISTENCY_NONE) {
    NFD_LOG_FACE_INFO("setPersistency " << oldPersistency << " -> " << newPersistency);
    this->afterChangePersistency(oldPersistency);
  }
}

void
Transport::afterChangePersistency(ndn::nfd::FacePersistency oldPersistency)
{
}

void
Transport::setState(TransportState newState)
{
  if (m_state == newState) {
    return;
  }

  bool isValid = false;
  switch (m_state) {
    case TransportState::UP:
      isValid = newState == TransportState::DOWN ||
                newState == TransportState::CLOSING ||
                newState == TransportState::FAILED;
      break;
    case TransportState::DOWN:
      isValid = newState == TransportState::UP ||
                newState == TransportState::CLOSING ||
                newState == TransportState::FAILED;
      break;
    case TransportState::CLOSING:
    case TransportState::FAILED:
      isValid = newState == TransportState::CLOSED;
      break;
    default:
      break;
  }

  if (!isValid) {
    NDN_THROW(std::runtime_error("Invalid state transition"));
  }

  NFD_LOG_FACE_INFO("setState " << m_state << " -> " << newState);

  TransportState oldState = m_state;
  m_state = newState;
  afterStateChange(oldState, newState);
  // warning: don't access any members after this:
  // the Transport may be deallocated in the signal handler if newState is CLOSED
}

std::ostream&
operator<<(std::ostream& os, const FaceLogHelper<Transport>& flh)
{
  const Transport& transport = flh.obj;
  const Face* face = transport.getFace();
  FaceId faceId = face == nullptr ? INVALID_FACEID : face->getId();

  os << "[id=" << faceId << ",local=" << transport.getLocalUri()
     << ",remote=" << transport.getRemoteUri() << "] ";
  return os;
}

} // namespace face
} // namespace nfd
