/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
/**
 * Copyright (c) 2013-2017, 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 "state-server.h"
#include "logging.h"
#include "periodic-task.h"
#include "simple-interval-generator.h"
#include "task.h"
#include <boost/date_time/posix_time/posix_time.hpp>
#include <boost/lexical_cast.hpp>
#include <boost/make_shared.hpp>
#include <utility>

_LOG_INIT(StateServer);

using namespace Ndnx;
using namespace std;
using namespace boost;

StateServer::StateServer(CcnxWrapperPtr ccnx, ActionLogPtr actionLog,
                         const boost::filesystem::path& rootDir, const Ccnx::Name& userName,
                         const std::string& sharedFolderName, const std::string& appName,
                         ObjectManager& objectManager, int freshness /* = -1*/)
  : m_ccnx(ccnx)
  , m_actionLog(actionLog)
  , m_objectManager(objectManager)
  , m_rootDir(rootDir)
  , m_freshness(freshness)
  , m_executor(1)
  , m_userName(userName)
  , m_sharedFolderName(sharedFolderName)
  , m_appName(appName)
{
  // may be later /localhost should be replaced with /%C1.M.S.localhost

  // <PREFIX_INFO> = /localhost/<user's-device-name>/"chronoshare"/"info"
  m_PREFIX_INFO = Name("/localhost")(m_userName)("chronoshare")(m_sharedFolderName)("info");

  // <PREFIX_CMD> = /localhost/<user's-device-name>/"chronoshare"/"cmd"
  m_PREFIX_CMD = Name("/localhost")(m_userName)("chronoshare")(m_sharedFolderName)("cmd");

  m_executor.start();

  registerPrefixes();
}

StateServer::~StateServer()
{
  m_executor.shutdown();

  deregisterPrefixes();
}

void
StateServer::registerPrefixes()
{
  // currently supporting limited number of command.
  // will be extended to support all planned commands later

  // <PREFIX_INFO>/"actions"/"all"/<segment>  get list of all actions
  m_ccnx->setInterestFilter(Name(m_PREFIX_INFO)("actions")("folder"),
                            bind(&StateServer::info_actions_folder, this, _1));
  m_ccnx->setInterestFilter(Name(m_PREFIX_INFO)("actions")("file"),
                            bind(&StateServer::info_actions_file, this, _1));

  // <PREFIX_INFO>/"filestate"/"all"/<segment>
  m_ccnx->setInterestFilter(Name(m_PREFIX_INFO)("files")("folder"),
                            bind(&StateServer::info_files_folder, this, _1));

  // <PREFIX_CMD>/"restore"/"file"/<one-component-relative-file-name>/<version>/<file-hash>
  m_ccnx->setInterestFilter(Name(m_PREFIX_CMD)("restore")("file"),
                            bind(&StateServer::cmd_restore_file, this, _1));
}

void
StateServer::deregisterPrefixes()
{
  m_ccnx->clearInterestFilter(Name(m_PREFIX_INFO)("actions")("folder"));
  m_ccnx->clearInterestFilter(Name(m_PREFIX_INFO)("actions")("file"));
  m_ccnx->clearInterestFilter(Name(m_PREFIX_INFO)("files")("folder"));
  m_ccnx->clearInterestFilter(Name(m_PREFIX_CMD)("restore")("file"));
}

void
StateServer::formatActionJson(json_spirit::Array& actions, const Ccnx::Name& name,
                              sqlite3_int64 seq_no, const ActionItem& action)
{
  /*
 *      {
 *          "id": {
 *              "userName": "<NDN-NAME-OF-THE-USER>",
 *              "seqNo": "<SEQ_NO_OF_THE_ACTION>"
 *          },
 *          "timestamp": "<ACTION-TIMESTAMP>",
 *          "filename": "<FILENAME>",
 *
 *          "action": "UPDATE | DELETE",
 *
 *          // only if update
 *          "update": {
 *              "hash": "<FILE-HASH>",
 *              "timestamp": "<FILE-TIMESTAMP>",
 *              "chmod": "<FILE-MODE>",
 *              "segNum": "<NUMBER-OF-SEGMENTS (~file size)>"
 *          },
 *
 *          // if parent_device_name is set
 *          "parentId": {
 *              "userName": "<NDN-NAME-OF-THE-USER>",
 *              "seqNo": "<SEQ_NO_OF_THE_ACTION>"
 *          }
 *      }
 */

  using namespace json_spirit;
  using namespace boost::posix_time;

  Object json;
  Object id;

  id.push_back(Pair("userName", boost::lexical_cast<string>(name)));
  id.push_back(Pair("seqNo", static_cast<int64_t>(seq_no)));

  json.push_back(Pair("id", id));

  json.push_back(Pair("timestamp", to_iso_extended_string(from_time_t(action.timestamp()))));
  json.push_back(Pair("filename", action.filename()));
  json.push_back(Pair("version", action.version()));
  json.push_back(Pair("action", (action.action() == 0) ? "UPDATE" : "DELETE"));

  if (action.action() == 0) {
    Object update;
    update.push_back(Pair("hash", boost::lexical_cast<string>(
                                    Hash(action.file_hash().c_str(), action.file_hash().size()))));
    update.push_back(Pair("timestamp", to_iso_extended_string(from_time_t(action.mtime()))));

    ostringstream chmod;
    chmod << setbase(8) << setfill('0') << setw(4) << action.mode();
    update.push_back(Pair("chmod", chmod.str()));

    update.push_back(Pair("segNum", action.seg_num()));
    json.push_back(Pair("update", update));
  }

  if (action.has_parent_device_name()) {
    Object parentId;
    Ccnx::Name parent_device_name(action.parent_device_name().c_str(),
                                  action.parent_device_name().size());
    id.push_back(Pair("userName", boost::lexical_cast<string>(parent_device_name)));
    id.push_back(Pair("seqNo", action.parent_seq_no()));

    json.push_back(Pair("parentId", parentId));
  }

  actions.push_back(json);
}

void
StateServer::info_actions_folder(const Name& interest)
{
  if (interest.size() - m_PREFIX_INFO.size() != 3 && interest.size() - m_PREFIX_INFO.size() != 4) {
    _LOG_DEBUG("Invalid interest: " << interest);
    return;
  }

  _LOG_DEBUG(">> info_actions_folder: " << interest);
  m_executor.execute(bind(&StateServer::info_actions_fileOrFolder_Execute, this, interest, true));
}

void
StateServer::info_actions_file(const Name& interest)
{
  if (interest.size() - m_PREFIX_INFO.size() != 3 && interest.size() - m_PREFIX_INFO.size() != 4) {
    _LOG_DEBUG("Invalid interest: " << interest);
    return;
  }

  _LOG_DEBUG(">> info_actions_file: " << interest);
  m_executor.execute(bind(&StateServer::info_actions_fileOrFolder_Execute, this, interest, false));
}


void
StateServer::info_actions_fileOrFolder_Execute(const Ccnx::Name& interest, bool isFolder /* = true*/)
{
  // <PREFIX_INFO>/"actions"/"folder|file"/<folder|file>/<offset>  get list of all actions

  try {
    int offset = interest.getCompFromBackAsInt(0);

    /// @todo !!! add security checking

    string fileOrFolderName;
    if (interest.size() - m_PREFIX_INFO.size() == 4)
      fileOrFolderName = interest.getCompFromBackAsString(1);
    else // == 3
      fileOrFolderName = "";
    /*
 *   {
 *      "actions": [
 *           ...
 *      ],
 *
 *      // only if there are more actions available
 *      "more": "<NDN-NAME-OF-NEXT-SEGMENT-OF-ACTION>"
 *   }
 */

    using namespace json_spirit;
    Object json;

    Array actions;
    bool more;
    if (isFolder) {
      more =
        m_actionLog->LookupActionsInFolderRecursively(boost::bind(StateServer::formatActionJson,
                                                                  boost::ref(actions), _1, _2, _3),
                                                      fileOrFolderName, offset * 10, 10);
    }
    else {
      more = m_actionLog->LookupActionsForFile(boost::bind(StateServer::formatActionJson,
                                                           boost::ref(actions), _1, _2, _3),
                                               fileOrFolderName, offset * 10, 10);
    }

    json.push_back(Pair("actions", actions));

    if (more) {
      json.push_back(Pair("more", lexical_cast<string>(offset + 1)));
      // Ccnx::Name more = Name (interest.getPartialName (0, interest.size () - 1))(offset + 1);
      // json.push_back (Pair ("more", lexical_cast<string> (more)));
    }

    ostringstream os;
    write_stream(Value(json), os, pretty_print | raw_utf8);
    m_ccnx->publishData(interest, os.str(), 1);
  }
  catch (Ccnx::NameException& ne) {
    // ignore any unexpected interests and errors
    _LOG_ERROR(*boost::get_error_info<Ccnx::error_info_str>(ne));
  }
}

void
StateServer::formatFilestateJson(json_spirit::Array& files, const FileItem& file)
{
  /**
 *   {
 *      "filestate": [
 *      {
 *          "filename": "<FILENAME>",
 *          "owner": {
 *              "userName": "<NDN-NAME-OF-THE-USER>",
 *              "seqNo": "<SEQ_NO_OF_THE_ACTION>"
 *          },
 *
 *          "hash": "<FILE-HASH>",
 *          "timestamp": "<FILE-TIMESTAMP>",
 *          "chmod": "<FILE-MODE>",
 *          "segNum": "<NUMBER-OF-SEGMENTS (~file size)>"
 *      }, ...,
 *      ]
 *
 *      // only if there are more actions available
 *      "more": "<NDN-NAME-OF-NEXT-SEGMENT-OF-FILESTATE>"
 *   }
 */
  using namespace json_spirit;
  using namespace boost::posix_time;

  Object json;

  json.push_back(Pair("filename", file.filename()));
  json.push_back(Pair("version", file.version()));
  {
    Object owner;
    Ccnx::Name device_name(file.device_name().c_str(), file.device_name().size());
    owner.push_back(Pair("userName", boost::lexical_cast<string>(device_name)));
    owner.push_back(Pair("seqNo", file.seq_no()));

    json.push_back(Pair("owner", owner));
  }

  json.push_back(Pair("hash", boost::lexical_cast<string>(
                                Hash(file.file_hash().c_str(), file.file_hash().size()))));
  json.push_back(Pair("timestamp", to_iso_extended_string(from_time_t(file.mtime()))));

  ostringstream chmod;
  chmod << setbase(8) << setfill('0') << setw(4) << file.mode();
  json.push_back(Pair("chmod", chmod.str()));

  json.push_back(Pair("segNum", file.seg_num()));

  files.push_back(json);
}

void
debugFileState(const FileItem& file)
{
  std::cout << file.filename() << std::endl;
}

void
StateServer::info_files_folder(const Ccnx::Name& interest)
{
  if (interest.size() - m_PREFIX_INFO.size() != 3 && interest.size() - m_PREFIX_INFO.size() != 4) {
    _LOG_DEBUG("Invalid interest: " << interest << ", " << interest.size() - m_PREFIX_INFO.size());
    return;
  }

  _LOG_DEBUG(">> info_files_folder: " << interest);
  m_executor.execute(bind(&StateServer::info_files_folder_Execute, this, interest));
}


void
StateServer::info_files_folder_Execute(const Ccnx::Name& interest)
{
  // <PREFIX_INFO>/"filestate"/"folder"/<one-component-relative-folder-name>/<offset>
  try {
    int offset = interest.getCompFromBackAsInt(0);

    // /// @todo !!! add security checking

    string folder;
    if (interest.size() - m_PREFIX_INFO.size() == 4)
      folder = interest.getCompFromBackAsString(1);
    else // == 3
      folder = "";

    /*
 *   {
 *      "files": [
 *           ...
 *      ],
 *
 *      // only if there are more actions available
 *      "more": "<NDN-NAME-OF-NEXT-SEGMENT-OF-ACTION>"
 *   }
 */

    using namespace json_spirit;
    Object json;

    Array files;
    bool more = m_actionLog->GetFileState()
                  ->LookupFilesInFolderRecursively(boost::bind(StateServer::formatFilestateJson,
                                                               boost::ref(files), _1),
                                                   folder, offset * 10, 10);

    json.push_back(Pair("files", files));

    if (more) {
      json.push_back(Pair("more", lexical_cast<string>(offset + 1)));
      // Ccnx::Name more = Name (interest.getPartialName (0, interest.size () - 1))(offset + 1);
      // json.push_back (Pair ("more", lexical_cast<string> (more)));
    }

    ostringstream os;
    write_stream(Value(json), os, pretty_print | raw_utf8);
    m_ccnx->publishData(interest, os.str(), 1);
  }
  catch (Ccnx::NameException& ne) {
    // ignore any unexpected interests and errors
    _LOG_ERROR(*boost::get_error_info<Ccnx::error_info_str>(ne));
  }
}


void
StateServer::cmd_restore_file(const Ccnx::Name& interest)
{
  if (interest.size() - m_PREFIX_CMD.size() != 4 && interest.size() - m_PREFIX_CMD.size() != 5) {
    _LOG_DEBUG("Invalid interest: " << interest);
    return;
  }

  _LOG_DEBUG(">> cmd_restore_file: " << interest);
  m_executor.execute(bind(&StateServer::cmd_restore_file_Execute, this, interest));
}

void
StateServer::cmd_restore_file_Execute(const Ccnx::Name& interest)
{
  // <PREFIX_CMD>/"restore"/"file"/<one-component-relative-file-name>/<version>/<file-hash>

  /// @todo !!! add security checking

  try {
    FileItemPtr file;

    if (interest.size() - m_PREFIX_CMD.size() == 5) {
      Hash hash(head(interest.getCompFromBack(0)), interest.getCompFromBack(0).size());
      int64_t version = interest.getCompFromBackAsInt(1);
      string filename =
        interest.getCompFromBackAsString(2); // should be safe even with full relative path

      file = m_actionLog->LookupAction(filename, version, hash);
      if (!file) {
        _LOG_ERROR("Requested file is not found: [" << filename << "] version [" << version
                                                    << "] hash ["
                                                    << hash.shortHash()
                                                    << "]");
      }
    }
    else {
      int64_t version = interest.getCompFromBackAsInt(0);
      string filename =
        interest.getCompFromBackAsString(1); // should be safe even with full relative path

      file = m_actionLog->LookupAction(filename, version, Hash(0, 0));
      if (!file) {
        _LOG_ERROR("Requested file is not found: [" << filename << "] version [" << version << "]");
      }
    }

    if (!file) {
      m_ccnx->publishData(interest, "FAIL: Requested file is not found", 1);
      return;
    }

    Hash hash = Hash(file->file_hash().c_str(), file->file_hash().size());

    ///////////////////
    // now the magic //
    ///////////////////

    boost::filesystem::path filePath = m_rootDir / file->filename();
    Name deviceName(file->device_name().c_str(), file->device_name().size());

    try {
      if (filesystem::exists(filePath) && filesystem::last_write_time(filePath) == file->mtime() &&
#if BOOST_VERSION >= 104900
          filesystem::status(filePath).permissions() == static_cast<filesystem::perms>(file->mode()) &&
#endif
          *Hash::FromFileContent(filePath) == hash) {
        m_ccnx->publishData(interest, "OK: File already exists", 1);
        _LOG_DEBUG("Asking to assemble a file, but file already exists on a filesystem");
        return;
      }
    }
    catch (filesystem::filesystem_error& error) {
      m_ccnx->publishData(interest, "FAIL: File operation failed", 1);
      _LOG_ERROR("File operations failed on [" << filePath << "] (ignoring)");
    }

    _LOG_TRACE("Restoring file [" << filePath << "]");
    if (m_objectManager.objectsToLocalFile(deviceName, hash, filePath)) {
      last_write_time(filePath, file->mtime());
#if BOOST_VERSION >= 104900
      permissions(filePath, static_cast<filesystem::perms>(file->mode()));
#endif
      m_ccnx->publishData(interest, "OK", 1);
    }
    else {
      m_ccnx->publishData(interest, "FAIL: Unknown error while restoring file", 1);
    }
  }
  catch (Ccnx::NameException& ne) {
    // ignore any unexpected interests and errors
    _LOG_ERROR(*boost::get_error_info<Ccnx::error_info_str>(ne));
  }
}
