/* -*- 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 "ccnx-rit.h"

#include "ns3/log.h"
#include "ns3/simulator.h"
#include "ns3/ccnx-interest-header.h"
#include "ns3/assert.h"

#include <utility>

NS_LOG_COMPONENT_DEFINE ("CcnxRit");

namespace ns3 {

using namespace __ccnx_private_rit;

NS_OBJECT_ENSURE_REGISTERED (CcnxRit);

TypeId 
CcnxRit::GetTypeId (void)
{
  static TypeId tid = TypeId ("ns3::CcnxRit")
    .SetGroupName ("Ccnx")
    .SetParent<Object> ()
    .AddConstructor<CcnxRit> ()
    .AddAttribute ("RitTimeout",
                   "Timeout defining how long records should be kept in RIT",
                   TimeValue (Seconds (1)),
                   MakeTimeAccessor (&CcnxRit::GetRitTimeout, &CcnxRit::SetRitTimeout),
                   MakeTimeChecker ())
    .AddAttribute ("CleanupTimeout",
                   "Timeout defining how frequent RIT should be cleaned up",
                   TimeValue (Seconds (1)),
                   MakeTimeAccessor (&CcnxRit::GetCleanupTimeout, &CcnxRit::SetCleanupTimeout),
                   MakeTimeChecker ())
    ;

  return tid;
}
    
// /**
//  * \ingroup ccnx
//  * \brief Typedef for prefix hash index of RIT container
//  */
// struct CcnxRitByTimestamp
// {
//   typedef
//   CcnxRitContainer::type::index<timestamp>::type
//   type;
// };

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


CcnxRit::CcnxRit( )
{
}

CcnxRit::~CcnxRit( ) { }

void
CcnxRit::SetRitTimeout (const Time &timeout)
{
  m_ritTimeout = timeout;
}

Time
CcnxRit::GetRitTimeout () const
{
  return m_ritTimeout;
}

void
CcnxRit::SetCleanupTimeout (const Time &timeout)
{
  m_cleanupTimeout = timeout;
  if (m_cleanupEvent.IsRunning ())
    m_cleanupEvent.Cancel (); // cancel any scheduled cleanup events

  // schedule even with new timeout
  m_cleanupEvent = Simulator::Schedule (Simulator::Now () + m_cleanupTimeout,
                                        &CcnxRit::CleanExpired, this); 
}

Time
CcnxRit::GetCleanupTimeout () const
{
  return m_cleanupTimeout;
}

bool
CcnxRit::WasRecentlySatisfied (const CcnxInterestHeader &header)
{
  NS_LOG_FUNCTION_NOARGS ();
    std::pair<CcnxRitByNonce::type::iterator,CcnxRitByNonce::type::iterator>
    entries = get<nonce> ().equal_range (header.GetNonce ());
  
  if (entries.first == end ())
    return false;

  // check all entries if the name of RIT entry matches the name of interest
  for (CcnxRitByNonce::type::iterator it = entries.first; it != entries.second; it++)
    {
      // NS_LOG_DEBUG (it->m_prefix << " vs " << header.GetName () << " = " << (it->m_prefix == header.GetName ()));
      if (it->m_prefix == header.GetName ())
        return true;
    }

  return false;
}

void
CcnxRit::SetRecentlySatisfied (const CcnxInterestHeader &header)
{
  NS_LOG_FUNCTION_NOARGS ();
  NS_ASSERT_MSG (!WasRecentlySatisfied (header), "Duplicate recent interest should not be added to RIT");
  
  get<timestamp> ().push_back (
                               CcnxRitEntry(header.GetName (),
                                            header.GetNonce (),
                                            Simulator::Now ()+m_ritTimeout)
                               );
}


void CcnxRit::CleanExpired ()
{
  // NS_LOG_LOGIC ("Cleaning RIT");
  Time now = Simulator::Now ();
// #ifdef _DEBUG
//   uint32_t count = 0;
// #endif
  
  while( !empty() )
    {
      if( get<timestamp> ().front ().m_expireTime <= now ) // is the record stale?
        {
         get<timestamp> ().pop_front( );
// #ifdef _DEBUG
//          count++;
// #endif
        }
      else
        break; // nothing else to do. All later records will not be stale
    }
// #ifdef _DEBUG
//   NS_LOG_DEBUG (count << " records cleaned");
// #endif
  
  // schedule next even
  m_cleanupEvent = Simulator::Schedule (Simulator::Now () + m_cleanupTimeout,
                                        &CcnxRit::CleanExpired, this); 
}

} //namespace ns3
