/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
/**
 * Copyright (c) 2014, 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/>.
 */

#ifndef NDNS_DAEMON_DB_MGR_HPP
#define NDNS_DAEMON_DB_MGR_HPP

#include "config.hpp"
#include "zone.hpp"
#include "rrset.hpp"

#include <ndn-cxx/common.hpp>
#include <sqlite3.h>

namespace ndn {
namespace ndns {

#define DEFINE_ERROR(ErrorName, Base)           \
class ErrorName : public Base                   \
{                                               \
 public:                                        \
  explicit                                      \
  ErrorName(const std::string& what)            \
    : Base(what)                                \
  {                                             \
  }                                             \
}



/**
 * @brief Database Manager, provides CRUD operations on stored entities
 *
 * @note Method names follow MongoDB convention: insert/remove/find/update
 */
class DbMgr : noncopyable
{
public:

  /**
   * @brief The Database Status
   */
  enum DbStatus {
    DB_CONNECTED,
    DB_CLOSED,
    DB_ERROR
  };

  DEFINE_ERROR(Error, std::runtime_error);
  DEFINE_ERROR(PrepareError, Error);
  DEFINE_ERROR(ExecuteError, Error);
  DEFINE_ERROR(ConnectError, Error);

public:
  explicit
  DbMgr(const std::string& dbFile = DEFAULT_DATABASE_PATH "/" "ndns.db");

  ~DbMgr();

  /**
   * @brief connect to the database. If it's already opened, do nothing.
   */
  void
  open();

  /**
   * @brief close the database connection. Do nothing if it's already closed.
   * Destructor would automatically close the database connection as well.
   */
  void
  close();

  /**
  * @brief clear all the data in the database
  */
  void
  clearAllData();

public: // Zone manipulation
  DEFINE_ERROR(ZoneError, Error);

  /**
   * @brief insert the m_zone to the database, and set the zone's id.
   * If the zone is already in the db, handle the exception without leaving it to upper level,
   * meanwhile, set the zone's id too.
   * @pre m_zone.getId() == 0
   * @post m_zone.getId() > 0
   */
  void
  insert(Zone& zone);

  /**
   * @brief lookup the zone by name, fill the m_id and m_ttl
   * @post whatever the previous id is
   * @return true if the record exist
   */
  bool
  find(Zone& zone);

  /**
   * @brief get all zones in the database
   */
  std::vector<Zone>
  listZones();

  /**
   * @brief remove the zone
   * @pre m_zone.getId() > 0
   * @post m_zone.getId() == 0
   */
  void
  remove(Zone& zone);

public: // Rrset manipulation
  DEFINE_ERROR(RrsetError, Error);

  /**
   * @brief add the rrset
   * @pre m_rrset.getId() == 0
   * @post m_rrset.getId() > 0
   */
  void
  insert(Rrset& rrset);

  /**
   * @brief get the data from db according to `m_zone`, `m_label`, `m_type`.
   *
   * If record exists, `m_ttl`, `m_version` and `m_data` is set
   *
   * @pre m_rrset.getZone().getId() > 0
   * @post whatever the previous id is,
   *       m_rrset.getId() > 0 if record exists, otherwise m_rrset.getId() == 0
   * @return true if the record exist
   */
  bool
  find(Rrset& rrset);

  /**
   * @brief get all the rrsets which is stored at given zone
   * @throw RrsetError() if zone does not exist in the database
   * @note if zone.getId() == 0, the function setId for the zone automatically
   * @note all returned rrsets' m_zone point to the memory of the param[in] zone
   */
  std::vector<Rrset>
  findRrsets(Zone& zone);

  /**
   * @brief remove the rrset
   * @pre m_rrset.getId() > 0
   * @post m_rrset.getId() == 0
   */
  void
  remove(Rrset& rrset);

  /**
   * @brief replace ttl, version, and Data with new values
   * @pre m_rrset.getId() > 0
   */
  void
  update(Rrset& rrset);

  ////////////////////////////////
  ////////getter and setter
public:
  const std::string&
  getDbFile() const
  {
    return m_dbFile;
  }

private:
  std::string m_dbFile;
  sqlite3* m_conn;
};

} // namespace ndns
} // namespace ndn

#endif // NDNS_DAEMON_DB_MGR_HPP
