/* -*- 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: Zhenkai Zhu <zhenkai@cs.ucla.edu>
 *         Alexander Afanasyev <alexander.afanasyev@ucla.edu>
 */

#include "content-server.h"
#include "logging.h"
#include <boost/lexical_cast.hpp>

INIT_LOGGER ("ContentServer");

using namespace Ccnx;
using namespace std;
using namespace boost;

ContentServer::ContentServer(CcnxWrapperPtr ccnx, ActionLogPtr actionLog,
                             const boost::filesystem::path &rootDir,
                             const Ccnx::Name &deviceName, const std::string &sharedFolderName,
                             int freshness)
  : m_ccnx(ccnx)
  , m_actionLog(actionLog)
  , m_dbFolder(rootDir / ".chronoshare")
  , m_freshness(freshness)
  , m_executor (1)
  , m_deviceName (deviceName)
  , m_sharedFolderName (sharedFolderName)
{
  m_executor.start ();
}

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

  ScopedLock lock (m_mutex);
  for (PrefixIt it = m_prefixes.begin(); it != m_prefixes.end(); ++it)
  {
    m_ccnx->clearInterestFilter (*it);
  }
}

void
ContentServer::registerPrefix(const Name &prefix)
{
  m_ccnx->setInterestFilter (prefix, bind(&ContentServer::serve, this, prefix, _1));

  _LOG_DEBUG (">> content server: register " << prefix);

  ScopedLock lock (m_mutex);
  m_prefixes.insert(prefix);
}

void
ContentServer::deregisterPrefix (const Name &prefix)
{

  m_ccnx->clearInterestFilter(prefix);

  _LOG_DEBUG ("<< content server: deregister " << prefix);
  ScopedLock lock (m_mutex);
  m_prefixes.erase (prefix);
}

void
ContentServer::serve(Name forwardingHint, const Name &interest)
{
  // /forwardingHint/device-name/action/shared-folder/action-seq
  // /forwardingHint/device-name/file/file-hash/segment

  Name name = interest.getPartialName(forwardingHint.size());
  if (name.size() > 3)
  {
    string type = name.getCompAsString(name.size() - 3);
    if (type == "action")
    {
      serve_Action (forwardingHint, interest);
    }
    else if (type == "file")
    {
      serve_File (forwardingHint, interest);
    }
  }
}

void
ContentServer::serve_Action (Name forwardingHint, const Name &interest)
{
  _LOG_DEBUG (">> content server serving, forwardHing " << forwardingHint << ", interest " << interest);
  m_executor.execute (bind (&ContentServer::serve_Action_Execute, this, forwardingHint, interest));
  // need to unlock ccnx mutex... or at least don't lock it
}

void
ContentServer::serve_File (Name forwardingHint, const Name &interest)
{
  _LOG_DEBUG (">> content server serving, forwardHing " << forwardingHint << ", interest " << interest);
  m_executor.execute (bind (&ContentServer::serve_File_Execute, this, forwardingHint, interest));
  // need to unlock ccnx mutex... or at least don't lock it
}

void
ContentServer::serve_File_Execute (Name forwardingHint, Name interest)
{
  // /device-name/file/<file-hash>/segment, or

  int64_t segment = interest.getCompFromBackAsInt (0);
  Name deviceName = interest.getPartialName (forwardingHint.size (), interest.size () - forwardingHint.size () - 3);
  Hash hash (head(interest.getCompFromBack (1)), interest.getCompFromBack (1).size());

  _LOG_DEBUG (" server FILE for device: " << deviceName << ", file_hash: " << hash << " segment: " << segment);

  string hashStr = lexical_cast<string> (hash);
  if (ObjectDb::DoesExist (m_dbFolder, deviceName, hashStr)) // this is kind of overkill, as it counts available segments
    {
      ObjectDb db (m_dbFolder, hashStr);
      // may do prefetching

      BytesPtr co = db.fetchSegment (deviceName, segment);
      if (co)
        {
          if (forwardingHint.size () == 0)
            {
              m_ccnx->putToCcnd (*co);
            }
          else
            {
              if (m_freshness > 0)
                {
                  m_ccnx->publishData(interest, *co, m_freshness);
                }
              else
                {
                  m_ccnx->publishData(interest, *co);
                }
            }

        }
      else
        {
          _LOG_ERROR ("ObjectDd exists, but no segment " << segment << " for device: " << deviceName << ", file_hash: " << hash);
        }
    }
  else
    {
      _LOG_ERROR ("ObjectDd doesn't exist for device: " << deviceName << ", file_hash: " << hash);
    }

}

void
ContentServer::serve_Action_Execute (Name forwardingHint, Name interest)
{
  // /device-name/action/shared-folder/seq

  int64_t seqno = interest.getCompFromBackAsInt (0);
  Name deviceName = interest.getPartialName (forwardingHint.size (), interest.size () - forwardingHint.size () - 3);

  _LOG_DEBUG (" server ACTION for device: " << deviceName << " and seqno: " << seqno);

  PcoPtr pco = m_actionLog->LookupActionPco (deviceName, seqno);
  if (pco)
    {
      if (forwardingHint.size () == 0)
        {
          m_ccnx->putToCcnd (pco->buf ());
        }
      else
        {
          const Bytes &content = pco->buf ();
          if (m_freshness > 0)
            {
              m_ccnx->publishData(interest, content, m_freshness);
            }
          else
            {
              m_ccnx->publishData(interest, content);
            }
        }
    }
  else
    {
      _LOG_ERROR ("ACTION not found for device: " << deviceName << " and seqno: " << seqno);
    }
}
