/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil -*- */
/**
 * Copyright (C) 2013 Regents of the University of California.
 * See COPYING for copyright and distribution information.
 */

#include "common.hpp"
#include "ndnd-controller.hpp"

#include "../face.hpp"
#include "../security/signature-sha256-with-rsa.hpp"
#include "../util/random.hpp"

#include "ndnd-forwarding-entry.hpp"
#include "ndnd-face-instance.hpp"
#include "ndnd-status-response.hpp"

namespace ndn {
namespace ndnd {

Controller::Controller(Face& face)
  : m_face(face)
  , m_faceId(-1)
{
}

void
Controller::selfRegisterPrefix(const Name& prefixToRegister,
                               const SuccessCallback& onSuccess,
                               const FailCallback&    onFail)
{
  if (!m_ndndId.hasValue())
    {
      if (m_filterRequests.empty())
        {
          m_face.expressInterest(Name("/%C1.M.S.localhost/%C1.M.SRV/ndnd/KEY"),
                                 bind(&Controller::onNdnidFetched, this, _1, _2),
                                 bind(onFail, "NDNDID fetching timed out"));
        }
      m_filterRequests.push_back(FilterRequest(prefixToRegister, onSuccess, onFail));
    }
  else
    startPrefixAction(ForwardingEntry("selfreg", prefixToRegister),
                      bind(&Controller::recordSelfRegisteredFaceId, this, _1, onSuccess),
                      onFail);
}


void
Controller::selfDeregisterPrefix(const Name& prefixToRegister,
                                 const SuccessCallback& onSuccess,
                                 const FailCallback&    onFail)
{
  if (!m_ndndId.hasValue() || m_faceId == -1)
    {
      if (static_cast<bool>(onFail))
        onFail("NDNID is not available (must have been present after a successful registration operation)");
      return;
    }

  startPrefixAction(ForwardingEntry("unreg", prefixToRegister, m_faceId),
                    bind(onSuccess), onFail);
}


void
Controller::onNdnidFetched(const Interest& interest, Data& data)
{
  if (data.getName().size() > interest.getName().size())
    {
      m_ndndId = data.getName()[interest.getName().size()];

      if (m_ndndId.value_size() < 6)
        {
          for (FilterRequestList::iterator i = m_filterRequests.begin();
               i != m_filterRequests.end();
               ++i)
            {
              if (static_cast<bool>(i->m_onFailure))
                i->m_onFailure("Fetched unrecognized NDNID");
            }

          return;
        }

      for (FilterRequestList::iterator i = m_filterRequests.begin();
           i != m_filterRequests.end();
           ++i)
        {
          startPrefixAction(ForwardingEntry("selfreg", i->m_prefixToRegister),
                            bind(&Controller::recordSelfRegisteredFaceId, this, _1, i->m_onSuccess),
                            i->m_onFailure);
        }
    }
  else
    {
      for (FilterRequestList::iterator i = m_filterRequests.begin();
           i != m_filterRequests.end();
           ++i)
        {
          if (static_cast<bool>(i->m_onFailure))
              i->m_onFailure("NDNID cannot be fetched");
        }
    }
  m_filterRequests.clear();
}

void
Controller::recordSelfRegisteredFaceId(const ForwardingEntry& entry,
                                       const SuccessCallback& onSuccess)
{
  m_faceId = entry.getFaceId();
  if (static_cast<bool>(onSuccess))
    onSuccess();
}

void
Controller::startFaceAction(const FaceInstance& entry,
                            const FaceOperationSucceedCallback& onSuccess,
                            const FailCallback& onFail)
{
  // Set the ForwardingEntry as the content of a Data packet and sign.
  Data data;
  data.setName(Name().appendVersion(ndn::random::generateWord32()));
  data.setContent(entry.wireEncode());

  // Create an empty signature, since nobody going to verify it for now
  // @todo In the future, we may require real signatures to do the registration
  SignatureSha256WithRsa signature;
  signature.setValue(Block(Tlv::SignatureValue));
  data.setSignature(signature);

  // Create an interest where the name has the encoded Data packet.
  Name interestName;
  interestName.append("ndnx");
  interestName.append(m_ndndId.value_begin()+6, m_ndndId.value_end());
  interestName.append(entry.getAction());
  interestName.append(data.wireEncode());

  Interest interest(interestName);
  interest.setScope(1);
  interest.setInterestLifetime(1000);
  interest.setMustBeFresh(true);

  m_face.expressInterest(interest,
                         bind(&Controller::processFaceActionResponse, this, _2, onSuccess, onFail),
                         bind(onFail, "Command Interest failed"));
}

void
Controller::startPrefixAction(const ForwardingEntry& entry,
                              const PrefixOperationSucceedCallback& onSuccess,
                              const FailCallback& onFail)
{
  // Set the ForwardingEntry as the content of a Data packet and sign.
  Data data;
  data.setName(Name().appendVersion(random::generateWord32()));
  data.setContent(entry.wireEncode());

  // Create an empty signature, since nobody going to verify it for now
  // @todo In the future, we may require real signatures to do the registration
  SignatureSha256WithRsa signature;
  signature.setValue(Block(Tlv::SignatureValue));
  data.setSignature(signature);

  // Create an interest where the name has the encoded Data packet.
  Name interestName;
  interestName.append("ndnx");
  interestName.append(m_ndndId.value_begin()+6, m_ndndId.value_end());
  interestName.append(entry.getAction());
  interestName.append(data.wireEncode());

  Interest interest(interestName);
  interest.setScope(1);
  interest.setInterestLifetime(1000);
  interest.setMustBeFresh(true);

  m_face.expressInterest(interest,
                         bind(&Controller::processPrefixActionResponse, this, _2, onSuccess, onFail),
                         bind(onFail, "Command Interest timed out"));
}

void
Controller::processFaceActionResponse(Data& data,
                                      const FaceOperationSucceedCallback& onSuccess,
                                      const FailCallback& onFail)
{
  Block content = data.getContent();
  content.parse();

  if (content.elements().empty())
    {
      if (static_cast<bool>(onFail))
        onFail("Empty response");
      return;
    }

  Block::element_const_iterator val = content.elements_begin();

  switch(val->type())
    {
    case Tlv::FaceManagement::FaceInstance:
      {
        FaceInstance entry;
        entry.wireDecode(*val);

        if (static_cast<bool>(onSuccess))
          onSuccess(entry);
        return;
      }
    case Tlv::FaceManagement::StatusResponse:
      {
        StatusResponse resp;
        resp.wireDecode(*val);

        if (static_cast<bool>(onFail))
          onFail(resp.getInfo());
        return;
      }
    default:
      {
        if (static_cast<bool>(onFail))
          onFail("Invalid response");
        return;
      }
    }
}

void
Controller::processPrefixActionResponse(Data& data,
                                        const PrefixOperationSucceedCallback& onSuccess,
                                        const FailCallback& onFail)
{
  Block content = data.getContent();
  content.parse();

  if (content.elements().empty())
    {
      if (static_cast<bool>(onFail))
        onFail("Empty response");
      return;
    }

  Block::element_const_iterator val = content.elements_begin();

  switch(val->type())
    {
    case Tlv::FaceManagement::ForwardingEntry:
      {
        ForwardingEntry entry;
        entry.wireDecode(*val);

        if (static_cast<bool>(onSuccess))
          onSuccess(entry);
        return;
      }
    case Tlv::FaceManagement::StatusResponse:
      {
        StatusResponse resp;
        resp.wireDecode(*val);

        // std::cerr << "StatusReponse: " << resp << std::endl;

        if (static_cast<bool>(onFail))
          onFail(resp.getInfo());
        return;
      }
    default:
      {
        if (static_cast<bool>(onFail))
          onFail("Invalid response");
        return;
      }
    }
}

} // namespace ndnd
} // namespace ndn
