/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
/*
 * Copyright (c) 2014-2020,  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 <ndn-cxx/data.hpp>
#include <ndn-cxx/interest.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:
  SegmentPublisherFixture()
    : face(m_io, util::DummyClientFace::Options{true, true})
    , publisher(face, keyChain)
  {
    face.setInterestFilter(InterestFilter("/hello/world"),
                           bind(&SegmentPublisherFixture::onInterest, this, _1, _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(face, interest, security::getAcceptAllValidator());
    fetcher->onComplete.connect([this] (auto&&...) { numComplete++; });
    fetcher->onError.connect([] (auto&&...) { BOOST_CHECK(false); });

    advanceClocks(10_ms);
  }

  void
  onInterest(const Name& prefix, 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);
    }
  }

  util::DummyClientFace face;
  KeyChain keyChain;
  SegmentPublisher publisher;
  shared_ptr<util::SegmentFetcher> fetcher;
  Name dataName;
  time::milliseconds freshness = 1_s;
  detail::State state;

  int numComplete = 0;
  int numRepliesFromStore = 0;
};

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);

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

  advanceClocks(time::milliseconds(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;
  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(LargerDataName)
{
  BOOST_CHECK_EQUAL(publisher.m_ims.size(), 0);
  dataName = Name("/hello/world/IBF");

  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);

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

BOOST_AUTO_TEST_SUITE_END()

} // namespace psync
