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

#include "handles/read-handle.hpp"
#include "storage/sqlite-storage.hpp"
#include "storage/repo-storage.hpp"

#include "../repo-storage-fixture.hpp"
#include "../dataset-fixtures.hpp"

#include <boost/asio/io_service.hpp>
#include <boost/test/unit_test.hpp>

namespace repo {
namespace tests {

// All the test cases in this test suite should be run at once.
BOOST_AUTO_TEST_SUITE(TestBasicInerestRead)

const static uint8_t content[8] = {3, 1, 4, 1, 5, 9, 2, 6};

template<class Dataset>
class BasicInterestReadFixture : public RepoStorageFixture, public Dataset
{
public:
  BasicInterestReadFixture()
    : scheduler(repoFace.getIoService())
    , readHandle(repoFace, *handle, keyChain, scheduler, 0)
    , readFace(repoFace.getIoService())
  {
  }

  ~BasicInterestReadFixture()
  {
    repoFace.getIoService().stop();
  }

  void
  startListen()
  {
    readHandle.listen("/");
  }

  void
  scheduleReadEvent()
  {
    int timeCount = 1;
    for (typename Dataset::DataContainer::iterator i = this->data.begin();
         i != this->data.end(); ++i) {
      //First insert a data into database;
      (*i)->setContent(content, sizeof(content));
      (*i)->setFreshnessPeriod(ndn::time::milliseconds(36000));
      keyChain.sign(**i);
      bool rc = handle->insertData(**i);

      BOOST_CHECK_EQUAL(rc, true);
      Interest readInterest((*i)->getName());
      readInterest.setMustBeFresh(true);
      scheduler.scheduleEvent(ndn::time::milliseconds(timeCount * 50),
                              bind(&BasicInterestReadFixture<Dataset>::sendInterest, this,
                                        readInterest));
      timeCount++;
    }
  }

  void
  onReadData(const ndn::Interest& interest, const ndn::Data& data)
  {
    int rc = memcmp(data.getContent().value(), content, sizeof(content));
    BOOST_CHECK_EQUAL(rc, 0);
  }

  void
  onReadTimeout(const ndn::Interest& interest)
  {
    BOOST_ERROR("Insert not successfull or Read data does not successfull");
  }

  void
  sendInterest(const ndn::Interest& interest)
  {
    readFace.expressInterest(interest,
                             bind(&BasicInterestReadFixture::onReadData, this, _1, _2),
                             bind(&BasicInterestReadFixture::onReadTimeout, this, _1), // Nack
                             bind(&BasicInterestReadFixture::onReadTimeout, this, _1));
  }

public:
  ndn::Face repoFace;
  ndn::KeyChain keyChain;
  ndn::Scheduler scheduler;
  ReadHandle readHandle;
  ndn::Face readFace;
};


typedef boost::mpl::vector< BasicDataset,
                            FetchByPrefixDataset,
                            BasicChildSelectorDataset,
                            ExtendedChildSelectorDataset,
                            SamePrefixDataset<10> > Datasets;

BOOST_FIXTURE_TEST_CASE_TEMPLATE(Read, T, Datasets, BasicInterestReadFixture<T>)
{
  // Insert dataset
  // for (typename T::DataContainer::iterator i = this->data.begin();
  //      i != this->data.end(); ++i) {
  //   BOOST_CHECK_EQUAL(this->handle.insertData(**i), true);
  // }

  // BOOST_CHECK_EQUAL(this->handle.size(), this->data.size());

  this->startListen();
  this->scheduler.scheduleEvent(ndn::time::seconds(0),
                                bind(&BasicInterestReadFixture<T>::scheduleReadEvent, this));

  this->repoFace.processEvents(ndn::time::seconds(20));

}

BOOST_AUTO_TEST_SUITE_END()

} // namespace tests
} // namespace repo
