/*
 * Licensed to the Apache Software Foundation (ASF) under one or more
 * contributor license agreements.  See the NOTICE file distributed with
 * this work for additional information regarding copyright ownership.
 * The ASF licenses this file to You under the Apache License, Version 2.0
 * (the "License"); you may not use this file except in compliance with
 * the License.  You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

#include <geode/Region.hpp>
#include <geode/Cache.hpp>

#include "SqLiteImpl.hpp"
#include "sqliteimpl_export.h"

#ifdef _WIN32
#include <Windows.h>
#endif

namespace {
std::string g_default_persistence_directory = "GeodeRegionData";
}  // namespace

namespace apache {
namespace geode {
namespace client {

void SqLiteImpl::init(const std::shared_ptr<Region> &region,
                      const std::shared_ptr<Properties> &diskProperties) {
  // Set the default values

  int maxPageCount = 0;
  int pageSize = 0;
  m_regionPtr = region;
  m_persistanceDir = g_default_persistence_directory;
  std::string regionName = region->getName();
  if (diskProperties != nullptr) {
    auto maxPageCountPtr = diskProperties->find(MAX_PAGE_COUNT);
    auto pageSizePtr = diskProperties->find(PAGE_SIZE);
    auto persDir = diskProperties->find(PERSISTENCE_DIR);

    if (maxPageCountPtr != nullptr) {
      maxPageCount = atoi(maxPageCountPtr->value().c_str());
    }

    if (pageSizePtr != nullptr) pageSize = atoi(pageSizePtr->value().c_str());

    if (persDir != nullptr) m_persistanceDir = persDir->value().c_str();
  }

#ifndef _WIN32
  char currWDPath[512];
  ::getcwd(currWDPath, 512);

  if (m_persistanceDir.at(0) != '/') {
    if (0 == ::strlen(currWDPath)) {
      throw InitFailedException(
          "Failed to get absolute path for persistence directory.");
    }
    m_persistanceDir = std::string(currWDPath) + "/" + m_persistanceDir;
  }

  // Create persistence directory
  ::mkdir(m_persistanceDir.c_str(), S_IRWXU | S_IRWXG | S_IROTH | S_IXOTH);

  // Create region directory
  std::string regionDirectory = m_persistanceDir + "/" + regionName;
  ::mkdir(regionDirectory.c_str(), S_IRWXU | S_IRWXG | S_IROTH | S_IXOTH);
  m_regionDBFile = regionDirectory + "/" + regionName + ".db";

#else
  char currWDPath[512];
  GetCurrentDirectory(512, currWDPath);

  if (m_persistanceDir.find(":", 0) == std::string::npos) {
    if (currWDPath == NULL)
      throw InitFailedException(
          "Failed to get absolute path for persistence directory.");
    m_persistanceDir = std::string(currWDPath) + "/" + m_persistanceDir;
  }

  // Create persistence directory
  CreateDirectory(m_persistanceDir.c_str(), NULL);

  // Create region directory
  std::string regionDirectory = m_persistanceDir + "/" + regionName;
  CreateDirectory(regionDirectory.c_str(), NULL);
  m_regionDBFile = regionDirectory + "/" + regionName + ".db";

#endif

  if (m_sqliteHelper->initDB(region->getName().c_str(), maxPageCount, pageSize,
                             m_regionDBFile.c_str()) != 0) {
    throw IllegalStateException("Failed to initialize database in SQLITE.");
  }
}

void SqLiteImpl::write(const std::shared_ptr<CacheableKey> &key,
                       const std::shared_ptr<Cacheable> &value,
                       std::shared_ptr<void> &) {
  // Serialize key and value.
  auto &cache = m_regionPtr->getCache();
  auto keyDataBuffer = cache.createDataOutput();
  auto valueDataBuffer = cache.createDataOutput();
  size_t keyBufferSize, valueBufferSize;

  keyDataBuffer.writeObject(key);
  valueDataBuffer.writeObject(value);
  void *keyData =
      const_cast<uint8_t *>(keyDataBuffer.getBuffer(&keyBufferSize));
  void *valueData =
      const_cast<uint8_t *>(valueDataBuffer.getBuffer(&valueBufferSize));

  if (m_sqliteHelper->insertKeyValue(keyData, static_cast<int>(keyBufferSize),
                                     valueData,
                                     static_cast<int>(valueBufferSize)) != 0) {
    throw IllegalStateException("Failed to write key value in SQLITE.");
  }
}

bool SqLiteImpl::writeAll() { return true; }
std::shared_ptr<Cacheable> SqLiteImpl::read(
    const std::shared_ptr<CacheableKey> &key, const std::shared_ptr<void> &) {
  // Serialize key.
  auto keyDataBuffer = m_regionPtr->getCache().createDataOutput();
  size_t keyBufferSize;
  keyDataBuffer.writeObject(key);
  void *keyData =
      const_cast<uint8_t *>(keyDataBuffer.getBuffer(&keyBufferSize));
  void *valueData;
  int valueBufferSize;

  if (m_sqliteHelper->getValue(keyData, static_cast<int>(keyBufferSize),
                               valueData, valueBufferSize) != 0) {
    throw IllegalStateException("Failed to read the value from SQLITE.");
  }

  // Deserialize object and return value.
  auto valueDataBuffer = m_regionPtr->getCache().createDataInput(
      reinterpret_cast<uint8_t *>(valueData), valueBufferSize);
  std::shared_ptr<Cacheable> retValue;
  valueDataBuffer.readObject(retValue);

  // Free memory for serialized form of Cacheable object.
  free(valueData);
  return retValue;
}

bool SqLiteImpl::readAll() { return true; }

void SqLiteImpl::destroyRegion() {
  if (m_sqliteHelper->closeDB() != 0) {
    throw IllegalStateException("Failed to destroy region from SQLITE.");
  }

#ifndef _WIN32
  ::unlink(m_regionDBFile.c_str());
  ::rmdir(m_regionDir.c_str());
  ::rmdir(m_persistanceDir.c_str());
#else
  DeleteFile(m_regionDBFile.c_str());
  RemoveDirectory(m_regionDir.c_str());
  RemoveDirectory(m_persistanceDir.c_str());
#endif
}

void SqLiteImpl::destroy(const std::shared_ptr<CacheableKey> &key,
                         const std::shared_ptr<void> &) {
  // Serialize key and value.
  auto keyDataBuffer = m_regionPtr->getCache().createDataOutput();
  size_t keyBufferSize;
  keyDataBuffer.writeObject(key);
  void *keyData =
      const_cast<uint8_t *>(keyDataBuffer.getBuffer(&keyBufferSize));
  if (m_sqliteHelper->removeKey(keyData, static_cast<int>(keyBufferSize)) !=
      0) {
    throw IllegalStateException("Failed to destroy the key from SQLITE.");
  }
}

SqLiteImpl::SqLiteImpl() { m_sqliteHelper = new SqLiteHelper(); }

void SqLiteImpl::close() {
  m_sqliteHelper->closeDB();

#ifndef _WIN32
  ::unlink(m_regionDBFile.c_str());
  ::rmdir(m_regionDir.c_str());
  ::rmdir(m_persistanceDir.c_str());
#else
  DeleteFile(m_regionDBFile.c_str());
  RemoveDirectory(m_regionDir.c_str());
  RemoveDirectory(m_persistanceDir.c_str());
#endif
}

}  // namespace client
}  // namespace geode
}  // namespace apache

extern "C" {

using apache::geode::client::PersistenceManager;
using apache::geode::client::SqLiteImpl;

SQLITEIMPL_EXPORT PersistenceManager *createSqLiteInstance() {
  return new SqLiteImpl();
}
}
