/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
/**
 * Copyright (c) 2013-2014 Regents of the University of California.
 *
 * This file is part of ndn-cxx library (NDN C++ library with eXperimental eXtensions).
 *
 * ndn-cxx library is free software: you can redistribute it and/or modify it under the
 * terms of the GNU Lesser General Public License as published by the Free Software
 * Foundation, either version 3 of the License, or (at your option) any later version.
 *
 * ndn-cxx library 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 Lesser General Public License for more details.
 *
 * You should have received copies of the GNU General Public License and GNU Lesser
 * General Public License along with ndn-cxx, e.g., in COPYING.md file.  If not, see
 * <http://www.gnu.org/licenses/>.
 *
 * See AUTHORS.md for complete list of ndn-cxx authors and contributors.
 */

#ifndef NDN_DETAIL_FACE_IMPL_HPP
#define NDN_DETAIL_FACE_IMPL_HPP

#include "../common.hpp"
#include "../face.hpp"

#include "registered-prefix.hpp"
#include "pending-interest.hpp"

#include "../util/scheduler.hpp"
#include "../util/config-file.hpp"

#include "transport/transport.hpp"
#include "transport/unix-transport.hpp"
#include "transport/tcp-transport.hpp"

#include "management/nfd-controller.hpp"

namespace ndn {

class Face::Impl : noncopyable
{
public:
  typedef std::list<shared_ptr<PendingInterest> > PendingInterestTable;
  typedef std::list<shared_ptr<InterestFilterRecord> > InterestFilterTable;
  typedef std::list<shared_ptr<RegisteredPrefix> > RegisteredPrefixTable;

  explicit
  Impl(Face& face)
    : m_face(face)
  {
  }

  /////////////////////////////////////////////////////////////////////////////////////////////////
  /////////////////////////////////////////////////////////////////////////////////////////////////

  void
  satisfyPendingInterests(Data& data)
  {
    for (PendingInterestTable::iterator i = m_pendingInterestTable.begin();
         i != m_pendingInterestTable.end();
         )
      {
        if ((*i)->getInterest()->matchesData(data))
          {
            // Copy pointers to the objects and remove the PIT entry before calling the callback.
            OnData onData = (*i)->getOnData();
            shared_ptr<const Interest> interest = (*i)->getInterest();

            PendingInterestTable::iterator next = i;
            ++next;
            m_pendingInterestTable.erase(i);
            i = next;

            if (static_cast<bool>(onData)) {
              onData(*interest, data);
            }
          }
        else
          ++i;
      }
  }

  void
  processInterestFilters(Interest& interest)
  {
    for (InterestFilterTable::iterator i = m_interestFilterTable.begin();
         i != m_interestFilterTable.end();
         ++i)
      {
        if ((*i)->doesMatch(interest.getName()))
          {
            (**i)(interest);
          }
      }
  }

  /////////////////////////////////////////////////////////////////////////////////////////////////
  /////////////////////////////////////////////////////////////////////////////////////////////////

  void
  asyncExpressInterest(const shared_ptr<const Interest>& interest,
                       const OnData& onData, const OnTimeout& onTimeout)
  {
    if (!m_face.m_transport->isConnected())
      m_face.m_transport->connect(*m_face.m_ioService,
                                  bind(&Face::onReceiveElement, &m_face, _1));

    if (!m_face.m_transport->isExpectingData())
      m_face.m_transport->resume();

    m_pendingInterestTable.push_back(make_shared<PendingInterest>(interest, onData, onTimeout));

    if (!interest->getLocalControlHeader().empty(false, true))
      {
        // encode only NextHopFaceId towards the forwarder
        m_face.m_transport->send(interest->getLocalControlHeader()
                                   .wireEncode(*interest, false, true),
                                 interest->wireEncode());
      }
    else
      {
        m_face.m_transport->send(interest->wireEncode());
      }

    if (!m_pitTimeoutCheckTimerActive) {
      m_pitTimeoutCheckTimerActive = true;
      m_pitTimeoutCheckTimer->expires_from_now(time::milliseconds(100));
      m_pitTimeoutCheckTimer->async_wait(bind(&Impl::checkPitExpire, this));
    }
  }

  void
  asyncRemovePendingInterest(const PendingInterestId* pendingInterestId)
  {
    m_pendingInterestTable.remove_if(MatchPendingInterestId(pendingInterestId));
  }

  void
  asyncPutData(const shared_ptr<const Data>& data)
  {
    if (!m_face.m_transport->isConnected())
      m_face.m_transport->connect(*m_face.m_ioService,
                                  bind(&Face::onReceiveElement, &m_face, _1));

    if (!m_face.m_transport->isExpectingData())
      m_face.m_transport->resume();

    if (!data->getLocalControlHeader().empty(false, true))
      {
        m_face.m_transport->send(data->getLocalControlHeader().wireEncode(*data, false, true),
                                 data->wireEncode());
      }
    else
      {
        m_face.m_transport->send(data->wireEncode());
      }
  }

  /////////////////////////////////////////////////////////////////////////////////////////////////
  /////////////////////////////////////////////////////////////////////////////////////////////////

  void
  asyncSetInterestFilter(const shared_ptr<InterestFilterRecord>& interestFilterRecord)
  {
    m_interestFilterTable.push_back(interestFilterRecord);
  }

  void
  asyncUnsetInterestFilter(const InterestFilterId* interestFilterId)
  {
    InterestFilterTable::iterator i = std::find_if(m_interestFilterTable.begin(),
                                                   m_interestFilterTable.end(),
                                                   MatchInterestFilterId(interestFilterId));
    if (i != m_interestFilterTable.end())
      {
        m_interestFilterTable.erase(i);
      }
  }

  /////////////////////////////////////////////////////////////////////////////////////////////////
  /////////////////////////////////////////////////////////////////////////////////////////////////

  template<class SignatureGenerator>
  const RegisteredPrefixId*
  registerPrefix(const Name& prefix,
                 const shared_ptr<InterestFilterRecord>& filter,
                 const RegisterPrefixSuccessCallback& onSuccess,
                 const RegisterPrefixFailureCallback& onFailure,
                 uint64_t flags,
                 const SignatureGenerator& signatureGenerator)
  {
    using namespace nfd;

    typedef void (nfd::Controller::*Registrator)
      (const nfd::ControlParameters&,
       const nfd::Controller::CommandSucceedCallback&,
       const nfd::Controller::CommandFailCallback&,
       const SignatureGenerator&,
       const time::milliseconds&);

    ControlParameters registerParameters, unregisterParameters;
    registerParameters.setName(prefix);
    unregisterParameters.setName(prefix);

    Registrator registrator, unregistrator;
    if (!m_face.m_isDirectNfdFibManagementRequested) {
      registrator = static_cast<Registrator>(&Controller::start<RibRegisterCommand>);
      unregistrator = static_cast<Registrator>(&Controller::start<RibUnregisterCommand>);

      registerParameters.setFlags(flags);
    }
    else {
      registrator = static_cast<Registrator>(&Controller::start<FibAddNextHopCommand>);
      unregistrator = static_cast<Registrator>(&Controller::start<FibRemoveNextHopCommand>);
    }

    RegisteredPrefix::Unregistrator bindedUnregistrator =
        ndn::bind(unregistrator, m_face.m_nfdController.get(), unregisterParameters, _1, _2,
                  signatureGenerator,
                  m_face.m_nfdController->getDefaultCommandTimeout());

    shared_ptr<RegisteredPrefix> prefixToRegister =
      make_shared<RegisteredPrefix>(prefix, filter, bindedUnregistrator);

    ((*m_face.m_nfdController).*registrator)(registerParameters,
                                             bind(&Impl::afterPrefixRegistered, this,
                                                  prefixToRegister, onSuccess),
                                             bind(onFailure, prefixToRegister->getPrefix(), _2),
                                             signatureGenerator,
                                             m_face.m_nfdController->getDefaultCommandTimeout());

    return reinterpret_cast<const RegisteredPrefixId*>(prefixToRegister.get());
  }

  void
  afterPrefixRegistered(const shared_ptr<RegisteredPrefix>& registeredPrefix,
                        const RegisterPrefixSuccessCallback& onSuccess)
  {
    m_registeredPrefixTable.push_back(registeredPrefix);

    if (static_cast<bool>(registeredPrefix->getFilter())) {
      // it was a combined operation
      m_interestFilterTable.push_back(registeredPrefix->getFilter());
    }

    if (static_cast<bool>(onSuccess)) {
      onSuccess(registeredPrefix->getPrefix());
    }
  }

  void
  asyncUnregisterPrefix(const RegisteredPrefixId* registeredPrefixId,
                        const UnregisterPrefixSuccessCallback& onSuccess,
                        const UnregisterPrefixFailureCallback& onFailure)
  {
    RegisteredPrefixTable::iterator i = std::find_if(m_registeredPrefixTable.begin(),
                                                     m_registeredPrefixTable.end(),
                                                     MatchRegisteredPrefixId(registeredPrefixId));
    if (i != m_registeredPrefixTable.end())
      {
        const shared_ptr<InterestFilterRecord>& filter = (*i)->getFilter();
        if (static_cast<bool>(filter))
          {
            // it was a combined operation
            m_interestFilterTable.remove(filter);
          }

        (*i)->unregister(bind(&Impl::finalizeUnregisterPrefix, this, i, onSuccess),
                         bind(onFailure, _2));
      }
    else {
      if (static_cast<bool>(onFailure)) {
        onFailure("Unrecognized PrefixId");
      }
    }

    // there cannot be two registered prefixes with the same id
  }

  void
  finalizeUnregisterPrefix(RegisteredPrefixTable::iterator item,
                           const UnregisterPrefixSuccessCallback& onSuccess)
  {
    m_registeredPrefixTable.erase(item);

    if (!m_pitTimeoutCheckTimerActive && m_registeredPrefixTable.empty())
      {
        m_face.m_transport->pause();
        if (!m_ioServiceWork) {
          m_processEventsTimeoutTimer->cancel();
        }
      }

    if (static_cast<bool>(onSuccess)) {
      onSuccess();
    }
  }

  /////////////////////////////////////////////////////////////////////////////////////////////////
  /////////////////////////////////////////////////////////////////////////////////////////////////

  void
  checkPitExpire()
  {
    // Check for PIT entry timeouts.
    time::steady_clock::TimePoint now = time::steady_clock::now();

    PendingInterestTable::iterator i = m_pendingInterestTable.begin();
    while (i != m_pendingInterestTable.end())
      {
        if ((*i)->isTimedOut(now))
          {
            // Save the PendingInterest and remove it from the PIT.  Then call the callback.
            shared_ptr<PendingInterest> pendingInterest = *i;

            i = m_pendingInterestTable.erase(i);

            pendingInterest->callTimeout();
          }
        else
          ++i;
      }

    if (!m_pendingInterestTable.empty()) {
      m_pitTimeoutCheckTimerActive = true;

      m_pitTimeoutCheckTimer->expires_from_now(time::milliseconds(100));
      m_pitTimeoutCheckTimer->async_wait(bind(&Impl::checkPitExpire, this));
    }
    else {
      m_pitTimeoutCheckTimerActive = false;

      if (m_registeredPrefixTable.empty()) {
        m_face.m_transport->pause();
        if (!m_ioServiceWork) {
          m_processEventsTimeoutTimer->cancel();
        }
      }
    }
  }

private:
  Face& m_face;

  PendingInterestTable m_pendingInterestTable;
  InterestFilterTable m_interestFilterTable;
  RegisteredPrefixTable m_registeredPrefixTable;

  ConfigFile m_config;

  shared_ptr<boost::asio::io_service::work> m_ioServiceWork; // if thread needs to be preserved
  shared_ptr<monotonic_deadline_timer> m_pitTimeoutCheckTimer;
  bool m_pitTimeoutCheckTimerActive;
  shared_ptr<monotonic_deadline_timer> m_processEventsTimeoutTimer;

  friend class Face;
};

} // namespace ndn

#endif // NDN_DETAIL_FACE_IMPL_HPP
