/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
/*
 * Copyright (c) 2014-2020, Regents of the University of California.
 *
 * This file is part of NDNS (Named Data Networking Domain Name Service).
 * See AUTHORS.md for complete list of NDNS authors and contributors.
 *
 * NDNS 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.
 *
 * NDNS 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
 * NDNS, e.g., in COPYING.md file.  If not, see <http://www.gnu.org/licenses/>.
 */

#include "db-mgr.hpp"
#include "logger.hpp"
#include "clients/response.hpp"
#include "util/util.hpp"

namespace ndn {
namespace ndns {

NDNS_LOG_INIT(DbMgr);

static const std::string NDNS_SCHEMA = R"VALUE(
CREATE TABLE IF NOT EXISTS zones (
  id    INTEGER NOT NULL PRIMARY KEY,
  name  blob NOT NULL UNIQUE,
  ttl   integer(10) NOT NULL);

CREATE TABLE IF NOT EXISTS zone_info (
  zone_id  INTEGER NOT NULL,
  key      VARCHAR(10) NOT NULL,
  value    blob NOT NULL,
  PRIMARY KEY (zone_id, key),
  FOREIGN KEY(zone_id) REFERENCES zones(id) ON UPDATE Cascade ON DELETE Cascade);

CREATE TABLE IF NOT EXISTS rrsets (
  id      INTEGER NOT NULL PRIMARY KEY,
  zone_id integer(10) NOT NULL,
  label   blob NOT NULL,
  type    blob NOT NULL,
  version blob NOT NULL,
  ttl     integer(10) NOT NULL,
  data    blob NOT NULL,
  FOREIGN KEY(zone_id) REFERENCES zones(id) ON UPDATE Cascade ON DELETE Cascade);

CREATE UNIQUE INDEX rrsets_zone_id_label_type_version
  ON rrsets (zone_id, label, type, version);
)VALUE";

DbMgr::DbMgr(const std::string& dbFile)
  : m_dbFile(dbFile)
  , m_conn(nullptr)
{
  if (m_dbFile.empty())
    m_dbFile = getDefaultDatabaseFile();

  open();

  NDNS_LOG_INFO("open database: " << m_dbFile);
}

DbMgr::~DbMgr()
{
  close();
}

void
DbMgr::open()
{
  int res = sqlite3_open_v2(m_dbFile.data(), &m_conn,
                            SQLITE_OPEN_READWRITE | SQLITE_OPEN_CREATE,
#ifdef DISABLE_SQLITE3_FS_LOCKING
                            "unix-dotfile"
#else
                            nullptr
#endif
                            );

  if (res != SQLITE_OK) {
    NDNS_LOG_FATAL("Cannot open the db file: " << m_dbFile);
    NDN_THROW(ConnectError("Cannot open the db file: " + m_dbFile));
  }

  // ignore any errors from DB creation (command will fail for the existing database, which is ok)
  sqlite3_exec(m_conn, NDNS_SCHEMA.data(), nullptr, nullptr, nullptr);
}

void
DbMgr::close()
{
  if (m_conn == nullptr)
    return;

  int ret = sqlite3_close(m_conn);
  if (ret != SQLITE_OK) {
    NDNS_LOG_FATAL("Cannot close the db: " << m_dbFile);
  }
  else {
    m_conn = nullptr;
    NDNS_LOG_INFO("Close database: " << m_dbFile);
  }
}

void
DbMgr::clearAllData()
{
  const char* sql = "DELETE FROM zones; DELETE FROM rrsets;";

  // sqlite3_step cannot execute multiple SQL statements
  int rc = sqlite3_exec(m_conn, sql, nullptr, nullptr, nullptr);
  if (rc != SQLITE_OK) {
    NDN_THROW(ExecuteError(sql));
  }

  NDNS_LOG_INFO("clear all the data in the database: " << m_dbFile);
}

void
DbMgr::saveName(const Name& name, sqlite3_stmt* stmt, int iCol, bool isStatic)
{
  const Block& wire = name.wireEncode();
  sqlite3_bind_blob(stmt, iCol, wire.value(), wire.value_size(), isStatic ? SQLITE_STATIC : SQLITE_TRANSIENT);
}

Name
DbMgr::restoreName(sqlite3_stmt* stmt, int iCol)
{
  Name name;

  const uint8_t* buffer = static_cast<const uint8_t*>(sqlite3_column_blob(stmt, iCol));
  size_t nBytesLeft = sqlite3_column_bytes(stmt, iCol);

  while (nBytesLeft > 0) {
    bool hasDecodingSucceeded;
    name::Component component;
    std::tie(hasDecodingSucceeded, component) = Block::fromBuffer(buffer, nBytesLeft);
    if (!hasDecodingSucceeded) {
      NDN_THROW(Error("Error while decoding name from the database"));
    }
    name.append(component);
    buffer += component.size();
    nBytesLeft -= component.size();
  }

  return name;
}

///////////////////////////////////////////////////////////////////////////////////////////////////
// Zone
///////////////////////////////////////////////////////////////////////////////////////////////////

void
DbMgr::insert(Zone& zone)
{
  if (zone.getId() > 0)
    return;

  sqlite3_stmt* stmt;
  const char* sql = "INSERT INTO zones (name, ttl) VALUES (?, ?)";
  int rc = sqlite3_prepare_v2(m_conn, sql, -1, &stmt, nullptr);
  if (rc != SQLITE_OK) {
    NDN_THROW(PrepareError(sql));
  }

  saveName(zone.getName(), stmt, 1);
  sqlite3_bind_int(stmt,  2, zone.getTtl().count());

  rc = sqlite3_step(stmt);
  if (rc != SQLITE_DONE) {
    sqlite3_finalize(stmt);
    NDN_THROW(ExecuteError(sql));
  }

  zone.setId(sqlite3_last_insert_rowid(m_conn));
  sqlite3_finalize(stmt);
}

void
DbMgr::setZoneInfo(Zone& zone,
                   const std::string& key,
                   const Block& value)
{
  if (zone.getId() == 0) {
    NDN_THROW(Error("zone has not been initialized"));
  }

  if (key.length() > 10) {
    NDN_THROW(Error("key length should not exceed 10"));
  }

  sqlite3_stmt* stmt;
  const char* sql = "INSERT OR REPLACE INTO zone_info (zone_id, key, value) VALUES (?, ?, ?)";
  int rc = sqlite3_prepare_v2(m_conn, sql, -1, &stmt, nullptr);
  if (rc != SQLITE_OK) {
    NDN_THROW(PrepareError(sql));
  }

  sqlite3_bind_int(stmt,  1, zone.getId());
  sqlite3_bind_text(stmt, 2, key.data(),  key.length(), SQLITE_STATIC);
  sqlite3_bind_blob(stmt, 3, value.wire(), value.size(), SQLITE_STATIC);

  rc = sqlite3_step(stmt);
  if (rc != SQLITE_DONE) {
    sqlite3_finalize(stmt);
    NDN_THROW(ExecuteError(sql));
  }

  sqlite3_finalize(stmt);
}

std::map<std::string, Block>
DbMgr::getZoneInfo(Zone& zone)
{
  using std::string;
  std::map<string, Block> rtn;

  if (zone.getId() == 0) {
    find(zone);
  }

  if (zone.getId() == 0) {
    NDN_THROW(Error("zone has not been initialized"));
  }

  sqlite3_stmt* stmt;
  const char* sql = "SELECT key, value FROM zone_info WHERE zone_id=?";
  int rc = sqlite3_prepare_v2(m_conn, sql, -1, &stmt, nullptr);
  if (rc != SQLITE_OK) {
    NDN_THROW(PrepareError(sql));
  }

  sqlite3_bind_int(stmt, 1, zone.getId());

  while (sqlite3_step(stmt) == SQLITE_ROW) {
    const char* key = reinterpret_cast<const char*>(sqlite3_column_text(stmt, 0));
    rtn[string(key)] = Block(static_cast<const uint8_t*>(sqlite3_column_blob(stmt, 1)),
                             sqlite3_column_bytes(stmt, 1));
  }

  sqlite3_finalize(stmt);
  return rtn;
}

bool
DbMgr::find(Zone& zone)
{
  sqlite3_stmt* stmt;
  const char* sql = "SELECT id, ttl FROM zones WHERE name=?";
  int rc = sqlite3_prepare_v2(m_conn, sql, -1, &stmt, nullptr);
  if (rc != SQLITE_OK) {
    NDN_THROW(PrepareError(sql));
  }

  saveName(zone.getName(), stmt, 1);

  if (sqlite3_step(stmt) == SQLITE_ROW) {
    zone.setId(sqlite3_column_int64(stmt, 0));
    zone.setTtl(time::seconds(sqlite3_column_int(stmt, 1)));
  }
  else {
    zone.setId(0);
  }

  sqlite3_finalize(stmt);

  return zone.getId() != 0;
}

std::vector<Zone>
DbMgr::listZones()
{
  sqlite3_stmt* stmt;
  const char* sql = "SELECT id, name, ttl FROM zones";
  int rc = sqlite3_prepare_v2(m_conn, sql, -1, &stmt, nullptr);
  if (rc != SQLITE_OK) {
    NDN_THROW(PrepareError(sql));
  }

  std::vector<Zone> vec;

  while (sqlite3_step(stmt) == SQLITE_ROW) {
    vec.emplace_back();
    Zone& zone = vec.back();
    zone.setId(sqlite3_column_int64(stmt, 0));
    zone.setTtl(time::seconds(sqlite3_column_int(stmt, 2)));
    zone.setName(restoreName(stmt, 1));
  }
  sqlite3_finalize(stmt);

  return vec;
}

void
DbMgr::remove(Zone& zone)
{
  if (zone.getId() == 0)
    return;

  sqlite3_stmt* stmt;
  const char* sql = "DELETE FROM zones where id=?";
  int rc = sqlite3_prepare_v2(m_conn, sql, -1, &stmt, nullptr);
  if (rc != SQLITE_OK) {
    NDN_THROW(PrepareError(sql));
  }

  sqlite3_bind_int64(stmt, 1, zone.getId());

  rc = sqlite3_step(stmt);
  if (rc != SQLITE_DONE) {
    sqlite3_finalize(stmt);
    NDN_THROW(ExecuteError(sql));
  }

  sqlite3_finalize(stmt);

  zone = Zone();
}

///////////////////////////////////////////////////////////////////////////////////////////////////
// Rrset
///////////////////////////////////////////////////////////////////////////////////////////////////

void
DbMgr::insert(Rrset& rrset)
{
  if (rrset.getId() != 0)
    return;

  if (rrset.getZone() == nullptr) {
    NDN_THROW(RrsetError("Rrset has not been assigned to a zone"));
  }

  if (rrset.getZone()->getId() == 0) {
    insert(*rrset.getZone());
  }

  const char* sql =
    "INSERT INTO rrsets (zone_id, label, type, version, ttl, data)"
    "    VALUES (?, ?, ?, ?, ?, ?)";

  sqlite3_stmt* stmt;
  int rc = sqlite3_prepare_v2(m_conn, sql, -1, &stmt, nullptr);
  if (rc != SQLITE_OK) {
    NDN_THROW(PrepareError(sql));
  }

  sqlite3_bind_int64(stmt, 1, rrset.getZone()->getId());

  saveName(rrset.getLabel(), stmt, 2);
  sqlite3_bind_blob(stmt,  3, rrset.getType().wire(),    rrset.getType().size(),    SQLITE_STATIC);
  sqlite3_bind_blob(stmt,  4, rrset.getVersion().wire(), rrset.getVersion().size(), SQLITE_STATIC);
  sqlite3_bind_int64(stmt, 5, rrset.getTtl().count());
  sqlite3_bind_blob(stmt,  6, rrset.getData().wire(),    rrset.getData().size(),    SQLITE_STATIC);

  rc = sqlite3_step(stmt);
  if (rc != SQLITE_DONE) {
    sqlite3_finalize(stmt);
    NDN_THROW(ExecuteError(sql));
  }

  rrset.setId(sqlite3_last_insert_rowid(m_conn));
  sqlite3_finalize(stmt);
}

bool
DbMgr::find(Rrset& rrset)
{
  if (rrset.getZone() == nullptr) {
    NDN_THROW(RrsetError("Rrset has not been assigned to a zone"));
  }

  if (rrset.getZone()->getId() == 0) {
    bool isFound = find(*rrset.getZone());
    if (!isFound) {
      return false;
    }
  }

  sqlite3_stmt* stmt;
  const char* sql =
    "SELECT id, ttl, version, data FROM rrsets"
    "    WHERE zone_id=? and label=? and type=?";
  int rc = sqlite3_prepare_v2(m_conn, sql, -1, &stmt, nullptr);
  if (rc != SQLITE_OK) {
    NDN_THROW(PrepareError(sql));
  }

  sqlite3_bind_int64(stmt, 1, rrset.getZone()->getId());

  saveName(rrset.getLabel(), stmt, 2);
  sqlite3_bind_blob(stmt, 3, rrset.getType().wire(), rrset.getType().size(), SQLITE_STATIC);

  if (sqlite3_step(stmt) == SQLITE_ROW) {
    rrset.setId(sqlite3_column_int64(stmt, 0));
    rrset.setTtl(time::seconds(sqlite3_column_int64(stmt, 1)));
    rrset.setVersion(Block(static_cast<const uint8_t*>(sqlite3_column_blob(stmt, 2)),
                           sqlite3_column_bytes(stmt, 2)));
    rrset.setData(Block(static_cast<const uint8_t*>(sqlite3_column_blob(stmt, 3)),
                        sqlite3_column_bytes(stmt, 3)));
  }
  else {
    rrset.setId(0);
  }
  sqlite3_finalize(stmt);

  return rrset.getId() != 0;
}

bool
DbMgr::findLowerBound(Rrset& rrset)
{
  if (rrset.getZone() == nullptr) {
    NDN_THROW(RrsetError("Rrset has not been assigned to a zone"));
  }

  if (rrset.getZone()->getId() == 0) {
    bool isFound = find(*rrset.getZone());
    if (!isFound) {
      return false;
    }
  }

  sqlite3_stmt* stmt;
  const char* sql =
    "SELECT id, ttl, version, data FROM rrsets"
    "    WHERE zone_id=? and label<? and type=? ORDER BY label DESC";
  int rc = sqlite3_prepare_v2(m_conn, sql, -1, &stmt, nullptr);
  if (rc != SQLITE_OK) {
    NDN_THROW(PrepareError(sql));
  }

  sqlite3_bind_int64(stmt, 1, rrset.getZone()->getId());

  saveName(rrset.getLabel(), stmt, 2);
  sqlite3_bind_blob(stmt, 3, rrset.getType().wire(), rrset.getType().size(), SQLITE_STATIC);

  if (sqlite3_step(stmt) == SQLITE_ROW) {
    rrset.setId(sqlite3_column_int64(stmt, 0));
    rrset.setTtl(time::seconds(sqlite3_column_int64(stmt, 1)));
    rrset.setVersion(Block(static_cast<const uint8_t*>(sqlite3_column_blob(stmt, 2)),
                           sqlite3_column_bytes(stmt, 2)));
    rrset.setData(Block(static_cast<const uint8_t*>(sqlite3_column_blob(stmt, 3)),
                        sqlite3_column_bytes(stmt, 3)));
  }
  else {
    rrset.setId(0);
  }
  sqlite3_finalize(stmt);

  return rrset.getId() != 0;
}

std::vector<Rrset>
DbMgr::findRrsets(Zone& zone)
{
  if (zone.getId() == 0)
    find(zone);

  if (zone.getId() == 0)
    NDN_THROW(RrsetError("Attempting to find all the rrsets with a zone does not in the database"));

  std::vector<Rrset> vec;
  sqlite3_stmt* stmt;
  const char* sql = "SELECT id, ttl, version, data, label, type "
                    "FROM rrsets where zone_id=? ORDER BY label";

  int rc = sqlite3_prepare_v2(m_conn, sql, -1, &stmt, nullptr);
  if (rc != SQLITE_OK) {
    NDN_THROW(PrepareError(sql));
  }
  sqlite3_bind_int64(stmt, 1, zone.getId());

  while (sqlite3_step(stmt) == SQLITE_ROW) {
    vec.emplace_back(&zone);
    Rrset& rrset = vec.back();

    rrset.setId(sqlite3_column_int64(stmt, 0));
    rrset.setTtl(time::seconds(sqlite3_column_int64(stmt, 1)));
    rrset.setVersion(Block(static_cast<const uint8_t*>(sqlite3_column_blob(stmt, 2)),
                           sqlite3_column_bytes(stmt, 2)));
    rrset.setData(Block(static_cast<const uint8_t*>(sqlite3_column_blob(stmt, 3)),
                        sqlite3_column_bytes(stmt, 3)));
    rrset.setLabel(restoreName(stmt, 4));
    rrset.setType(Block(static_cast<const uint8_t*>(sqlite3_column_blob(stmt, 5)),
                  sqlite3_column_bytes(stmt, 5)));
  }
  sqlite3_finalize(stmt);

  return vec;
}

void
DbMgr::removeRrsetsOfZoneByType(Zone& zone, const name::Component& type)
{
  if (zone.getId() == 0)
    find(zone);

  if (zone.getId() == 0)
    NDN_THROW(RrsetError("Attempting to find all the rrsets with a zone does not in the database"));

  sqlite3_stmt* stmt;
  const char* sql = "DELETE FROM rrsets WHERE zone_id = ? AND type = ?";
  int rc = sqlite3_prepare_v2(m_conn, sql, -1, &stmt, nullptr);
  if (rc != SQLITE_OK) {
    NDN_THROW(PrepareError(sql));
  }

  sqlite3_bind_int64(stmt, 1, zone.getId());
  sqlite3_bind_blob(stmt,  2, type.wire(), type.size(), SQLITE_STATIC);

  rc = sqlite3_step(stmt);
  if (rc != SQLITE_DONE) {
    sqlite3_finalize(stmt);
    NDN_THROW(ExecuteError(sql));
  }
  sqlite3_finalize(stmt);
}

void
DbMgr::remove(Rrset& rrset)
{
  if (rrset.getId() == 0)
    NDN_THROW(RrsetError("Attempting to remove Rrset that has no assigned id"));

  sqlite3_stmt* stmt;
  const char* sql = "DELETE FROM rrsets WHERE id=?";
  int rc = sqlite3_prepare_v2(m_conn, sql, -1, &stmt, nullptr);
  if (rc != SQLITE_OK) {
    NDN_THROW(PrepareError(sql));
  }

  sqlite3_bind_int64(stmt, 1, rrset.getId());

  rc = sqlite3_step(stmt);
  if (rc != SQLITE_DONE) {
    sqlite3_finalize(stmt);
    NDN_THROW(ExecuteError(sql));
  }

  sqlite3_finalize(stmt);

  rrset = Rrset(rrset.getZone());
}

void
DbMgr::update(Rrset& rrset)
{
  if (rrset.getId() == 0) {
    NDN_THROW(RrsetError("Attempting to replace Rrset that has no assigned id"));
  }

  if (rrset.getZone() == nullptr) {
    NDN_THROW(RrsetError("Rrset has not been assigned to a zone"));
  }

  sqlite3_stmt* stmt;
  const char* sql = "UPDATE rrsets SET ttl=?, version=?, data=? WHERE id=?";
  int rc = sqlite3_prepare_v2(m_conn, sql, -1, &stmt, nullptr);
  if (rc != SQLITE_OK) {
    NDN_THROW(PrepareError(sql));
  }

  sqlite3_bind_int64(stmt, 1, rrset.getTtl().count());
  sqlite3_bind_blob(stmt,  2, rrset.getVersion().wire(), rrset.getVersion().size(), SQLITE_STATIC);
  sqlite3_bind_blob(stmt,  3, rrset.getData().wire(),    rrset.getData().size(),    SQLITE_STATIC);
  sqlite3_bind_int64(stmt, 4, rrset.getId());

  sqlite3_step(stmt);
  sqlite3_finalize(stmt);
}

} // namespace ndns
} // namespace ndn
