/* -*- 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);

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
