/* -*- 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;

  size_t manifestFileCounter = 0u;
  for (fs::recursive_directory_iterator i = directoryPtr;
       i != fs::recursive_directory_iterator();
       ++i) {
    Name manifestPrefix("/NTORRENT" +
                        directoryPathName.getSubName(directoryPathName.size() - 1).toUri());
    std::pair<std::vector<FileManifest>, std::vector<Data>> currentManifestPair =
                                                    FileManifest::generate((*i).path().string(),
                                                    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].getName());
    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
