/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
/**
 * Copyright (c) 2014-2018, Regents of the University of California
 *
 * This file is part of NAC (Name-Based Access Control for NDN).
 * See AUTHORS.md for complete list of NAC authors and contributors.
 *
 * NAC 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.
 *
 * NAC 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
 * NAC, e.g., in COPYING.md file.  If not, see <http://www.gnu.org/licenses/>.
 *
 * @author Prashanth Swaminathan <prashanthsw@gmail.com>
 */

#include "producer-db.hpp"
#include <ndn-cxx/util/sqlite3-statement.hpp>
#include <iostream>
#include <boost/filesystem.hpp>
#include <sqlite3.h>

namespace ndn {
namespace nac {

using util::Sqlite3Statement;
using time::system_clock;

static const std::string INITIALIZATION =R"_DBTEXT_(
CREATE TABLE IF NOT EXISTS
  contentkeys(
    rowId            INTEGER PRIMARY KEY,
    timeslot         INTEGER,
    key              BLOB NOT NULL
  );
CREATE UNIQUE INDEX IF NOT EXISTS
   timeslotIndex ON contentkeys(timeslot);)_DBTEXT_";

class ProducerDB::Impl
{
public:
  Impl(const std::string& dbPath)
  {
    // open Database

    int result = sqlite3_open_v2(dbPath.c_str(),
                                 &m_database,
                                 SQLITE_OPEN_READWRITE | SQLITE_OPEN_CREATE,
                                 nullptr);

    if (result != SQLITE_OK)
      BOOST_THROW_EXCEPTION(Error("Producer DB cannot be opened/created: " + dbPath));

    // enable foreign key
    sqlite3_exec(m_database, "PRAGMA foreign_keys = ON", nullptr, nullptr, nullptr);

    // initialize database specific tables
    char* errorMessage = nullptr;
    result = sqlite3_exec(m_database, INITIALIZATION.c_str(), nullptr, nullptr, &errorMessage);
    if (result != SQLITE_OK && errorMessage != nullptr) {
      sqlite3_free(errorMessage);
      BOOST_THROW_EXCEPTION(Error("Producer DB cannot be initialized"));
    }
  }

  ~Impl()
  {
    sqlite3_close(m_database);
  }

public:
  sqlite3* m_database;
};

ProducerDB::ProducerDB(const std::string& dbPath)
  : m_impl(new Impl(dbPath))
{
}

ProducerDB::~ProducerDB() = default;

static int32_t
getFixedTimeslot(const system_clock::TimePoint& timeslot)
{
  return (time::toUnixTimestamp(timeslot)).count() / 3600000;
}

bool
ProducerDB::hasContentKey(const system_clock::TimePoint& timeslot) const
{
  int32_t fixedTimeslot = getFixedTimeslot(timeslot);
  Sqlite3Statement statement(m_impl->m_database,
                             R"_DBTEXT_(SELECT key FROM contentkeys where timeslot=?)_DBTEXT_");
  statement.bind(1, fixedTimeslot);
  return (statement.step() == SQLITE_ROW);
}


Buffer
ProducerDB::getContentKey(const system_clock::TimePoint& timeslot) const
{
  int32_t fixedTimeslot = getFixedTimeslot(timeslot);
  Sqlite3Statement statement(m_impl->m_database,
                             R"_DBTEXT_(SELECT key FROM contentkeys where timeslot=?)_DBTEXT_");
  statement.bind(1, fixedTimeslot);

  Buffer result;
  if (statement.step() == SQLITE_ROW) {
    result = Buffer(statement.getBlob(0), statement.getSize(0));
  }
  else {
    BOOST_THROW_EXCEPTION(Error("Cannot get the key from database"));
  }
  return result;
}

void
ProducerDB::addContentKey(const system_clock::TimePoint& timeslot, const Buffer& key)
{
  // BOOST_ASSERT(key.length() != 0);
  int32_t fixedTimeslot = getFixedTimeslot(timeslot);
  Sqlite3Statement statement(m_impl->m_database,
                             R"_DBTEXT_(INSERT INTO contentkeys (timeslot, key)
                             values (?, ?))_DBTEXT_");
  statement.bind(1, fixedTimeslot);
  statement.bind(2, key.data(), key.size(), SQLITE_TRANSIENT);
  if (statement.step() != SQLITE_DONE) {
    BOOST_THROW_EXCEPTION(Error("Cannot add the key to database"));
  }
}

void
ProducerDB::deleteContentKey(const system_clock::TimePoint& timeslot)
{
  int32_t fixedTimeslot = getFixedTimeslot(timeslot);
  Sqlite3Statement statement(m_impl->m_database,
                             R"_DBTEXT_(DELETE FROM contentkeys WHERE timeslot=?)_DBTEXT_");
  statement.bind(1, fixedTimeslot);
  statement.step();
}

} // namespace nac
} // namespace ndn
