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

#include "profile.hpp"
#include <ndn-cxx/security/additional-description.hpp>

namespace chronochat {

using std::vector;
using std::string;
using std::map;

using ndn::security::Certificate;

const std::string Profile::OID_NAME("2.5.4.41");
const std::string Profile::OID_ORG("2.5.4.11");
const std::string Profile::OID_GROUP("2.5.4.1");
const std::string Profile::OID_HOMEPAGE("2.5.4.3");
const std::string Profile::OID_ADVISOR("2.5.4.80");
const std::string Profile::OID_EMAIL("1.2.840.113549.1.9.1");

Profile::Profile(const Certificate& identityCertificate)
{
  Name keyName = identityCertificate.getKeyName();

  m_entries[string("IDENTITY")] = keyName.getPrefix(-2).toUri();

  auto additionalWire = identityCertificate.getSignatureInfo().getCustomTlv(tlv::AdditionalDescription);
  if (additionalWire) {
    ndn::security::AdditionalDescription additional(*additionalWire);

    for (auto it = additional.begin(); it != additional.end(); it++) {
      const string oidStr = it->first;
      string valueStr = it->second;
      if (oidStr == OID_NAME)
        m_entries["name"] = valueStr;
      else if (oidStr == OID_ORG)
        m_entries["institution"] = valueStr;
      else if (oidStr == OID_GROUP)
        m_entries["group"] = valueStr;
      else if (oidStr == OID_HOMEPAGE)
        m_entries["homepage"] = valueStr;
      else if (oidStr == OID_ADVISOR)
        m_entries["advisor"] = valueStr;
      else if (oidStr == OID_EMAIL)
        m_entries["email"] = valueStr;
      else
        m_entries[oidStr] = valueStr;
    }
  }
}

Profile::Profile(const Name& identityName)
{
  m_entries["IDENTITY"] = identityName.toUri();
}

Profile::Profile(const Name& identityName,
                 const string& name,
                 const string& institution)
{
  m_entries["IDENTITY"] = identityName.toUri();
  m_entries["name"] = name;
  m_entries["institution"] = institution;
}

Profile::Profile(const Profile& profile)
  : m_entries(profile.m_entries)
{
}

Profile::Profile(const Block& profileWire)
{
  this->wireDecode(profileWire);
}

template<ndn::encoding::Tag T>
size_t
Profile::wireEncode(ndn::EncodingImpl<T>& block) const
{
  size_t totalLength = 0;

  // Profile := PROFILE-TYPE TLV-LENGTH
  //             ProfileEntry+
  //
  // ProfileEntry := PROFILEENTRY-TYPE TLV-LENGTH
  //                   Oid
  //                   EntryData
  //
  // Oid := OID-TYPE TLV-LENGTH
  //            String
  //
  // EntryData := ENTRYDATA-TYPE TLV-LENGTH
  //                  String

  // Entries
  size_t entryLength = 0;
  for (map<string, string>::const_reverse_iterator it = m_entries.rbegin();
       it != m_entries.rend(); it++) {
    // Entry Data
    const uint8_t* dataWire = reinterpret_cast<const uint8_t*>(it->second.c_str());
    entryLength += block.prependByteArrayBlock(tlv::EntryData, dataWire, it->second.length());
    // Oid
    const uint8_t* oidWire = reinterpret_cast<const uint8_t*>(it->first.c_str());
    entryLength += block.prependByteArrayBlock(tlv::Oid, oidWire, it->first.length());
    entryLength += block.prependVarNumber(entryLength);
    entryLength += block.prependVarNumber(tlv::ProfileEntry);
    totalLength += entryLength;
    entryLength = 0;
  }

  // Profile
  totalLength += block.prependVarNumber(totalLength);
  totalLength += block.prependVarNumber(tlv::Profile);

  return totalLength;
}



const Block&
Profile::wireEncode() const
{
  ndn::EncodingEstimator estimator;
  size_t estimatedSize = wireEncode(estimator);

  ndn::EncodingBuffer buffer(estimatedSize, 0);
  wireEncode(buffer);

  m_wire = buffer.block();
  m_wire.parse();

  return m_wire;
}

void
Profile::wireDecode(const Block& profileWire)
{
  m_wire = profileWire;
  m_wire.parse();

  if (m_wire.type() != tlv::Profile)
    NDN_THROW(Error("Unexpected TLV number when decoding profile packet"));

  Block::element_const_iterator i = m_wire.elements_begin();
  if (i == m_wire.elements_end())
    NDN_THROW(Error("Missing Profile Entry"));
  if (i->type() != tlv::ProfileEntry)
    NDN_THROW(Error("Expect Profile Entry but get TLV Type " + std::to_string(i->type())));

  while (i != m_wire.elements_end() && i->type() == tlv::ProfileEntry) {
    Block temp = *i;
    temp.parse();
    Block::element_const_iterator j = temp.elements_begin();
    if (j == temp.elements_end())
      NDN_THROW(Error("Missing Oid"));
    if (j->type() != tlv::Oid)
      NDN_THROW(Error("Expect Oid but get TLV Type" + std::to_string(j->type())));

    string Oid = std::string(reinterpret_cast<const char* >(j->value()),
                             j->value_size());
    ++j;
    if (j == temp.elements_end())
      NDN_THROW(Error("Missing EntryData"));
    if (j->type() != tlv::EntryData)
      NDN_THROW(Error("Expect EntryData but get TLV Type " + std::to_string(j->type())));

    string EntryData = std::string(reinterpret_cast<const char* >(j->value()),
                                   j->value_size());
    ++j;
    if (j != temp.elements_end())
      NDN_THROW(Error("Unexpected element"));

    m_entries[Oid] = EntryData;
    ++i;
  }

  if (i != m_wire.elements_end())
      NDN_THROW(Error("Unexpected element"));
}

bool
Profile::operator==(const Profile& profile) const
{
  if (m_entries.size() != profile.m_entries.size())
    return false;

  for(map<string, string>::const_iterator it = m_entries.begin(); it != m_entries.end(); it++) {
    map<string, string>::const_iterator found = profile.m_entries.find(it->first);
    if (found == profile.m_entries.end())
      return false;
    if (found->second != it->second)
      return false;
  }

  return true;
}

bool
Profile::operator!=(const Profile& profile) const
{
  return !(*this == profile);
}

} // namespace chronochat
