/* -*- Mode: C++; c-file-style: "gnu"; indent-tabs-mode:nil -*- */
/*
 * Copyright (c) 2011 University of California, Los Angeles
 *
 * This program is free software; you can redistribute it and/or modify
 * it under the terms of the GNU General Public License version 2 as
 * published by the Free Software Foundation;
 *
 * This program 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 this program; if not, write to the Free Software
 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
 *
 * Author: Alexander Afanasyev <alexander.afanasyev@ucla.edu>
 */

#include "ndn-pit-entry.h"

#include "ns3/ndn-fib.h"
#include "ns3/ndn-name-components.h"
#include "ns3/ndn-interest-header.h"

#include "ns3/simulator.h"
#include "ns3/log.h"

#include <boost/lambda/lambda.hpp>
#include <boost/lambda/bind.hpp>
#include <boost/foreach.hpp>
namespace ll = boost::lambda;

NS_LOG_COMPONENT_DEFINE ("ndn.pit.Entry");

namespace ns3 {
namespace ndn {
namespace pit {

Entry::Entry (Pit &container,
              Ptr<const InterestHeader> header,
              Ptr<fib::Entry> fibEntry)
  : m_container (container)
  , m_interest (header)
  , m_fibEntry (fibEntry)
  , m_expireTime (Simulator::Now () + (!header->GetInterestLifetime ().IsZero ()?
                                       header->GetInterestLifetime ():
                                       Seconds (1.0)))
  , m_maxRetxCount (0)
{
  NS_LOG_FUNCTION (GetPrefix () << m_expireTime);
  // note that if interest lifetime is not set, the behavior is undefined
}

Entry::~Entry ()
{
  NS_LOG_FUNCTION (GetPrefix ());
}

void
Entry::UpdateLifetime (const Time &offsetTime)
{
  NS_LOG_FUNCTION (offsetTime.ToDouble (Time::S));
  
  Time newExpireTime = Simulator::Now () + offsetTime;
  if (newExpireTime > m_expireTime)
    m_expireTime = newExpireTime;
  
  NS_LOG_INFO ("Updated lifetime to " << m_expireTime.ToDouble (Time::S));
}

const NameComponents &
Entry::GetPrefix () const
{
  return m_interest->GetName ();
}

const Time &
Entry::GetExpireTime () const
{
  return m_expireTime;
}

bool
Entry::IsNonceSeen (uint32_t nonce) const
{
  return m_seenNonces.find (nonce) != m_seenNonces.end ();
}

void
Entry::AddSeenNonce (uint32_t nonce)
{
  m_seenNonces.insert (nonce);
}


Entry::in_iterator
Entry::AddIncoming (Ptr<Face> face)
{
  std::pair<in_iterator,bool> ret = 
    m_incoming.insert (IncomingFace (face));

  // NS_ASSERT_MSG (ret.second, "Something is wrong");

  return ret.first;
}

void
Entry::RemoveIncoming (Ptr<Face> face)
{
  m_incoming.erase (face);
}

void
Entry::ClearIncoming ()
{
  m_incoming.clear ();
}

Entry::out_iterator
Entry::AddOutgoing (Ptr<Face> face)
{
  std::pair<out_iterator,bool> ret =
    m_outgoing.insert (OutgoingFace (face));

  if (!ret.second)
    { // outgoing face already exists
      const_cast<OutgoingFace&>(*ret.first).UpdateOnRetransmit ();
      // m_outgoing.modify (ret.first,
      //                    ll::bind (&OutgoingFace::UpdateOnRetransmit, ll::_1));
    }

  return ret.first;
}

void
Entry::ClearOutgoing ()
{
  m_outgoing.clear ();
}

void
Entry::RemoveAllReferencesToFace (Ptr<Face> face)
{
  in_iterator incoming = m_incoming.find (face);

  if (incoming != m_incoming.end ())
    m_incoming.erase (incoming);

  out_iterator outgoing =
    m_outgoing.find (face);

  if (outgoing != m_outgoing.end ())
    m_outgoing.erase (outgoing);
}

// void
// Entry::SetWaitingInVain (Entry::out_iterator face)
// {
//   NS_LOG_DEBUG (boost::cref (*face->m_face));

//   m_outgoing.modify (face,
//                      (&ll::_1)->*&EntryOutgoingFace::m_waitingInVain = true);
// }

void
Entry::SetWaitingInVain (Ptr<Face> face)
{
  // NS_LOG_DEBUG (boost::cref (*face->m_face));

  out_iterator item = m_outgoing.find (face);
  if (item == m_outgoing.end ())
    return;

  const_cast<OutgoingFace&>(*item).m_waitingInVain = true;
  // m_outgoing.modify (item,
  //                    (&ll::_1)->*&OutgoingFace::m_waitingInVain = true);
}


bool
Entry::AreAllOutgoingInVain () const
{
  NS_LOG_DEBUG (m_outgoing.size ());

  bool inVain = true;
  std::for_each (m_outgoing.begin (), m_outgoing.end (),
                 ll::var(inVain) &= (&ll::_1)->*&OutgoingFace::m_waitingInVain);

  NS_LOG_DEBUG ("inVain " << inVain);
  return inVain;
}

bool
Entry::AreTherePromisingOutgoingFacesExcept (Ptr<Face> face) const
{
  bool inVain = true;
  std::for_each (m_outgoing.begin (), m_outgoing.end (),
                 ll::var(inVain) &=
                 ((&ll::_1)->*&OutgoingFace::m_face == face ||
                  (&ll::_1)->*&OutgoingFace::m_waitingInVain));

  return !inVain;
}

void
Entry::IncreaseAllowedRetxCount ()
{
  NS_LOG_ERROR (this);
  if (Simulator::Now () - m_lastRetransmission >= MilliSeconds (100))
    {
      // cheat:
      // don't allow retransmission faster than every 100ms
      m_maxRetxCount++;
      m_lastRetransmission = Simulator::Now ();
    }
}

Ptr<fib::Entry>
Entry::GetFibEntry ()
{
  return m_fibEntry;
};

const Entry::in_container &
Entry::GetIncoming () const
{
  return m_incoming;
}

const Entry::out_container &
Entry::GetOutgoing () const
{
  return m_outgoing;
}

uint32_t
Entry::GetMaxRetxCount () const
{
  return m_maxRetxCount;
}


std::ostream& operator<< (std::ostream& os, const Entry &entry)
{
  os << "Prefix: " << entry.GetPrefix () << "\n";
  os << "In: ";
  bool first = true;
  BOOST_FOREACH (const IncomingFace &face, entry.m_incoming)
    {
      if (!first)
        os << ",";
      else
        first = false;
      
      os << *face.m_face;
    }

  os << "\nOut: ";
  first = true;
  BOOST_FOREACH (const OutgoingFace &face, entry.m_outgoing)
    {
      if (!first)
        os << ",";
      else
        first = false;
      
      os << *face.m_face;
    }
  os << "\nNonces: ";
  first = true;
  BOOST_FOREACH (uint32_t nonce, entry.m_seenNonces)
    {
      if (!first)
        os << ",";
      else
        first = false;
      
      os << nonce;
    }

  return os;
}


} // namespace pit
} // namespace ndn
} // namespace ns3
