/* -*-  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: Ilya Moiseenko <iliamo@cs.ucla.edu>
 */

#include "ccnx-interest-sender.h"

NS_LOG_COMPONENT_DEFINE ("CcnxInterestSender");

namespace ns3
{    

NS_OBJECT_ENSURE_REGISTERED (CcnxInterestSender);

TypeId
CcnxInterestSender::GetTypeId (void)
{
    static TypeId tid = TypeId ("ns3::CcnxInterestSender")
    .SetParent<Application> ()
    .AddConstructor<CcnxInterestSender> ()
    .AddAttribute ("OffTime", "Time interval between packets",
                   TimeValue (Seconds (0.1)),
                   MakeTimeAccessor (&CcnxInterestSender::m_offTime),
                   MakeTimeChecker ())
    .AddAttribute ("Face","Local face to be used",
                   PointerValue (CreateObject<CcnxLocalFace> ()),
                   MakePointerAccessor (&CcnxInterestSender::m_face),
                   MakePointerChecker<CcnxLocalFace> ())
    /*.AddAttribute ("NameComponents","CcnxName of the Interest (use CcnxNameComponents)",
                   CcnxNameComponentsValue(CcnxNameComponents()),
                   MakeCcnxNameComponentsAccessor(&CcnxInterestSender::m_interestName),
                   MakeCcnxNameComponentsChecker())*/
    .AddAttribute ("InterestName","CcnxName of the Interest (use CcnxNameComponents)",
                   PointerValue (CreateObject<CcnxNameComponents> ()),
                   MakePointerAccessor (&CcnxInterestSender::m_interestName),
                   MakePointerChecker<CcnxNameComponents> ())
    .AddAttribute ("LifeTime", "LifeTime fo interest packet",
                   TimeValue (Seconds (4.0)),
                   MakeTimeAccessor (&CcnxInterestSender::m_interestLifeTime),
                   MakeTimeChecker ())
    .AddAttribute ("MinSuffixComponents", "MinSuffixComponents",
                   IntegerValue(-1),
                   MakeIntegerAccessor(&CcnxInterestSender::m_minSuffixComponents),
                   MakeIntegerChecker<int32_t>())
    .AddAttribute ("MaxSuffixComponents", "MaxSuffixComponents",
                   IntegerValue(-1),
                   MakeIntegerAccessor(&CcnxInterestSender::m_maxSuffixComponents),
                   MakeIntegerChecker<int32_t>())
    .AddAttribute ("ChildSelector", "ChildSelector",
                   BooleanValue(false),
                   MakeBooleanAccessor(&CcnxInterestSender::m_childSelector),
                   MakeBooleanChecker())
    /*.AddAttribute ("Exclude","only simple name matching is supported (use CcnxNameComponents)",
                   CcnxNameComponentsValue(CcnxNameComponents()),
                   MakeCcnxNameComponentsAccessor(&CcnxInterestSender::m_exclude),
                   MakeCcnxNameComponentsChecker())*/
    .AddAttribute ("Exclude", "only simple name matching is supported (use CcnxNameComponents)",
                   PointerValue (CreateObject<CcnxNameComponents> ()),
                   MakePointerAccessor (&CcnxInterestSender::m_exclude),
                   MakePointerChecker<CcnxNameComponents> ())
    .AddAttribute ("Initial Nonce", "If 0 then nonce is not used",
                   UintegerValue(1),
                   MakeUintegerAccessor(&CcnxInterestSender::m_initialNonce),
                   MakeUintegerChecker<uint32_t>())
    ;
    /*
    .AddAttribute ("NoiseModel",
                   "A pointer to the model of the channel ambient noise.",
                   PointerValue (CreateObject<UanNoiseModelDefault> ()),
                   MakePointerAccessor (&UanChannel::m_noise),
                   MakePointerChecker<UanNoiseModel> ())*/
    return tid;
}
    
CcnxInterestSender::CcnxInterestSender ()
{
    NS_LOG_FUNCTION_NOARGS ();
}
    
CcnxInterestSender::~CcnxInterestSender()
{
    NS_LOG_FUNCTION_NOARGS ();
}
    
void
CcnxInterestSender::DoDispose (void)
{
    NS_LOG_FUNCTION_NOARGS ();
        
    Application::DoDispose ();
}
    
// Application Methods
void 
CcnxInterestSender::StartApplication () // Called at time specified by Start
{
    NS_LOG_FUNCTION_NOARGS ();
    ScheduleNextTx();
}
    
void 
CcnxInterestSender::StopApplication () // Called at time specified by Stop
{
    NS_LOG_FUNCTION_NOARGS ();
    
    CancelEvents ();
}
    
void 
CcnxInterestSender::CancelEvents ()
{
    NS_LOG_FUNCTION_NOARGS ();
        
    Simulator::Cancel (m_sendEvent);
}

void 
CcnxInterestSender::ScheduleNextTx ()
{
    NS_LOG_FUNCTION_NOARGS ();
        
    Time nextTime = Seconds(m_offTime);
    m_sendEvent = Simulator::Schedule (nextTime, &CcnxInterestSender::SendPacket, this);
}
    
void
CcnxInterestSender::SendPacket ()
{
    NS_LOG_FUNCTION_NOARGS ();
    NS_LOG_INFO ("Sending Interest at " << Simulator::Now ());
    
    uint32_t randomNonce = UniformVariable().GetInteger(1, std::numeric_limits<uint32_t>::max ());
    CcnxInterestHeader interestHeader;
    interestHeader.SetNonce(randomNonce);
    //const Ptr<CcnxNameComponents> name = Create<CcnxNameComponents>(m_interestName);
    interestHeader.SetName(m_interestName);
    interestHeader.SetInterestLifetime(m_interestLifeTime);
    interestHeader.SetChildSelector(m_childSelector);
    //const Ptr<CcnxNameComponents> exclude = Create<CcnxNameComponents>(m_exclude);
    interestHeader.SetExclude(m_exclude);
    interestHeader.SetMaxSuffixComponents(m_maxSuffixComponents);
    interestHeader.SetMinSuffixComponents(m_minSuffixComponents);
    
    Ptr<Packet> packet = Create<Packet> ();
    packet->AddHeader (interestHeader);
    
    m_face->Send(packet);
    
    ScheduleNextTx();
}

    
}
