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

#include "dispatcher.h"
#include <boost/make_shared.hpp>

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

static const string BROADCAST_DOMAIN = "/ndn/broadcast/chronoshare";
static const int MAX_FILE_SEGMENT_SIZE = 1024;

Dispatcher::Dispatcher(const filesystem::path &path, const std::string &localUserName, const Ccnx::Name &localPrefix, const std::string &sharedFolder, const filesystem::path &rootDir, Ccnx::CcnxWrapperPtr ccnx, SchedulerPtr scheduler, int poolSize)
           : m_ccnx(ccnx)
           , m_core(NULL)
           , m_rootDir(rootDir)
           , m_executor(poolSize)
           , m_objectManager(ccnx, rootDir)
           , m_localUserName(localUserName)
           , m_sharedFolder(sharedFolder)
{
  m_syncLog = make_shared<SyncLog>(path, localUserName);
  m_actionLog = make_shared<ActionLog>(m_ccnx, path, m_syncLog, sharedFolder);

  Name syncPrefix(BROADCAST_DOMAIN + sharedFolder);
  m_core = new SyncCore (m_syncLog, localUserName, localPrefix, syncPrefix,
                         bind(&Dispatcher::syncStateChanged, this, _1), ccnx, scheduler);
}

Dispatcher::~Dispatcher()
{
  if (m_core != NULL)
  {
    delete m_core;
    m_core = NULL;
  }
}

void
Dispatcher::fileChangedCallback(const filesystem::path &relativeFilePath, ActionType type)
{
  Executor::Job job = bind(&Dispatcher::fileChanged, this, relativeFilePath, type);
  m_executor.execute(job);
}

void
Dispatcher::syncStateChangedCallback(const SyncStateMsgPtr &stateMsg)
{
  Executor::Job job = bind(&Dispatcher::syncStateChanged, this, stateMsg);
  m_executor.execute(job);
}

void
Dispatcher::actionReceivedCallback(const ActionItemPtr &actionItem)
{
  Executor::Job job = bind(&Dispatcher::actionReceived, this, actionItem);
  m_executor.execute(job);
}

void
Dispatcher::fileSegmentReceivedCallback(const Ccnx::Name &name, const Ccnx::Bytes &content)
{
  Executor::Job job = bind(&Dispatcher::fileSegmentReceived, this, name, content);
  m_executor.execute(job);
}

void
Dispatcher::fileReadyCallback(const Ccnx::Name &fileNamePrefix)
{
  Executor::Job job = bind(&Dispatcher::fileReady, this, fileNamePrefix);
  m_executor.execute(job);
}

void
Dispatcher::fileChanged(const filesystem::path &relativeFilePath, ActionType type)
{

  switch (type)
  {
    case UPDATE:
    {
      filesystem::path absolutePath = m_rootDir / relativeFilePath;
      if (filesystem::exists(absolutePath))
      {
        HashPtr hash = Hash::FromFileContent(absolutePath);
        if (m_actionLog->KnownFileState(relativeFilePath.generic_string(), *hash))
        {
          // the file state is known; i.e. the detected changed file is identical to
          // the file state kept in FileState table
          // it is the case that backend puts the file fetched from remote;
          // we should not publish action for this.
        }
        else
        {
          uintmax_t fileSize = filesystem::file_size(absolutePath);
          int seg_num;
          tie (hash, seg_num) = m_objectManager.localFileToObjects (absolutePath, m_localUserName);

          time_t wtime = filesystem::last_write_time (absolutePath);
          filesystem::file_status stat = filesystem::status (absolutePath);
          int mode = stat.permissions();

          m_actionLog->AddLocalActionUpdate (relativeFilePath.generic_string(), *hash, wtime, mode, seg_num);
          // publish the file

          // notify SyncCore to propagate the change
          m_core->localStateChanged();
        }
        break;
      }
      else
      {
        BOOST_THROW_EXCEPTION (Error::Dispatcher() << error_info_str("Update non exist file: " + absolutePath.string() ));
      }
    }
    case DELETE:
    {
      m_actionLog->AddLocalActionDelete (relativeFilePath.generic_string());
      // notify SyncCore to propagate the change
      m_core->localStateChanged();
      break;
    }
    default:
      break;
  }
}

void
Dispatcher::syncStateChanged(const SyncStateMsgPtr &stateMsg)
{
  int size = stateMsg->state_size();
  int index = 0;
  // iterate and fetch the actions
  while (index < size)
  {
    SyncState state = stateMsg->state(index);
    if (state.has_old_seq() && state.has_seq())
    {
      uint64_t oldSeq = state.old_seq();
      uint64_t newSeq = state.seq();
      Name userName = state.name();
      Name locator = state.locator();

      // fetch actions with oldSeq + 1 to newSeq (inclusive)
      Name actionNameBase(userName);
      actionNameBase.appendComp("action")
                .appendComp(m_sharedFolder);

      for (uint64_t seqNo = oldSeq + 1; seqNo <= newSeq; seqNo++)
      {
        Name actionName = actionNameBase;
        actionName.appendComp(seqNo);

        // TODO:
        // use fetcher to fetch the name with callback "actionRecieved"
      }
    }
  }
}

void
Dispatcher::actionReceived(const ActionItemPtr &actionItem)
{
  switch (actionItem->action())
  {
    case ActionItem::UPDATE:
    {
      // @TODO
      // need a function in ActionLog to apply received action, i.e. record remote action in ActionLog

      string hashBytes = actionItem->file_hash();
      Hash hash(hashBytes.c_str(), hashBytes.size());
      ostringstream oss;
      oss << hash;
      string hashString = oss.str();
      ObjectDbPtr db = make_shared<ObjectDb>(m_rootDir, hashString);
      m_objectDbMap[hashString] = db;

      // TODO:
      // user fetcher to fetch the file with callback "fileSegmentReceived" for segment callback and "fileReady" for file ready callback
      break;
    }
    case ActionItem::DELETE:
    {
      string filename = actionItem->filename();
      // TODO:
      // m_actionLog->AddRemoteActionDelete(filename);
      break;
    }
    default:
      break;
  }
}

void
Dispatcher::fileSegmentReceived(const Ccnx::Name &name, const Ccnx::Bytes &content)
{
  int size = name.size();
  uint64_t segment = name.getCompAsInt(size - 1);
  Bytes hashBytes = name.getComp(size - 2);
  Hash hash(head(hashBytes), hashBytes.size());
  ostringstream oss;
  oss << hash;
  string hashString = oss.str();
  if (m_objectDbMap.find(hashString) != m_objectDbMap.end())
  {
    ObjectDbPtr db = m_objectDbMap[hashString];
    // get the device name
    // Name deviceName = name.getPartialName();
    // db->saveContenObject(deviceName, segment, content);
  }
  else
  {
    cout << "no db available for this content object: " << name << ", size: " << content.size() << endl;
  }
}

void
Dispatcher::fileReady(const Ccnx::Name &fileNamePrefix)
{
  int size = fileNamePrefix.size();
  Bytes hashBytes = fileNamePrefix.getComp(size - 1);
  Hash hash(head(hashBytes), hashBytes.size());
  ostringstream oss;
  oss << hash;
  string hashString = oss.str();

  if (m_objectDbMap.find(hashString) != m_objectDbMap.end())
  {
    // remove the db handle
    m_objectDbMap.erase(hashString);
  }
  else
  {
    cout << "no db available for this file: " << fileNamePrefix << endl;
  }

  // query the action table to get the path on local file system
  // m_objectManager.objectsToLocalFile(deviceName, hash, relativeFilePath);

}
