/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil -*- */
/*
 * Copyright (c) 2013, Regents of the University of California
 *                     Yingdi Yu
 *
 * BSD license, See the LICENSE file for more information
 *
 * Author: Mengjin Yan <jane.yan0129@gmail.com>
 * Author: Yingdi Yu <yingdi@cs.ucla.edu>
 */

#include "chatroom-discovery-logic.hpp"


namespace chronos {

const size_t ChatroomDiscoveryLogic::OFFSET_CHATROOM_NAME = 4;
const size_t ChatroomDiscoveryLogic::DISCOVERY_INTEREST_NAME_SIZE = 4;
const size_t ChatroomDiscoveryLogic::REFRESHING_INTEREST_NAME_SIZE = 5;
const time::milliseconds ChatroomDiscoveryLogic::DEFAULT_REFRESHING_TIMER(10000);
const Name ChatroomDiscoveryLogic::DISCOVERY_PREFIX("/ndn/broadcast/chronochat/chatroom-list");
const time::seconds ChatroomDiscoveryLogic::m_discoveryInterval(600);

ChatroomDiscoveryLogic::ChatroomDiscoveryLogic(shared_ptr<ndn::Face> face,
                                               const UpdateCallback& updateCallback)
  : m_face(face)
  , m_scheduler(face->getIoService())
  , m_onUpdate(updateCallback)
{

  m_face->setInterestFilter(DISCOVERY_PREFIX,
                            bind(&ChatroomDiscoveryLogic::onDiscoveryInterest,
                                 this, _1, _2),
                            bind(&ChatroomDiscoveryLogic::onPrefixRegistrationFailed,
                                 this, _1));
}

void
ChatroomDiscoveryLogic::addLocalChatroom(const ChatroomInfo& chatroom)
{
  m_localChatrooms[chatroom.getName()] = chatroom;
  m_chatrooms[chatroom.getName()] = chatroom; // no need to discover local chatroom
}

void
ChatroomDiscoveryLogic::removeLocalChatroom(const Name::Component& chatroomName)
{
  m_localChatrooms.erase(chatroomName);
  m_chatrooms.erase(chatroomName);
}

void
ChatroomDiscoveryLogic::sendDiscoveryInterest()
{
  Interest discovery(DISCOVERY_PREFIX);
  discovery.setMustBeFresh(true);
  discovery.setInterestLifetime(time::milliseconds(10000));

  Exclude exclude;
  Chatrooms::iterator it;
  for (it = m_chatrooms.begin(); it != m_chatrooms.end(); ++it) {
    exclude.excludeOne(it->first);
  }
  discovery.setExclude(exclude);

  m_face->expressInterest(discovery,
                          bind(&ChatroomDiscoveryLogic::onReceiveData, this,
                               _1, _2, false),
                          bind(&ChatroomDiscoveryLogic::onDiscoveryInterestTimeout, this,
                               _1));

}

void
ChatroomDiscoveryLogic::onDiscoveryInterest(const Name& name, const Interest& interest)
{
  if (m_localChatrooms.empty())
    return;

  if (interest.getName() == DISCOVERY_PREFIX) {
    // discovery
    for (Chatrooms::const_iterator it = m_localChatrooms.begin();
         it != m_localChatrooms.end(); ++it) {

      if (!interest.getExclude().empty() &&
          interest.getExclude().isExcluded(it->first))
        continue;


      Name dataName(interest.getName());
      dataName.append(it->first);

      shared_ptr<Data> chatroomInfo = make_shared<Data>(dataName);
      chatroomInfo->setFreshnessPeriod(time::seconds(10));
      chatroomInfo->setContent(it->second.wireEncode());

      m_keyChain.sign(*chatroomInfo);
      m_face->put(*chatroomInfo);
      break;
    }
    return;
  }

  if (DISCOVERY_PREFIX.isPrefixOf(interest.getName()) &&
      interest.getName().size() == REFRESHING_INTEREST_NAME_SIZE) {
    // refreshing
    Chatrooms::const_iterator it =
      m_localChatrooms.find(interest.getName().get(OFFSET_CHATROOM_NAME));

    if (it == m_localChatrooms.end())
      return;

    shared_ptr<Data> chatroomInfo = make_shared<Data>(interest.getName());
    chatroomInfo->setFreshnessPeriod(time::seconds(10));
    chatroomInfo->setContent(it->second.wireEncode());

    m_keyChain.sign(*chatroomInfo);
    m_face->put(*chatroomInfo);

    return;
  }
}

void
ChatroomDiscoveryLogic::onPrefixRegistrationFailed(const Name& name)
{
}

void
ChatroomDiscoveryLogic::refreshChatroom(const Name::Component& chatroomName)
{
  Name name = DISCOVERY_PREFIX;
  name.append(chatroomName);

  BOOST_ASSERT(name.size() == REFRESHING_INTEREST_NAME_SIZE);

  Interest discovery(name);
  discovery.setMustBeFresh(true);
  discovery.setInterestLifetime(time::milliseconds(10000));

  m_face->expressInterest(discovery,
                          bind(&ChatroomDiscoveryLogic::onReceiveData, this,
                               _1, _2, true),
                          bind(&ChatroomDiscoveryLogic::onRefreshingInterestTimeout, this,
                               _1));

}

void
ChatroomDiscoveryLogic::onReceiveData(const ndn::Interest& interest,
                                      const ndn::Data& data,
                                      const bool isRefreshing)
{
  // Name::Component chatroomName = data.getName().get(OFFSET_CHATROOM_NAME);

  ChatroomInfo chatroom;
  chatroom.wireDecode(data.getContent().blockFromValue());
  // chatroom.setName(chatroomName);

  // Tmp Disabled
  // if (chatroom.getTrustModel() == ChatroomInfo::TRUST_MODEL_WEBOFTRUST)
  //   addContacts(chatroom);


  m_chatrooms[chatroom.getName()] = chatroom;
  m_onUpdate(chatroom, true); //add

  time::milliseconds refreshingTime;
  if (data.getFreshnessPeriod() > DEFAULT_REFRESHING_TIMER)
    refreshingTime = data.getFreshnessPeriod();
  else
    refreshingTime = DEFAULT_REFRESHING_TIMER;

  m_scheduler.scheduleEvent(refreshingTime,
                            bind(&ChatroomDiscoveryLogic::refreshChatroom, this,
                                 chatroom.getName()));

  if (!isRefreshing)
    sendDiscoveryInterest();
}

void
ChatroomDiscoveryLogic::onRefreshingInterestTimeout(const ndn::Interest& interest)
{
  Name::Component chatroomName = interest.getName().get(OFFSET_CHATROOM_NAME);

  Chatrooms::iterator it = m_chatrooms.find(chatroomName);
  if (it != m_chatrooms.end()) {
    m_onUpdate(it->second, false); //delete
    m_chatrooms.erase(it);
  }
}


void
ChatroomDiscoveryLogic::onDiscoveryInterestTimeout(const Interest& interest)
{
  m_scheduler.scheduleEvent(m_discoveryInterval,
                            bind(&ChatroomDiscoveryLogic::sendDiscoveryInterest, this));
}

void
ChatroomDiscoveryLogic::addContacts(ChatroomInfo& chatroom)
{
  // Tmp Disabled

  // std::vector<Name>::const_iterator nameIt;
  // std::vector<shared_ptr<Contact> >::iterator contactIt;
  // ContactList contactList;
  // m_contactManager->getContactList(contactList);

  // for (contactIt = contactList.begin();
  //      contactIt != contactList.end(); ++contactIt) {
  //   nameIt = std::find(chatroom.getParticipants().begin(),
  //                 chatroom.getParticipants().end(), (*contactIt)->getNameSpace());
  //   if (nameIt != chatroom.getParticipants().end())
  //     chatroom.addContact(*nameIt);
  // }
}


} // namespace chronos
