/* -*- Mode: C++; c-file-style: "gnu"; indent-tabs-mode:nil -*- */
/*
 * Copyright (c) 2013 University of California, Los Angeles
 *
 * This program is free software; you can redistribute it and/or modify
 * it under the terms of the GNU General Public License version 2 as
 * published by the Free Software Foundation;
 *
 * This program 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 this program; if not, write to the Free Software
 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
 *
 * Author: Alexander Afanasyev <alexander.afanasyev@ucla.edu>
 *         Zhenkai Zhu <zhenkai@cs.ucla.edu>
 */

#include "state-server.h"
#include "logging.h"
#include <boost/make_shared.hpp>
#include <utility>
#include "task.h"
#include "periodic-task.h"
#include "simple-interval-generator.h"
#include <boost/lexical_cast.hpp>
#include <boost/date_time/posix_time/posix_time.hpp>

INIT_LOGGER ("StateServer");

using namespace Ccnx;
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));
    }
}
