/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
/**
 * Copyright (c) 2013-2017, Regents of the University of California.
 *
 * This file is part of ChronoShare, a decentralized file sharing application over NDN.
 *
 * ChronoShare 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.
 *
 * ChronoShare 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 copies of the GNU General Public License along with
 * ChronoShare, e.g., in COPYING.md file.  If not, see <http://www.gnu.org/licenses/>.
 *
 * See AUTHORS.md for complete list of ChronoShare authors and contributors.
 */
#include "fetch-manager.hpp"

#include "test-common.hpp"

#include <ndn-cxx/util/dummy-client-face.hpp>

#include <boost/lexical_cast.hpp>
#include <boost/algorithm/string/join.hpp>
#include <boost/range/adaptor/transformed.hpp>

namespace ndn {
namespace chronoshare {
namespace tests {

_LOG_INIT(Test.FetchManager);

BOOST_AUTO_TEST_SUITE(TestFetchManager)

class FetcherTestData : public IdentityManagementTimeFixture
{
public:
  FetcherTestData()
    : face(m_io, m_keyChain, {true, true})
    , m_done(false)
    , m_failed(false)
    , m_hasMissing(true)
  {
  }

  void
  onData(const ndn::Name& deviceName, const ndn::Name& basename, uint64_t seqno,
         ndn::shared_ptr<ndn::Data> data)
  {
    _LOG_TRACE("onData: " << seqno << data->getName());

    recvData.insert(seqno);
    differentNames.insert(basename);
    Name name = basename;
    name.appendSegment(seqno);
    segmentNames.insert(name);

    Block block = data->getContent();
    std::string recvNo(reinterpret_cast<const char*>(block.value()), block.value_size());
    recvContent.insert(boost::lexical_cast<uint32_t>(recvNo));
  }

  void
  finish(const ndn::Name& deviceName, const ndn::Name& baseName)
  {
  }

  void
  onComplete(Fetcher& fetcher)
  {
    m_done = true;
  }

  void
  onFail(Fetcher& fetcher)
  {
    m_failed = true;
  }

public:
  util::DummyClientFace face;
  std::set<uint32_t> recvData;
  std::set<uint32_t> recvContent;

  std::set<Name> differentNames;
  std::set<Name> segmentNames;

  bool m_done;
  bool m_failed;

  bool m_hasMissing;
};

BOOST_FIXTURE_TEST_CASE(TestFetcher, FetcherTestData)
{
  Name baseName("/fetchtest");
  Name deviceName("/device");

  // publish seqnos:  0, 1, 2, 3, 4, 5, 6, 7, 8, 9, <gap 5>, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, <gap 1>, 26
  // this will allow us to test our pipeline of 6
  std::set<uint32_t> seqs = {0, 1, 2, 3, 4, 5, 6, 7, 8, 9, /*<gap 10-14>,*/
                             15, 16, 17, 18, 19, 20, 21, 22, 23, 24, /*<gap 25>,*/ 26};

  face.onSendInterest.connect([&, this] (const Interest& interest) {

      uint32_t requestedSeqNo = interest.getName().at(-1).toNumber();
      if (seqs.count(requestedSeqNo) > 0) {

        auto data = make_shared<Data>();
        Name name(baseName);
        name.appendSegment(requestedSeqNo);

        data->setName(name);
        data->setFreshnessPeriod(time::seconds(300));
        std::string content = to_string(requestedSeqNo);
        data->setContent(reinterpret_cast<const uint8_t*>(content.data()), content.size());
        m_keyChain.sign(*data);
        m_io.post([data, this] { face.receive(*data); });
      }
    });

  Fetcher fetcher(face, true, bind(&FetcherTestData::onData, this, _1, _2, _3, _4),
                  bind(&FetcherTestData::finish, this, _1, _2),
                  bind(&FetcherTestData::onComplete, this, _1),
                  bind(&FetcherTestData::onFail, this, _1), deviceName, Name("/fetchtest"), 0, 26,
                  time::seconds(5), Name());

  BOOST_CHECK_EQUAL(fetcher.IsActive(), false);
  fetcher.RestartPipeline();
  BOOST_CHECK_EQUAL(fetcher.IsActive(), true);

  this->advanceClocks(time::milliseconds(50), 1000);
  BOOST_CHECK_EQUAL(m_failed, true);
  BOOST_CHECK_EQUAL(differentNames.size(), 1);
  BOOST_CHECK_EQUAL(segmentNames.size(), 20);
  BOOST_CHECK_EQUAL(recvData.size(), 20);
  BOOST_CHECK_EQUAL(recvContent.size(), 20);

  BOOST_CHECK_EQUAL("0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24",
                    join(recvData | boost::adaptors::transformed([] (int i) { return std::to_string(i); }), ", "));
  BOOST_CHECK_EQUAL_COLLECTIONS(recvData.begin(), recvData.end(), recvContent.begin(), recvContent.end());

  BOOST_CHECK_EQUAL(fetcher.IsActive(), false);
  fetcher.RestartPipeline();
  BOOST_CHECK_EQUAL(fetcher.IsActive(), true);

  this->advanceClocks(time::milliseconds(100), 100);
  BOOST_CHECK_EQUAL(m_done, false);
  BOOST_CHECK_EQUAL(m_failed, true);
  BOOST_CHECK_EQUAL(fetcher.IsActive(), false);

  std::set<uint32_t> missing = {10, 11, 12, 13, 14, 25};
  seqs.insert(missing.begin(), missing.end());

  m_failed = false;
  fetcher.RestartPipeline();
  BOOST_CHECK_EQUAL(fetcher.IsActive(), true);

  this->advanceClocks(time::milliseconds(100), 100);
  BOOST_CHECK_EQUAL(m_done, true);
  BOOST_CHECK_EQUAL(m_failed, false);
  BOOST_CHECK_EQUAL(segmentNames.size(), 27);
  BOOST_CHECK_EQUAL(recvData.size(), 27);
  BOOST_CHECK_EQUAL(recvContent.size(), 27);

  BOOST_CHECK_EQUAL("0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26",
                    join(recvData | boost::adaptors::transformed([] (int i) { return std::to_string(i); }), ", "));
  BOOST_CHECK_EQUAL_COLLECTIONS(recvData.begin(), recvData.end(), recvContent.begin(), recvContent.end());

  // TODO add tests that other callbacks got called
}

BOOST_AUTO_TEST_SUITE_END()

} // namespace tests
} // namespace chronoshare
} // namespace ndn
