/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
/**
* Copyright (c) 2016 Regents of the University of California.
*
* This file is part of the nTorrent codebase.
*
* nTorrent is free software: you can redistribute it and/or modify it under the
* terms of the GNU Lesser General Public License as published by the Free Software
* Foundation, either version 3 of the License, or (at your option) any later version.
*
* nTorrent 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 Lesser General Public License for more details.
*
* You should have received copies of the GNU General Public License and GNU Lesser
* General Public License along with nTorrent, e.g., in COPYING.md file. If not, see
* <http://www.gnu.org/licenses/>.
*
* See AUTHORS for complete list of nTorrent authors and contributors.
*/

#include "torrent-file.hpp"

#include <ndn-cxx/security/key-chain.hpp>
#include <ndn-cxx/security/signing-helpers.hpp>

#include <algorithm>

#include <boost/range/adaptors.hpp>
#include <boost/filesystem.hpp>
#include <boost/filesystem/fstream.hpp>

namespace fs = boost::filesystem;

namespace ndn {

namespace ntorrent {

BOOST_CONCEPT_ASSERT((WireEncodable<TorrentFile>));
BOOST_CONCEPT_ASSERT((WireDecodable<TorrentFile>));
static_assert(std::is_base_of<Data::Error, TorrentFile::Error>::value,
                "TorrentFile::Error should inherit from Data::Error");

TorrentFile::TorrentFile(const Name& torrentFileName,
                         const Name& torrentFilePtr,
                         const Name& commonPrefix,
                         const std::vector<ndn::Name>& catalog)
  : Data(torrentFileName)
  , m_commonPrefix(commonPrefix)
  , m_torrentFilePtr(torrentFilePtr)
  , m_catalog(catalog)
{
}

TorrentFile::TorrentFile(const Name& torrentFileName,
                         const Name& commonPrefix,
                         const std::vector<ndn::Name>& catalog)
  : Data(torrentFileName)
  , m_commonPrefix(commonPrefix)
  , m_catalog(catalog)
{
}

TorrentFile::TorrentFile(const Block& block)
{
  this->wireDecode(block);
}

void
TorrentFile::createSuffixCatalog()
{
  for (auto i = m_catalog.begin() ; i != m_catalog.end(); ++i) {
    m_suffixCatalog.push_back((*i).getSubName(m_commonPrefix.size()));
  }
}

shared_ptr<Name>
TorrentFile::getTorrentFilePtr() const
{
  if (this->hasTorrentFilePtr()) {
    return make_shared<Name>(m_torrentFilePtr);
  }
  return nullptr;
}

void
TorrentFile::constructLongNames()
{
  for (auto i = m_suffixCatalog.begin(); i != m_suffixCatalog.end(); ++i) {
      Name commonPrefix = m_commonPrefix;
      m_catalog.push_back(commonPrefix.append((*i)));
  }
}

template<encoding::Tag TAG>
size_t
TorrentFile::encodeContent(EncodingImpl<TAG>& encoder) const
{
  // TorrentFileContent ::= CONTENT-TYPE TLV-LENGTH
  //                      Suffix+
  //                      CommonPrefix
  //                      TorrentFilePtr?

  // Suffix ::= NAME-TYPE TLV-LENGTH
  //          Name

  // CommonPrefix ::= NAME-TYPE TLV-LENGTH
  //                Name

  // TorrentFilePtr ::= NAME-TYPE TLV-LENGTH
  //                  Name

  size_t totalLength = 0;
  for (const auto& name : m_suffixCatalog |  boost::adaptors::reversed) {
    size_t fileManifestSuffixLength = 0;
    fileManifestSuffixLength += name.wireEncode(encoder);
    totalLength += fileManifestSuffixLength;
  }
  totalLength += m_commonPrefix.wireEncode(encoder);
  if (!m_torrentFilePtr.empty()) {
    size_t torrentFilePtrLength = 0;
    torrentFilePtrLength += m_torrentFilePtr.wireEncode(encoder);
    totalLength += torrentFilePtrLength;
  }

  totalLength += encoder.prependVarNumber(totalLength);
  totalLength += encoder.prependVarNumber(tlv::Content);
  return totalLength;
}

bool
TorrentFile::erase(const Name& name)
{
  auto found = std::find(m_catalog.begin(), m_catalog.end(), name);
  if (found != m_catalog.end()) {
    m_catalog.erase(found);
    return true;
  }
  return false;
}

void
TorrentFile::encodeContent()
{
  onChanged();

  EncodingEstimator estimator;
  size_t estimatedSize = encodeContent(estimator);

  EncodingBuffer buffer(estimatedSize, 0);
  encodeContent(buffer);

  setContentType(tlv::ContentType_Blob);
  setContent(buffer.block());
}

void
TorrentFile::decodeContent()
{
  // TorrentFileContent ::= CONTENT-TYPE TLV-LENGTH
  //                      Suffix+
  //                      CommonPrefix
  //                      TorrentFilePtr?

  // Suffix ::= NAME-TYPE TLV-LENGTH
  //          Name

  // CommonPrefix ::= NAME-TYPE TLV-LENGTH
  //                Name

  // TorrentFilePtr ::= NAME-TYPE TLV-LENGTH
  //                  Name

  if (getContentType() != tlv::ContentType_Blob) {
      BOOST_THROW_EXCEPTION(Error("Expected Content Type Blob"));
  }

  const Block& content = Data::getContent();
  content.parse();

  // Check whether there is a TorrentFilePtr
  auto element = content.elements_begin();
  if (content.elements_end() == element) {
    BOOST_THROW_EXCEPTION(Error("Torrent-file with empty content"));
  }
  element->parse();
  Name name(*element);
  if (name.empty())
    BOOST_THROW_EXCEPTION(Error("Empty name included in the torrent-file"));

  if (name.get(name.size() - 3) == name::Component("torrent-file")) {
    m_torrentFilePtr = name;
    ++element;
    m_commonPrefix = Name(*element);
    if (m_commonPrefix.empty()) {
      BOOST_THROW_EXCEPTION(Error("Common prefix cannot be empty"));
    }
  }
  else {
    m_commonPrefix = name;
  }
  element++;
  for (; element != content.elements_end(); ++element) {
    element->parse();
    Name fileManifestSuffix(*element);
    if (fileManifestSuffix.empty())
      BOOST_THROW_EXCEPTION(Error("Empty manifest file name included in the torrent-file"));
    this->insertToSuffixCatalog(fileManifestSuffix);
  }
  if (m_suffixCatalog.size() == 0) {
    BOOST_THROW_EXCEPTION(Error("Torrent-file with empty catalog of file manifest names"));
  }
}

void
TorrentFile::wireDecode(const Block& wire)
{
  m_catalog.clear();
  m_suffixCatalog.clear();
  Data::wireDecode(wire);
  this->decodeContent();
  this->constructLongNames();
}

void
TorrentFile::finalize()
{
  this->createSuffixCatalog();
  this->encodeContent();
  m_suffixCatalog.clear();
}

std::pair<std::vector<TorrentFile>,
          std::vector<std::pair<std::vector<FileManifest>,
                                std::vector<Data>>>>
TorrentFile::generate(const std::string& directoryPath,
                      size_t namesPerSegment,
                      size_t subManifestSize,
                      size_t dataPacketSize,
                      bool returnData)
{
  BOOST_ASSERT(0 < namesPerSegment);

  std::vector<TorrentFile> torrentSegments;

  fs::path path(directoryPath);
  if (!fs::exists(path)) {
    BOOST_THROW_EXCEPTION(Error(directoryPath + ": no such directory."));
  }

  Name directoryPathName(directoryPath);
  fs::recursive_directory_iterator directoryPtr(fs::system_complete(directoryPath).string());

  Name commonPrefix("/NTORRENT" +
                    directoryPathName.getSubName(directoryPathName.size() - 1).toUri());

  Name torrentName(commonPrefix.toUri() + "/torrent-file");
  TorrentFile currentTorrentFile(torrentName, commonPrefix, {});
  std::vector<std::pair<std::vector<FileManifest>, std::vector<Data>>> manifestPairs;
  // sort all the file names lexicographically
  std::set<std::string> fileNames;
  for (auto i = directoryPtr; i != fs::recursive_directory_iterator(); ++i) {
    fileNames.insert(i->path().string());
  }
  size_t manifestFileCounter = 0u;
  for (const auto& fileName : fileNames) {
    Name manifestPrefix("/NTORRENT" +
                        directoryPathName.getSubName(directoryPathName.size() - 1).toUri());
    std::pair<std::vector<FileManifest>, std::vector<Data>> currentManifestPair =
                                                    FileManifest::generate(fileName,
                                                    manifestPrefix, subManifestSize,
                                                    dataPacketSize, returnData);

    if (manifestFileCounter != 0 && 0 == manifestFileCounter % namesPerSegment) {
      torrentSegments.push_back(currentTorrentFile);
      Name currentTorrentName = torrentName;
      currentTorrentName.appendSequenceNumber(static_cast<int>(manifestFileCounter));
      currentTorrentFile = TorrentFile(currentTorrentName, commonPrefix, {});
    }
    currentTorrentFile.insert(currentManifestPair.first[0].getFullName());
    currentManifestPair.first.shrink_to_fit();
    currentManifestPair.second.shrink_to_fit();
    manifestPairs.push_back(currentManifestPair);
    ++manifestFileCounter;
  }

  // Sign and append the last torrent-file
  security::KeyChain keyChain;
  currentTorrentFile.finalize();
  keyChain.sign(currentTorrentFile, signingWithSha256());
  torrentSegments.push_back(currentTorrentFile);

  for (auto it = torrentSegments.rbegin() + 1; it != torrentSegments.rend(); ++it) {
    auto next = it - 1;
    it->setTorrentFilePtr(next->getFullName());
    it->finalize();
    keyChain.sign(*it, signingWithSha256());
  }

  torrentSegments.shrink_to_fit();
  manifestPairs.shrink_to_fit();
  return std::make_pair(torrentSegments, manifestPairs);
}

} // namespace ntorrent

} // namespace ndn
