/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
/*
 * Copyright (c) 2014-2022,  The University of Memphis
 *
 * This file is part of PSync.
 * See AUTHORS.md for complete list of PSync authors and contributors.
 *
 * PSync 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.
 *
 * PSync 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 a copy of the GNU Lesser General Public License along with
 * PSync, e.g., in COPYING.md file.  If not, see <http://www.gnu.org/licenses/>.
 **/

#include "PSync/segment-publisher.hpp"
#include "PSync/detail/state.hpp"

#include "tests/boost-test.hpp"
#include "tests/io-fixture.hpp"
#include "tests/key-chain-fixture.hpp"

#include <ndn-cxx/security/validator-null.hpp>
#include <ndn-cxx/util/dummy-client-face.hpp>
#include <ndn-cxx/util/segment-fetcher.hpp>

namespace psync {

using namespace ndn;

class SegmentPublisherFixture : public tests::IoFixture, public tests::KeyChainFixture
{
protected:
  SegmentPublisherFixture()
  {
    m_face.setInterestFilter(InterestFilter("/hello/world"),
                             bind(&SegmentPublisherFixture::onInterest, this, _2),
                             [] (auto&&...) { BOOST_CHECK(false); });
    advanceClocks(10_ms);

    for (int i = 0; i < 1000; ++i) {
      state.addContent(Name("/test").appendNumber(i));
    }
  }

  ~SegmentPublisherFixture() override
  {
    fetcher->stop();
  }

  void
  expressInterest(const Interest& interest)
  {
    fetcher = util::SegmentFetcher::start(m_face, interest, security::getAcceptAllValidator());
    fetcher->onComplete.connect([this] (auto&&...) { numComplete++; });
    fetcher->onError.connect([] (auto&&...) { BOOST_CHECK(false); });

    advanceClocks(10_ms);
  }

  void
  onInterest(const Interest& interest)
  {
    if (publisher.replyFromStore(interest.getName())) {
      numRepliesFromStore++;
      return;
    }

    // If dataName is same as interest name
    if (dataName.empty()) {
      publisher.publish(interest.getName(), interest.getName(), state.wireEncode(), freshness);
    }
    else {
      publisher.publish(interest.getName(), dataName, state.wireEncode(), freshness);
    }
  }

protected:
  util::DummyClientFace m_face{m_io, m_keyChain, {true, true}};
  SegmentPublisher publisher{m_face, m_keyChain};
  std::shared_ptr<util::SegmentFetcher> fetcher;
  Name dataName;
  detail::State state;

  int numComplete = 0;
  int numRepliesFromStore = 0;

  static constexpr time::milliseconds freshness = 1_s;
};

BOOST_FIXTURE_TEST_SUITE(TestSegmentPublisher, SegmentPublisherFixture)

BOOST_AUTO_TEST_CASE(Basic)
{
  BOOST_CHECK_EQUAL(publisher.m_ims.size(), 0);

  expressInterest(Interest("/hello/world"));
  BOOST_CHECK_EQUAL(numComplete, 1);
  // First segment is answered directly in publish,
  // Rest two are satisfied by the store
  BOOST_CHECK_EQUAL(numRepliesFromStore, 2);
  BOOST_CHECK_EQUAL(publisher.m_ims.size(), 3);

  for (const auto& data : publisher.m_ims) {
    BOOST_TEST_CONTEXT(data.getName()) {
      BOOST_REQUIRE_EQUAL(data.getName().size(), 4);
      BOOST_CHECK(data.getName()[-1].isSegment());
      BOOST_CHECK(data.getName()[-2].isVersion());
    }
  }

  numRepliesFromStore = 0;
  expressInterest(Interest("/hello/world"));
  BOOST_CHECK_EQUAL(numComplete, 2);
  BOOST_CHECK_EQUAL(numRepliesFromStore, 3);

  advanceClocks(freshness);
  BOOST_CHECK_EQUAL(publisher.m_ims.size(), 0);

  numRepliesFromStore = 0;
  expressInterest(Interest("/hello/world"));
  BOOST_CHECK_EQUAL(numComplete, 3);
  BOOST_CHECK_EQUAL(numRepliesFromStore, 2);

  numRepliesFromStore = 0;
  m_face.expressInterest(Interest("/hello/world").setCanBePrefix(true),
                         [this] (auto&&...) { this->numComplete++; },
                         [] (auto&&...) { BOOST_CHECK(false); },
                         [] (auto&&...) { BOOST_CHECK(false); });
  advanceClocks(10_ms);
  BOOST_CHECK_EQUAL(numComplete, 4);
  BOOST_CHECK_EQUAL(numRepliesFromStore, 1);
}

BOOST_AUTO_TEST_CASE(LongerDataName)
{
  dataName = Name("/hello/world/IBF");
  BOOST_CHECK_EQUAL(publisher.m_ims.size(), 0);

  expressInterest(Interest("/hello/world"));
  BOOST_CHECK_EQUAL(numComplete, 1);
  // First segment is answered directly in publish,
  // Rest two are satisfied by the store
  BOOST_CHECK_EQUAL(numRepliesFromStore, 2);
  BOOST_CHECK_EQUAL(publisher.m_ims.size(), 3);

  for (const auto& data : publisher.m_ims) {
    BOOST_TEST_CONTEXT(data.getName()) {
      BOOST_REQUIRE_EQUAL(data.getName().size(), 5);
      BOOST_CHECK(data.getName()[-1].isSegment());
      BOOST_CHECK(data.getName()[-2].isVersion());
    }
  }

  advanceClocks(freshness);
  BOOST_CHECK_EQUAL(publisher.m_ims.size(), 0);
}

BOOST_AUTO_TEST_SUITE_END()

} // namespace psync
