/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
/**
 * Copyright (c) 2014-2018, Regents of the University of California
 *
 * This file is part of NAC (Name-Based Access Control for NDN).
 * See AUTHORS.md for complete list of NAC authors and contributors.
 *
 * NAC is free software: you can redistribute it and/or modify it under the terms
 * of the GNU General Public License as published by the Free Software Foundation,
 * either version 3 of the License, or (at your option) any later version.
 *
 * NAC 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
 * NAC, e.g., in COPYING.md file.  If not, see <http://www.gnu.org/licenses/>.
 *
 * @author Zhiyi Zhang <zhiyi@cs.ucla.edu>
 */

#include "group-manager.hpp"
#include "encrypted-content.hpp"
#include "algo/encryptor.hpp"

#include <iostream>
#include <map>

#include <ndn-cxx/util/string-helper.hpp>

namespace ndn {
namespace nac {

GroupManager::GroupManager(const Name& prefix,
                           const Name& dataType,
                           const std::string& dbPath,
                           const int paramLength,
                           const int freshPeriod)
  : m_namespace(prefix)
  , m_db(dbPath)
  , m_paramLength(paramLength)
  , m_freshPeriod(freshPeriod)
{
  m_namespace.append(NAME_COMPONENT_READ).append(dataType);
}

std::list<Data>
GroupManager::getGroupKey(const TimeStamp& timeslot, bool needRegenerate)
{
  std::map<Name, Buffer> memberKeys;
  std::list<Data> result;

  // get time interval
  Interval finalInterval = calculateInterval(timeslot, memberKeys);
  if (finalInterval.isValid() == false) {
    return result;
  }

  std::string startTs = boost::posix_time::to_iso_string(finalInterval.getStartTime());
  std::string endTs = boost::posix_time::to_iso_string(finalInterval.getEndTime());

  // generate the pri key and pub key
  Buffer priKeyBuf, pubKeyBuf;
  Name eKeyName(m_namespace);
  eKeyName.append(NAME_COMPONENT_E_KEY).append(startTs).append(endTs);

  if (!needRegenerate && m_db.hasEKey(eKeyName)) {
    std::tie(pubKeyBuf, priKeyBuf) = getEKey(eKeyName);
  }
  else {
    generateKeyPairs(priKeyBuf, pubKeyBuf);
    if (m_db.hasEKey(eKeyName)) {
      deleteEKey(eKeyName);
    }
    addEKey(eKeyName, pubKeyBuf, priKeyBuf);
  }

  // add the first element to the result
  // E-KEY (public key) data packet name convention:
  // /<data_type>/E-KEY/[start-ts]/[end-ts]
  Data data = createEKeyData(startTs, endTs, pubKeyBuf);
  result.push_back(data);

  // encrypt pri key with pub key from certificate
  for (const auto& entry : memberKeys) {
    const Name& keyName = entry.first;
    const Buffer& certKey = entry.second;

    // generate the name of the packet
    // D-KEY (private key) data packet name convention:
    // /<data_type>/D-KEY/[start-ts]/[end-ts]/[member-name]
    data = createDKeyData(startTs, endTs, keyName, priKeyBuf, certKey);
    result.push_back(data);
  }
  return result;
}

void
GroupManager::addSchedule(const std::string& scheduleName, const Schedule& schedule)
{
  m_db.addSchedule(scheduleName, schedule);
}

void
GroupManager::deleteSchedule(const std::string& scheduleName)
{
  m_db.deleteSchedule(scheduleName);
}

void
GroupManager::updateSchedule(const std::string& scheduleName, const Schedule& schedule)
{
  m_db.updateSchedule(scheduleName, schedule);
}

void
GroupManager::addMember(const std::string& scheduleName, const Data& memCert)
{
  security::v2::Certificate cert(memCert);
  Buffer keybits = cert.getPublicKey();
  m_db.addMember(scheduleName, cert.getKeyName(), keybits);
}

void
GroupManager::addMember(const std::string& scheduleName, const Name& keyName, const Buffer& key)
{
  m_db.addMember(scheduleName, keyName, key);
}

void
GroupManager::removeMember(const Name& identity)
{
  m_db.deleteMember(identity);
}

void
GroupManager::updateMemberSchedule(const Name& identity, const std::string& scheduleName)
{
  m_db.updateMemberSchedule(identity, scheduleName);
}

Interval
GroupManager::calculateInterval(const TimeStamp& timeslot, std::map<Name, Buffer>& memberKeys)
{
  // prepare
  Interval positiveResult;
  Interval negativeResult;
  Interval tempInterval;
  Interval finalInterval;
  bool isPositive;
  memberKeys.clear();

  // get the all intervals from schedules
  for (const std::string& scheduleName : m_db.listAllScheduleNames()) {
    const Schedule& schedule = m_db.getSchedule(scheduleName);
    std::tie(isPositive, tempInterval) = schedule.getCoveringInterval(timeslot);

    if (isPositive) {
      if (!positiveResult.isValid())
        positiveResult = tempInterval;
      positiveResult&& tempInterval;

      std::map<Name, Buffer> m = m_db.getScheduleMembers(scheduleName);
      memberKeys.insert(m.begin(), m.end());
    }
    else {
      if (!negativeResult.isValid())
        negativeResult = tempInterval;
      negativeResult&& tempInterval;
    }
  }
  if (!positiveResult.isValid()) {
    // return invalid interval when there is no member has interval covering the
    // time slot
    return Interval(false);
  }

  // get the final interval result
  if (negativeResult.isValid())
    finalInterval = positiveResult && negativeResult;
  else
    finalInterval = positiveResult;

  return finalInterval;
}

void
GroupManager::generateKeyPairs(Buffer& priKeyBuf, Buffer& pubKeyBuf) const
{
  RsaKeyParams params(m_paramLength);
  DecryptKey<algo::Rsa> privateKey = algo::Rsa::generateKey(params);
  priKeyBuf = privateKey.getKeyBits();
  EncryptKey<algo::Rsa> publicKey = algo::Rsa::deriveEncryptKey(priKeyBuf);
  pubKeyBuf = publicKey.getKeyBits();
}

Data
GroupManager::createEKeyData(const std::string& startTs,
                             const std::string& endTs,
                             const Buffer& pubKeyBuf)
{
  Name name(m_namespace);
  name.append(NAME_COMPONENT_E_KEY).append(startTs).append(endTs);
  Data data(name);
  data.setFreshnessPeriod(time::hours(m_freshPeriod));
  data.setContent(pubKeyBuf.data(), pubKeyBuf.size());
  m_keyChain.sign(data);
  return data;
}

Data
GroupManager::createDKeyData(const std::string& startTs,
                             const std::string& endTs,
                             const Name& keyName,
                             const Buffer& priKeyBuf,
                             const Buffer& certKey)
{
  Name name(m_namespace);
  name.append(NAME_COMPONENT_D_KEY);
  name.append(startTs).append(endTs);
  Data data = Data(name);
  data.setFreshnessPeriod(time::hours(m_freshPeriod));
  algo::EncryptParams eparams(tlv::AlgorithmRsaOaep);
  algo::encryptData(data,
                    priKeyBuf.data(),
                    priKeyBuf.size(),
                    keyName,
                    certKey.data(),
                    certKey.size(),
                    eparams);
  m_keyChain.sign(data);
  return data;
}

void
GroupManager::addEKey(const Name& eKeyName, const Buffer& pubKey, const Buffer& priKey)
{
  m_db.addEKey(eKeyName, pubKey, priKey);
}

std::tuple<Buffer, Buffer>
GroupManager::getEKey(const Name& eKeyName)
{
  return m_db.getEKey(eKeyName);
}

void
GroupManager::deleteEKey(const Name& eKeyName)
{
  m_db.deleteEKey(eKeyName);
}

void
GroupManager::cleanEKeys()
{
  m_db.cleanEKeys();
}

} // namespace nac
} // namespace ndn
