/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
/**
 * Copyright (c) 2013-2016, Regents of the University of California.
 *
 * This file is part of ChronoShare, a decentralized file sharing application over NDN.
 *
 * ChronoShare 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.
 *
 * ChronoShare 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 copies of the GNU General Public License along with
 * ChronoShare, e.g., in COPYING.md file.  If not, see <http://www.gnu.org/licenses/>.
 *
 * See AUTHORS.md for complete list of ChronoShare authors and contributors.
 */

#include "db-helper.h"
#include "logging.h"

#include <boost/make_shared.hpp>
#include <boost/ref.hpp>
#include <boost/throw_exception.hpp>

INIT_LOGGER("DbHelper");

using namespace boost;
namespace fs = boost::filesystem;

const std::string INIT_DATABASE = "\
    PRAGMA foreign_keys = ON;      \
";

DbHelper::DbHelper(const fs::path& path, const std::string& dbname)
{
  fs::create_directories(path);

  int res = sqlite3_open((path / dbname).c_str(), &m_db);
  if (res != SQLITE_OK) {
    BOOST_THROW_EXCEPTION(Error::Db() << errmsg_info_str("Cannot open/create dabatabase: [" +
                                                         (path / dbname).string() + "]"));
  }

  res = sqlite3_create_function(m_db, "hash", 2, SQLITE_ANY, 0, 0, DbHelper::hash_xStep,
                                DbHelper::hash_xFinal);
  if (res != SQLITE_OK) {
    BOOST_THROW_EXCEPTION(Error::Db() << errmsg_info_str("Cannot create function ``hash''"));
  }

  res = sqlite3_create_function(m_db, "is_prefix", 2, SQLITE_ANY, 0, DbHelper::is_prefix_xFun, 0, 0);
  if (res != SQLITE_OK) {
    BOOST_THROW_EXCEPTION(Error::Db() << errmsg_info_str("Cannot create function ``is_prefix''"));
  }

  res = sqlite3_create_function(m_db, "directory_name", -1, SQLITE_ANY, 0,
                                DbHelper::directory_name_xFun, 0, 0);
  if (res != SQLITE_OK) {
    BOOST_THROW_EXCEPTION(Error::Db()
                          << errmsg_info_str("Cannot create function ``directory_name''"));
  }

  res = sqlite3_create_function(m_db, "is_dir_prefix", 2, SQLITE_ANY, 0,
                                DbHelper::is_dir_prefix_xFun, 0, 0);
  if (res != SQLITE_OK) {
    BOOST_THROW_EXCEPTION(Error::Db() << errmsg_info_str("Cannot create function ``is_dir_prefix''"));
  }

  sqlite3_exec(m_db, INIT_DATABASE.c_str(), NULL, NULL, NULL);
  _LOG_DEBUG_COND(sqlite3_errcode(m_db) != SQLITE_OK, sqlite3_errmsg(m_db));
}

DbHelper::~DbHelper()
{
  int res = sqlite3_close(m_db);
  if (res != SQLITE_OK) {
    // complain
  }
}

void
DbHelper::hash_xStep(sqlite3_context* context, int argc, sqlite3_value** argv)
{
  if (argc != 2) {
    // _LOG_ERROR ("Wrong arguments are supplied for ``hash'' function");
    sqlite3_result_error(context, "Wrong arguments are supplied for ``hash'' function", -1);
    return;
  }
  if (sqlite3_value_type(argv[0]) != SQLITE_BLOB || sqlite3_value_type(argv[1]) != SQLITE_INTEGER) {
    // _LOG_ERROR ("Hash expects (blob,integer) parameters");
    sqlite3_result_error(context, "Hash expects (blob,integer) parameters", -1);
    return;
  }

  EVP_MD_CTX** hash_context =
    reinterpret_cast<EVP_MD_CTX**>(sqlite3_aggregate_context(context, sizeof(EVP_MD_CTX*)));

  if (hash_context == 0) {
    sqlite3_result_error_nomem(context);
    return;
  }

  if (*hash_context == 0) {
    *hash_context = EVP_MD_CTX_create();
    EVP_DigestInit_ex(*hash_context, HASH_FUNCTION(), 0);
  }

  int nameBytes = sqlite3_value_bytes(argv[0]);
  const void* name = sqlite3_value_blob(argv[0]);
  sqlite3_int64 seqno = sqlite3_value_int64(argv[1]);

  EVP_DigestUpdate(*hash_context, name, nameBytes);
  EVP_DigestUpdate(*hash_context, &seqno, sizeof(sqlite3_int64));
}

void
DbHelper::hash_xFinal(sqlite3_context* context)
{
  EVP_MD_CTX** hash_context =
    reinterpret_cast<EVP_MD_CTX**>(sqlite3_aggregate_context(context, sizeof(EVP_MD_CTX*)));

  if (hash_context == 0) {
    sqlite3_result_error_nomem(context);
    return;
  }

  if (*hash_context == 0) // no rows
  {
    char charNullResult = 0;
    sqlite3_result_blob(context, &charNullResult, 1,
                        SQLITE_TRANSIENT); //SQLITE_TRANSIENT forces to make a copy
    return;
  }

  unsigned char* hash = new unsigned char[EVP_MAX_MD_SIZE];
  unsigned int hashLength = 0;

  int ok = EVP_DigestFinal_ex(*hash_context, hash, &hashLength);

  sqlite3_result_blob(context, hash, hashLength,
                      SQLITE_TRANSIENT); //SQLITE_TRANSIENT forces to make a copy
  delete[] hash;

  EVP_MD_CTX_destroy(*hash_context);
}

void
DbHelper::is_prefix_xFun(sqlite3_context* context, int argc, sqlite3_value** argv)
{
  int len1 = sqlite3_value_bytes(argv[0]);
  int len2 = sqlite3_value_bytes(argv[1]);

  if (len1 == 0) {
    sqlite3_result_int(context, 1);
    return;
  }

  if (len1 > len2) // first parameter should be at most equal in length to the second one
  {
    sqlite3_result_int(context, 0);
    return;
  }

  if (memcmp(sqlite3_value_blob(argv[0]), sqlite3_value_blob(argv[1]), len1) == 0) {
    sqlite3_result_int(context, 1);
  }
  else {
    sqlite3_result_int(context, 0);
  }
}

void
DbHelper::directory_name_xFun(sqlite3_context* context, int argc, sqlite3_value** argv)
{
  if (argc != 1) {
    sqlite3_result_error(context, "``directory_name'' expects 1 text argument", -1);
    sqlite3_result_null(context);
    return;
  }

  if (sqlite3_value_bytes(argv[0]) == 0) {
    sqlite3_result_null(context);
    return;
  }

  boost::filesystem::path filePath(
    std::string(reinterpret_cast<const char*>(sqlite3_value_text(argv[0])),
                sqlite3_value_bytes(argv[0])));
  std::string dirPath = filePath.parent_path().generic_string();
  // _LOG_DEBUG("directory_name FUN: " << dirPath);
  if (dirPath.size() == 0) {
    sqlite3_result_null(context);
  }
  else {
    sqlite3_result_text(context, dirPath.c_str(), dirPath.size(), SQLITE_TRANSIENT);
  }
}

void
DbHelper::is_dir_prefix_xFun(sqlite3_context* context, int argc, sqlite3_value** argv)
{
  int len1 = sqlite3_value_bytes(argv[0]);
  int len2 = sqlite3_value_bytes(argv[1]);

  if (len1 == 0) {
    sqlite3_result_int(context, 1);
    return;
  }

  if (len1 > len2) // first parameter should be at most equal in length to the second one
  {
    sqlite3_result_int(context, 0);
    return;
  }

  if (memcmp(sqlite3_value_blob(argv[0]), sqlite3_value_blob(argv[1]), len1) == 0) {
    if (len1 == len2) {
      sqlite3_result_int(context, 1);
    }
    else {
      if (reinterpret_cast<const char*>(sqlite3_value_blob(argv[1]))[len1] == '/') {
        sqlite3_result_int(context, 1);
      }
      else {
        sqlite3_result_int(context, 0);
      }
    }
  }
  else {
    sqlite3_result_int(context, 0);
  }
}
