/* -*- Mode: C++; c-file-style: "gnu"; indent-tabs-mode:nil -*- */
/*
 * Copyright (c) 2012 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: Zhenkai Zhu <zhenkai@cs.ucla.edu>
 *         Chaoyi Bian <bcy@pku.edu.cn>
 *	   Alexander Afanasyev <alexander.afanasyev@ucla.edu>
 */

#include "sync-ccnx-wrapper.h"
#include "sync-log.h"
#include <boost/throw_exception.hpp>
#include <boost/date_time/posix_time/posix_time.hpp>
#include <boost/lambda/lambda.hpp>
#include <boost/lambda/bind.hpp>

namespace ll = boost::lambda;

#include "../evaluation/type-tag.h"

#include <ns3/ccnx-name-components.h>
#include <ns3/ccnx-interest-header.h>
#include <ns3/ccnx-content-object-header.h>
#include <ns3/ccnx-face.h>
#include <ns3/packet.h>
#include <ns3/ccnx-fib.h>

typedef boost::error_info<struct tag_errmsg, std::string> errmsg_info_str;
typedef boost::error_info<struct tag_errmsg, int> errmsg_info_int;

using namespace std;
using namespace boost;
using namespace ns3;

INIT_LOGGER ("CcnxWrapper");

namespace Sync {

CcnxWrapper::CcnxWrapper()
  : m_rand (0, std::numeric_limits<uint32_t>::max ())
{
}

CcnxWrapper::~CcnxWrapper()
{
}

void
CcnxWrapper::StartApplication ()
{
  CcnxApp::StartApplication ();
}

void
CcnxWrapper::StopApplication ()
{
  CcnxApp::StopApplication ();
}

int
CcnxWrapper::publishData (const string &dataName, const string &dataBuffer, int freshness)
{
  // NS_LOG_INFO ("Requesting Interest: \n" << interestHeader);
  _LOG_INFO ("> Data for " << dataName);

  Ptr<CcnxNameComponents> name = Create<CcnxNameComponents> ();
  istringstream is (dataName);
  is >> *name;

  static CcnxContentObjectTail trailer;
  
  CcnxContentObjectHeader data;
  data.SetName (name);
  data.SetFreshness (Seconds (freshness));

  Ptr<Packet> packet = Create<Packet> (reinterpret_cast<const uint8_t*> (dataBuffer.c_str ()), dataBuffer.size ());
  packet->AddPacketTag (CreateObject<TypeTag> (TypeTag::DATA));
  packet->AddHeader (data);
  packet->AddTrailer (trailer);

  m_protocolHandler (packet);

  m_transmittedContentObjects (&data, packet, this, m_face);

  return 0;
}

int CcnxWrapper::sendInterest (const string &strInterest, const DataCallback &dataCallback)
{
  // NS_LOG_INFO ("Requesting Interest: \n" << interestHeader);
  _LOG_INFO ("> Interest for " << strInterest);

  Ptr<CcnxNameComponents> name = Create<CcnxNameComponents> ();
  istringstream is (strInterest);
  is >> *name;
  
  CcnxInterestHeader interestHeader;
  uint32_t nonce = m_rand.GetValue ();
  _LOG_DEBUG ("Nonce: " << nonce);
  interestHeader.SetNonce            (nonce);
  interestHeader.SetName             (name);
  interestHeader.SetInterestLifetime (Seconds (9.9)); // really long-lived interests

  Ptr<Packet> packet = Create<Packet> ();
  packet->AddPacketTag (CreateObject<TypeTag> (TypeTag::INTEREST));
  packet->AddHeader (interestHeader);

  // NS_LOG_DEBUG (interestHeader);
  
  m_protocolHandler (packet);

  m_transmittedInterests (&interestHeader, this, m_face);

  // Record the callback
  CcnxFilterEntryContainer<DataCallback>::type::iterator entry = m_dataCallbacks.find (*name);
  if (entry == m_dataCallbacks.end ())
    {
      pair<CcnxFilterEntryContainer<DataCallback>::type::iterator, bool> status =
        m_dataCallbacks.insert (CcnxFilterEntry<DataCallback> (name));

      entry = status.first;
    }
  m_dataCallbacks.modify (entry, ll::bind (&CcnxFilterEntry<DataCallback>::AddCallback, ll::_1, dataCallback));
  
  return 0;
}

int CcnxWrapper::setInterestFilter (const string &prefix, const InterestCallback &interestCallback)
{
  Ptr<CcnxNameComponents> name = Create<CcnxNameComponents> ();
  istringstream is (prefix);
  is >> *name;

  CcnxFilterEntryContainer<InterestCallback>::type::iterator entry = m_interestCallbacks.find (*name);
  if (entry == m_interestCallbacks.end ())
    {
      pair<CcnxFilterEntryContainer<InterestCallback>::type::iterator, bool> status =
        m_interestCallbacks.insert (CcnxFilterEntry<InterestCallback> (name));

      entry = status.first;
    }

  m_interestCallbacks.modify (entry, ll::bind (&CcnxFilterEntry<InterestCallback>::AddCallback, ll::_1, interestCallback));

  // creating actual face
  
  Ptr<CcnxFib> fib = GetNode ()->GetObject<CcnxFib> ();
  CcnxFibEntryContainer::type::iterator fibEntry = fib->Add (*name, m_face, 0);

  // make face green, so it will be used primarily
  fib->m_fib.modify (fibEntry,
                     ll::bind (&CcnxFibEntry::UpdateStatus,
                               ll::_1, m_face, CcnxFibFaceMetric::NDN_FIB_GREEN));

  return 0;
}

void
CcnxWrapper::clearInterestFilter (const std::string &prefix)
{
  Ptr<CcnxNameComponents> name = Create<CcnxNameComponents> ();
  istringstream is (prefix);
  is >> *name;

  CcnxFilterEntryContainer<InterestCallback>::type::iterator entry = m_interestCallbacks.find (*name);
  if (entry == m_interestCallbacks.end ())
    return;

  m_interestCallbacks.modify (entry, ll::bind (&CcnxFilterEntry<InterestCallback>::ClearCallback, ll::_1));  
}

CcnxFilterEntryContainer<CcnxWrapper::InterestCallback>::type::iterator
CcnxWrapper::InterestCallbackLookup (const ns3::CcnxNameComponents &name)
{
  CcnxFilterEntryContainer<InterestCallback>::type::iterator entry = m_interestCallbacks.end ();

  // do the longest prefix match
  for (size_t componentsCount = name.GetComponents ().size ()+1;
       componentsCount > 0;
       componentsCount--)
    {
      CcnxNameComponents subPrefix (name.GetSubComponents (componentsCount-1));

      entry = m_interestCallbacks.find (subPrefix);
      if (entry != m_interestCallbacks.end())
        return entry;
    }

  return entry;
}

CcnxFilterEntryContainer<CcnxWrapper::DataCallback>::type::iterator
CcnxWrapper::DataCallbackLookup (const ns3::CcnxNameComponents &name)
{
  CcnxFilterEntryContainer<DataCallback>::type::iterator entry = m_dataCallbacks.end ();

  // do the longest prefix match
  for (size_t componentsCount = name.GetComponents ().size ()+1;
       componentsCount > 0;
       componentsCount--)
    {
      CcnxNameComponents subPrefix (name.GetSubComponents (componentsCount-1));

      entry = m_dataCallbacks.find (subPrefix);
      if (entry != m_dataCallbacks.end())
        return entry;
    }

  return entry;  
}

void
CcnxWrapper::OnInterest (const Ptr<const CcnxInterestHeader> &interest, Ptr<Packet> packet)
{
  CcnxApp::OnInterest (interest, packet);

  CcnxFilterEntryContainer<InterestCallback>::type::iterator entry = InterestCallbackLookup (interest->GetName ());
  if (entry == m_interestCallbacks.end ())
    {
      _LOG_DEBUG ("No Interest callback set");
      return;
    }
  
  entry->m_callback (lexical_cast<string> (interest->GetName ()));  
}

void
CcnxWrapper::OnContentObject (const Ptr<const CcnxContentObjectHeader> &contentObject,
                              Ptr<Packet> payload)
{
  CcnxApp::OnContentObject (contentObject, payload);

  CcnxFilterEntryContainer<DataCallback>::type::iterator entry = DataCallbackLookup (contentObject->GetName ());
  if (entry == m_dataCallbacks.end ())
    {
      _LOG_DEBUG ("No Data callback set");
      return;
    }

  ostringstream content;
  payload->CopyData (&content, payload->GetSize ());
  
  entry->m_callback (lexical_cast<string> (contentObject->GetName ()), content.str ());
  
  // i guess it make sense to remove callback when interest is satisfied
  m_dataCallbacks.erase (entry);
}


}
