/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
/**
 * Copyright (c) 2014-2015,  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/>.
 *
 * @author Zhiyi Zhang <dreamerbarrychang@gmail.com>
 */

#include "group-manager-db.hpp"
#include "algo/rsa.hpp"

#include <sqlite3.h>
#include <boost/filesystem.hpp>
#include <ndn-cxx/util/sqlite3-statement.hpp>
#include <ndn-cxx/security/identity-certificate.hpp>

namespace ndn {
namespace gep {

using util::Sqlite3Statement;

static const std::string INITIALIZATION =
  "CREATE TABLE IF NOT EXISTS                         \n"
  "  schedules(                                       \n"
  "    schedule_id         INTEGER PRIMARY KEY,       \n"
  "    schedule_name       TEXT NOT NULL,             \n"
  "    schedule            BLOB NOT NULL              \n"
  "  );                                               \n"
  "CREATE UNIQUE INDEX IF NOT EXISTS                  \n"
  "   scheduleNameIndex ON schedules(schedule_name);  \n"
  "                                                   \n"
  "CREATE TABLE IF NOT EXISTS                         \n"
  "  members(                                         \n"
  "    member_id           INTEGER PRIMARY KEY,       \n"
  "    schedule_id         INTEGER NOT NULL,          \n"
  "    member_name         BLOB NOT NULL,             \n"
  "    key_name            BLOB NOT NULL,             \n"
  "    pubkey              BLOB NOT NULL,             \n"
  "    FOREIGN KEY(schedule_id)                       \n"
  "      REFERENCES schedules(schedule_id)            \n"
  "      ON DELETE CASCADE                            \n"
  "      ON UPDATE CASCADE                            \n"
  "  );                                               \n"
  "CREATE UNIQUE INDEX IF NOT EXISTS                  \n"
  "   memNameIndex ON members(member_name);           \n";

class GroupManagerDB::Impl
{
public:
  Impl(const std::string& dbDir)
  {
    // open Database

    int result = sqlite3_open_v2(dbDir.c_str(), &m_database,
                                 SQLITE_OPEN_READWRITE | SQLITE_OPEN_CREATE,
#ifdef NDN_CXX_DISABLE_SQLITE3_FS_LOCKING
                                 "unix-dotfile"
#else
                                 nullptr
#endif
                                 );

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

    // 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("GroupManager DB cannot be initialized"));
    }
  }

  ~Impl()
  {
    sqlite3_close(m_database);
  }

  int
  getScheduleId(const std::string& name) const
  {
    Sqlite3Statement statement(m_database,
                               "SELECT schedule_id FROM schedules WHERE schedule_name=?");
    statement.bind(1, name, SQLITE_TRANSIENT);

    int result = -1;
    if (statement.step() == SQLITE_ROW)
      result = statement.getInt(0);
    return result;
  }

public:
  sqlite3* m_database;
};

GroupManagerDB::GroupManagerDB(const std::string& dbDir)
  : m_impl(new Impl(dbDir))
{
}

GroupManagerDB::~GroupManagerDB() = default;

bool
GroupManagerDB::hasSchedule(const std::string& name) const
{
  Sqlite3Statement statement(m_impl->m_database,
                             "SELECT schedule_id FROM schedules where schedule_name=?");
  statement.bind(1, name, SQLITE_TRANSIENT);
  return (statement.step() == SQLITE_ROW);
}

std::list<std::string>
GroupManagerDB::listAllScheduleNames() const
{
  std::list<std::string> result;
  Sqlite3Statement statement(m_impl->m_database,
                             "SELECT schedule_name FROM schedules");

  result.clear();
  while (statement.step() == SQLITE_ROW) {
    result.push_back(statement.getString(0));
  }
  return result;
}

Schedule
GroupManagerDB::getSchedule(const std::string& name) const
{
  Sqlite3Statement statement(m_impl->m_database,
                             "SELECT schedule FROM schedules where schedule_name=?");
  statement.bind(1, name, SQLITE_TRANSIENT);

  Schedule result;
  if (statement.step() == SQLITE_ROW) {
    result.wireDecode(statement.getBlock(0));
  }
  else {
    BOOST_THROW_EXCEPTION(Error("Cannot get the result from database"));
  }
  return result;
}

std::map<Name, Buffer>
GroupManagerDB::getScheduleMembers(const std::string& name) const
{
  std::map<Name, Buffer> result;
  Sqlite3Statement statement(m_impl->m_database,
                             "SELECT key_name, pubkey\
                              FROM members JOIN schedules\
                              ON members.schedule_id=schedules.schedule_id\
                              WHERE schedule_name=?");
  statement.bind(1, name, SQLITE_TRANSIENT);
  result.clear();

  const uint8_t* keyBytes = nullptr;
  while (statement.step() == SQLITE_ROW) {
    keyBytes = statement.getBlob(1);
    const int& keyBytesSize = statement.getSize(1);
    result.insert(std::pair<Name, Buffer>(Name(statement.getBlock(0)),
                                          Buffer(keyBytes, keyBytesSize)));
  }
  return result;
}

void
GroupManagerDB::addSchedule(const std::string& name, const Schedule& schedule)
{
  BOOST_ASSERT(name.length() != 0);

  Sqlite3Statement statement(m_impl->m_database,
                             "INSERT INTO schedules (schedule_name, schedule)\
                              values (?, ?)");
  statement.bind(1, name, SQLITE_TRANSIENT);
  statement.bind(2, schedule.wireEncode(), SQLITE_TRANSIENT);
  if (statement.step() != SQLITE_DONE)
    BOOST_THROW_EXCEPTION(Error("Cannot add the schedule to database"));
}

void
GroupManagerDB::deleteSchedule(const std::string& name)
{
  Sqlite3Statement statement(m_impl->m_database,
                             "DELETE FROM schedules WHERE schedule_name=?");
  statement.bind(1, name, SQLITE_TRANSIENT);
  statement.step();
}

void
GroupManagerDB::renameSchedule(const std::string& oldName, const std::string& newName)
{
  BOOST_ASSERT(newName.length() != 0);

  Sqlite3Statement statement(m_impl->m_database,
                             "UPDATE schedules SET schedule_name=? WHERE schedule_name=?");
  statement.bind(1, newName, SQLITE_TRANSIENT);
  statement.bind(2, oldName, SQLITE_TRANSIENT);
  if (statement.step() != SQLITE_DONE)
    BOOST_THROW_EXCEPTION(Error("Cannot rename the schedule from database"));
}

void
GroupManagerDB::updateSchedule(const std::string& name, const Schedule& schedule)
{
  if (!hasSchedule(name)) {
    addSchedule(name, schedule);
    return;
  }

  Sqlite3Statement statement(m_impl->m_database,
                             "UPDATE schedules SET schedule=? WHERE schedule_name=?");
  statement.bind(1, schedule.wireEncode(), SQLITE_TRANSIENT);
  statement.bind(2, name, SQLITE_TRANSIENT);
  statement.step();
}

bool
GroupManagerDB::hasMember(const Name& identity) const
{
  Sqlite3Statement statement(m_impl->m_database,
                             "SELECT member_id FROM members WHERE member_name=?");
  statement.bind(1, identity.wireEncode(), SQLITE_TRANSIENT);
  return (statement.step() == SQLITE_ROW);
}

std::list<Name>
GroupManagerDB::listAllMembers() const
{
  std::list<Name> result;
  Sqlite3Statement statement(m_impl->m_database,
                             "SELECT member_name FROM members");

  result.clear();
  while (statement.step() == SQLITE_ROW) {
    result.push_back(Name(statement.getBlock(0)));
  }
  return result;
}

std::string
GroupManagerDB::getMemberSchedule(const Name& identity) const
{
  Sqlite3Statement statement(m_impl->m_database,
                             "SELECT schedule_name\
                              FROM schedules JOIN members\
                              ON schedules.schedule_id = members.schedule_id\
                              WHERE member_name=?");
  statement.bind(1, identity.wireEncode(), SQLITE_TRANSIENT);

  std::string result = "";
  if (statement.step() == SQLITE_ROW) {
    result = statement.getString(0);
  }
  else {
    BOOST_THROW_EXCEPTION(Error("Cannot get the result from database"));
  }
  return result;
}

void
GroupManagerDB::addMember(const std::string& scheduleName, const Name& keyName,
                          const Buffer& key)
{
  int scheduleId = m_impl->getScheduleId(scheduleName);
  if (scheduleId == -1)
    BOOST_THROW_EXCEPTION(Error("The schedule dose not exist"));

  // need to be changed in the future
  Name memberName = keyName.getPrefix(-1);

  Sqlite3Statement statement(m_impl->m_database,
                             "INSERT INTO members(schedule_id, member_name, key_name, pubkey)\
                              values (?, ?, ?, ?)");
  statement.bind(1, scheduleId);
  statement.bind(2, memberName.wireEncode(), SQLITE_TRANSIENT);
  statement.bind(3, keyName.wireEncode(), SQLITE_TRANSIENT);
  statement.bind(4, key.buf(), key.size(), SQLITE_TRANSIENT);

  if (statement.step() != SQLITE_DONE)
    BOOST_THROW_EXCEPTION(Error("Cannot add the member to database"));
}

void
GroupManagerDB::updateMemberSchedule(const Name& identity, const std::string& scheduleName)
{
  int scheduleId = m_impl->getScheduleId(scheduleName);
  if (scheduleId == -1)
    BOOST_THROW_EXCEPTION(Error("The schedule dose not exist"));

  Sqlite3Statement statement(m_impl->m_database,
                             "UPDATE members SET schedule_id=? WHERE member_name=?");
  statement.bind(1, scheduleId);
  statement.bind(2, identity.wireEncode(), SQLITE_TRANSIENT);
  statement.step();
}

void
GroupManagerDB::deleteMember(const Name& identity)
{
  Sqlite3Statement statement(m_impl->m_database,
                             "DELETE FROM members WHERE member_name=?");
  statement.bind(1, identity.wireEncode(), SQLITE_TRANSIENT);
  statement.step();
}

} // namespace gep
} // namespace ndn
