/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
/**
 * Copyright (c) 2014-2016,  Regents of the University of California
 *
 * This file is part of ndn-group-encrypt (Group-based Encryption Protocol for NDN).
 * See AUTHORS.md for complete list of ndn-group-encrypt authors and contributors.
 *
 * ndn-group-encrypt 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.
 *
 * ndn-group-encrypt 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
 * ndn-group-encrypt, e.g., in COPYING.md file.  If not, see <http://www.gnu.org/licenses/>.
 */

#include "producer.hpp"
#include "algo/encryptor.hpp"
#include "algo/rsa.hpp"
#include "algo/aes.hpp"
#include "encrypted-content.hpp"
#include "unit-test-time-fixture.hpp"
#include "random-number-generator.hpp"

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

#include "boost-test.hpp"
#include <boost/asio.hpp>
#include <boost/filesystem.hpp>

namespace ndn {
namespace gep {
namespace tests {

static const uint8_t DATA_CONTEN[] = {
  0xcb, 0xe5, 0x6a, 0x80, 0x41, 0x24, 0x58, 0x23,
  0x84, 0x14, 0x15, 0x61, 0x80, 0xb9, 0x5e, 0xbd,
  0xce, 0x32, 0xb4, 0xbe, 0xbc, 0x91, 0x31, 0xd6,
  0x19, 0x00, 0x80, 0x8b, 0xfa, 0x00, 0x05, 0x9c
};

class ProducerFixture : public UnitTestTimeFixture
{
public:
  ProducerFixture()
    : tmpPath(boost::filesystem::path(TMP_TESTS_PATH))
    , face1(io, keyChain, {true, true})
    , face2(io, keyChain, {true, true})
    , readInterestOffset1(0)
    , readDataOffset1(0)
    , readInterestOffset2(0)
    , readDataOffset2(0)
  {
    boost::filesystem::create_directories(tmpPath);
  }

  ~ProducerFixture()
  {
    boost::filesystem::remove_all(tmpPath);
  }

  void
  createEncryptionKey(Name eKeyName, const Name& timeMarker)
  {
    RandomNumberGenerator rng;
    RsaKeyParams params;
    eKeyName.append(timeMarker);

    Buffer dKeyBuf = algo::Rsa::generateKey(rng, params).getKeyBits();
    Buffer eKeyBuf = algo::Rsa::deriveEncryptKey(dKeyBuf).getKeyBits();
    decryptionKeys[eKeyName] = dKeyBuf;

    shared_ptr<Data> keyData = make_shared<Data>(eKeyName);
    keyData->setContent(eKeyBuf.buf(), eKeyBuf.size());
    keyChain.sign(*keyData);
    encryptionKeys[eKeyName] = keyData;
  }

  bool
  passPacket()
  {
    bool hasPassed = false;

    checkFace(face1.sentInterests, readInterestOffset1, face2, hasPassed);
    checkFace(face1.sentData, readDataOffset1, face2, hasPassed);
    checkFace(face2.sentInterests, readInterestOffset2, face1, hasPassed);
    checkFace(face2.sentData, readDataOffset2, face1, hasPassed);

    return hasPassed;
  }

  template<typename Packet>
  void
  checkFace(std::vector<Packet>& receivedPackets,
            size_t& readPacketOffset,
            util::DummyClientFace& receiver,
            bool& hasPassed)
  {
    while (receivedPackets.size() > readPacketOffset) {
      receiver.receive(receivedPackets[readPacketOffset]);
      readPacketOffset++;
      hasPassed = true;
    }
  }

public:
  boost::filesystem::path tmpPath;

  util::DummyClientFace face1;
  util::DummyClientFace face2;

  size_t readInterestOffset1;
  size_t readDataOffset1;
  size_t readInterestOffset2;
  size_t readDataOffset2;

  KeyChain keyChain;

  std::unordered_map<Name, Buffer> decryptionKeys;
  std::unordered_map<Name, shared_ptr<Data>> encryptionKeys;
};

BOOST_FIXTURE_TEST_SUITE(TestProducer, ProducerFixture)

BOOST_AUTO_TEST_CASE(ContentKeyRequest)
{
  std::string dbDir = tmpPath.c_str();
  dbDir += "/test.db";

  Name prefix("/prefix");
  Name suffix("/a/b/c");
  Name expectedInterest = prefix;
  expectedInterest.append(NAME_COMPONENT_READ);
  expectedInterest.append(suffix);
  expectedInterest.append(NAME_COMPONENT_E_KEY);

  Name cKeyName = prefix;
  cKeyName.append(NAME_COMPONENT_SAMPLE);
  cKeyName.append(suffix);
  cKeyName.append(NAME_COMPONENT_C_KEY);

  Name timeMarker("20150101T100000/20150101T120000");
  time::system_clock::TimePoint testTime1 = time::fromIsoString("20150101T100001");
  time::system_clock::TimePoint testTime2 = time::fromIsoString("20150101T110001");
  name::Component testTimeRounded1("20150101T100000");
  name::Component testTimeRounded2("20150101T110000");
  name::Component testTimeComponent2("20150101T110001");

  // Create content keys required for this test case:
  for (size_t i = 0; i < suffix.size(); i++) {
    createEncryptionKey(expectedInterest, timeMarker);
    expectedInterest = expectedInterest.getPrefix(-2).append(NAME_COMPONENT_E_KEY);
  }

  face2.setInterestFilter(prefix,
        [&] (const InterestFilter&, const Interest& i) {
           Name interestName = i.getName();
           interestName.append(timeMarker);
           BOOST_REQUIRE_EQUAL(encryptionKeys.find(interestName) !=
                               encryptionKeys.end(), true);
           face2.put(*(encryptionKeys[interestName]));
           return;
        },
        RegisterPrefixSuccessCallback(),
        [] (const Name&, const std::string& e) { });

  do {
    advanceClocks(time::milliseconds(10), 20);
  } while (passPacket());

  // Verify that content key is correctly encrypted for each domain, and the
  // produce method encrypts provided data with the same content key.
  Producer producer(prefix, suffix, face1, dbDir);
  ProducerDB testDb(dbDir);
  Buffer contentKey;

  auto checkEncryptionKeys =
          [&](const std::vector<Data>& result,
              const time::system_clock::TimePoint& testTime,
              const name::Component& roundedTime) {
            BOOST_CHECK_EQUAL(testDb.hasContentKey(testTime), true);
            contentKey = testDb.getContentKey(testTime);

            algo::EncryptParams params(tlv::AlgorithmRsaOaep);
            std::vector<Data>::const_iterator it;
            for (it = result.begin(); it != result.end(); ++it) {
              Name keyName = it->getName();
              BOOST_CHECK_EQUAL(keyName.getSubName(0,6), cKeyName);
              BOOST_CHECK_EQUAL(keyName.get(6), roundedTime);
              BOOST_CHECK_EQUAL(keyName.get(7), NAME_COMPONENT_FOR);
              BOOST_CHECK_EQUAL(decryptionKeys.find(keyName.getSubName(8)) !=
                                decryptionKeys.end(), true);
              Name testName = it->getName().getSubName(-8);
              Buffer decryptionKey;

              decryptionKey = decryptionKeys.at(keyName.getSubName(8));
              BOOST_CHECK_EQUAL(decryptionKey.size() != 0, true);
              Block encryptedKeyBlock = it->getContent();
              encryptedKeyBlock.parse();

              EncryptedContent content(*(encryptedKeyBlock.elements_begin()));
              const Buffer& encryptedKey = content.getPayload();
              Buffer retrievedKey = algo::Rsa::decrypt(decryptionKey.buf(),
                                                       decryptionKey.size(),
                                                       encryptedKey.buf(),
                                                       encryptedKey.size(),
                                                       params);

              BOOST_CHECK_EQUAL_COLLECTIONS(contentKey.begin(),
                                            contentKey.end(),
                                            retrievedKey.begin(),
                                            retrievedKey.end());
            }
            BOOST_CHECK_EQUAL(result.size(), 3);
          };

  // Initial test to confirm that keys are created for this timeslot
  Name contentKeyName1 =
      producer.createContentKey(testTime1,
      std::bind(checkEncryptionKeys, _1, testTime1, testTimeRounded1));

  do {
    advanceClocks(time::milliseconds(10), 20);
  } while (passPacket());

  // Verify that we do not repeat the search for e-keys, don't advance clock
  Name contentKeyName2 =
      producer.createContentKey(testTime2,
      std::bind(checkEncryptionKeys, _1, testTime2, testTimeRounded2));

  // Confirm content key names are correct
  BOOST_CHECK_EQUAL(contentKeyName1.getPrefix(-1), cKeyName);
  BOOST_CHECK_EQUAL(contentKeyName1.get(6), testTimeRounded1);
  BOOST_CHECK_EQUAL(contentKeyName2.getPrefix(-1), cKeyName);
  BOOST_CHECK_EQUAL(contentKeyName2.get(6), testTimeRounded2);

  // Confirm produce encrypts with correct key and has right name
  Data testData;
  producer.produce(testData, testTime2, DATA_CONTEN, sizeof(DATA_CONTEN));

  Name producedName = testData.getName();
  BOOST_CHECK_EQUAL(producedName.getSubName(0,5), cKeyName.getPrefix(-1));
  BOOST_CHECK_EQUAL(producedName.get(5), testTimeComponent2);
  BOOST_CHECK_EQUAL(producedName.get(6), NAME_COMPONENT_FOR);
  BOOST_CHECK_EQUAL(producedName.getSubName(7,6), cKeyName);
  BOOST_CHECK_EQUAL(producedName.get(13), testTimeRounded2);

  Block dataBlock = testData.getContent();
  dataBlock.parse();

  EncryptedContent dataContent(*(dataBlock).elements_begin());
  const Buffer& encData = dataContent.getPayload();
  const Buffer& iv = dataContent.getInitialVector();

  algo::EncryptParams params(tlv::AlgorithmAesCbc, 16);
  params.setIV(iv.buf(), iv.size());
  Buffer decryptTest = algo::Aes::decrypt(contentKey.buf(), contentKey.size(),
                                          encData.buf(), encData.size(), params);
  BOOST_CHECK_EQUAL_COLLECTIONS(decryptTest.begin(),
                                decryptTest.end(),
                                DATA_CONTEN,
                                DATA_CONTEN + sizeof(DATA_CONTEN));
}

BOOST_AUTO_TEST_CASE(ContentKeySearch)
{
  std::string dbDir = tmpPath.c_str();
  dbDir += "/test.db";

  Name timeMarkerFirstHop("20150101T070000/20150101T080000");
  Name timeMarkerSecondHop("20150101T080000/20150101T090000");
  Name timeMarkerThirdHop("20150101T100000/20150101T110000");

  Name prefix("/prefix");
  Name suffix("/suffix");
  Name expectedInterest = prefix;
  expectedInterest.append(NAME_COMPONENT_READ);
  expectedInterest.append(suffix);
  expectedInterest.append(NAME_COMPONENT_E_KEY);

  Name cKeyName = prefix;
  cKeyName.append(NAME_COMPONENT_SAMPLE);
  cKeyName.append(suffix);
  cKeyName.append(NAME_COMPONENT_C_KEY);

  time::system_clock::TimePoint testTime = time::fromIsoString("20150101T100001");

  // Create content keys required for this test case:
  createEncryptionKey(expectedInterest, timeMarkerFirstHop);
  createEncryptionKey(expectedInterest, timeMarkerSecondHop);
  createEncryptionKey(expectedInterest, timeMarkerThirdHop);

  size_t requestCount = 0;
  face2.setInterestFilter(prefix,
        [&] (const InterestFilter&, const Interest& i) {
           BOOST_REQUIRE_EQUAL(i.getName(), expectedInterest);
           Name interestName = i.getName();
           switch(requestCount) {
             case 0:
               interestName.append(timeMarkerFirstHop);
               break;

             case 1:
               interestName.append(timeMarkerSecondHop);
               break;

             case 2:
               interestName.append(timeMarkerThirdHop);
               break;

             default:
               break;
           }
           face2.put(*(encryptionKeys[interestName]));
           requestCount++;
           return;
        },
        RegisterPrefixSuccessCallback(),
        [] (const Name&, const std::string& e) { });

  do {
    advanceClocks(time::milliseconds(10), 20);
  } while (passPacket());

  // Verify that if a key is found, but not within the right timeslot, the search
  // is refined until a valid timeslot is found.
  Producer producer(prefix, suffix, face1, dbDir);
  producer.createContentKey(testTime,
          [&](const std::vector<Data>& result){
            BOOST_CHECK_EQUAL(requestCount, 3);
            BOOST_CHECK_EQUAL(result.size(), 1);

            Data keyData = result[0];
            Name keyName = keyData.getName();
            BOOST_CHECK_EQUAL(keyName.getSubName(0,4), cKeyName);
            BOOST_CHECK_EQUAL(keyName.get(4), timeMarkerThirdHop[0]);
            BOOST_CHECK_EQUAL(keyName.get(5), NAME_COMPONENT_FOR);
            BOOST_CHECK_EQUAL(keyName.getSubName(6),
                              expectedInterest.append(timeMarkerThirdHop));
          });
  do {
    advanceClocks(time::milliseconds(10), 20);
  } while (passPacket());
}

BOOST_AUTO_TEST_CASE(ContentKeyTimeout)
{
  std::string dbDir = tmpPath.c_str();
  dbDir += "/test.db";

  Name prefix("/prefix");
  Name suffix("/suffix");
  Name expectedInterest = prefix;
  expectedInterest.append(NAME_COMPONENT_READ);
  expectedInterest.append(suffix);
  expectedInterest.append(NAME_COMPONENT_E_KEY);

  time::system_clock::TimePoint testTime = time::fromIsoString("20150101T100001");

  size_t timeoutCount = 0;
  face2.setInterestFilter(prefix,
        [&] (const InterestFilter&, const Interest& i) {
           BOOST_CHECK_EQUAL(i.getName(), expectedInterest);
           timeoutCount++;
           return;
        },
        RegisterPrefixSuccessCallback(),
        [] (const Name&, const std::string& e) { });

  do {
    advanceClocks(time::milliseconds(10), 20);
  } while (passPacket());

  // Verify that if no response is received, the producer appropriately times out.
  // The result vector should not contain elements that have timed out.
  Producer producer(prefix, suffix, face1, dbDir);
  producer.createContentKey(testTime,
          [&](const std::vector<Data>& result){
            BOOST_CHECK_EQUAL(timeoutCount, 4);
            BOOST_CHECK_EQUAL(result.size(), 0);
          });

  do {
    advanceClocks(time::milliseconds(10), 500);
  } while (passPacket());
}

BOOST_AUTO_TEST_CASE(ProducerWithLink)
{
  std::string dbDir = tmpPath.c_str();
  dbDir += "/test.db";

  Name prefix("/prefix");
  Name suffix("/suffix");
  Name expectedInterest = prefix;
  expectedInterest.append(NAME_COMPONENT_READ);
  expectedInterest.append(suffix);
  expectedInterest.append(NAME_COMPONENT_E_KEY);

  time::system_clock::TimePoint testTime = time::fromIsoString("20150101T100001");

  size_t timeoutCount = 0;
  face2.setInterestFilter(prefix,
        [&] (const InterestFilter&, const Interest& i) {
           BOOST_CHECK_EQUAL(i.getName(), expectedInterest);
           BOOST_CHECK(i.getLink().getDelegations().size() == 3);
           timeoutCount++;
           return;
        },
        RegisterPrefixSuccessCallback(),
        [] (const Name&, const std::string& e) { });

  do {
    advanceClocks(time::milliseconds(10), 20);
  } while (passPacket());

  // Verify that if no response is received, the producer appropriately times out.
  // The result vector should not contain elements that have timed out.
  Link link("test", {{10, "/test1"}, {20, "/test2"}, {100, "/test3"}});
  keyChain.sign(link);
  Producer producer(prefix, suffix, face1, dbDir, 3, link);
  producer.createContentKey(testTime,
          [&](const std::vector<Data>& result){
            BOOST_CHECK_EQUAL(timeoutCount, 4);
            BOOST_CHECK_EQUAL(result.size(), 0);
          });

  do {
    advanceClocks(time::milliseconds(10), 800);
  } while (passPacket());
}

BOOST_AUTO_TEST_SUITE_END()

} // namespace tests
} // namespace gep
} // namespace ndn
