/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
/**
 * Copyright (c) 2014,  Regents of the University of California.
 *
 * This file is part of NDN repo-ng (Next generation of NDN repository).
 * See AUTHORS.md for complete list of repo-ng authors and contributors.
 *
 * repo-ng 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.
 *
 * repo-ng 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
 * repo-ng, e.g., in COPYING.md file.  If not, see <http://www.gnu.org/licenses/>.
 */

#include "delete-handle.hpp"

namespace repo {

DeleteHandle::DeleteHandle(Face& face, StorageHandle& storageHandle, KeyChain& keyChain,
                           Scheduler& scheduler, CommandInterestValidator& validator)
  : BaseHandle(face, storageHandle, keyChain, scheduler)
  , m_validator(validator)
{
}

void
DeleteHandle::onInterest(const Name& prefix, const Interest& interest)
{
  //std::cout << "call DeleteHandle" << std::endl;
  m_validator.validate(interest, bind(&DeleteHandle::onValidated, this, _1, prefix),
                       bind(&DeleteHandle::onValidationFailed, this, _1, prefix));
}

void
DeleteHandle::onRegisterSuccess(const Name& prefix)
{
  std::cerr << "Successfully registered prefix " << prefix << std::endl;
}

void
DeleteHandle::onRegisterFailed(const Name& prefix, const std::string& reason)
{
  throw Error("Delete prefix registration failed");
}


void
DeleteHandle::onCheckInterest(const Name& prefix, const Interest& interest)
{
  BOOST_ASSERT(false); // Deletion progress check, not implemented
}


void
DeleteHandle::onCheckRegisterFailed(const Name& prefix, const std::string& reason)
{
  throw Error("Delete check prefix registration failed");
}


void
DeleteHandle::onValidated(const shared_ptr<const Interest>& interest, const Name& prefix)
{
  RepoCommandParameter parameter;

  try {
    extractParameter(*interest, prefix, parameter);
  }
  catch (RepoCommandParameter::Error) {
    negativeReply(*interest, 403);
    return;
  }

  if (parameter.hasSelectors()) {

    if (parameter.hasStartBlockId() || parameter.hasEndBlockId()) {
      negativeReply(*interest, 402);
      return;
    }

    //choose data with selector and delete it
    processSelectorDeleteCommand(*interest, parameter);
    return;
  }

  if (!parameter.hasStartBlockId() && !parameter.hasEndBlockId()) {
    processSingleDeleteCommand(*interest, parameter);
    return;
  }

  processSegmentDeleteCommand(*interest, parameter);
}

void
DeleteHandle::onValidationFailed(const shared_ptr<const Interest>& interest, const Name& prefix)
{
  std::cout << "invalidated" << std::endl;
  negativeReply(*interest, 401);
}

void
DeleteHandle::listen(const Name& prefix)
{
  getFace().setInterestFilter(Name(prefix).append("delete"),
                              bind(&DeleteHandle::onInterest, this, _1, _2),
                              bind(&DeleteHandle::onRegisterSuccess, this, _1),
                              bind(&DeleteHandle::onRegisterFailed, this, _1, _2));
}

void
DeleteHandle::positiveReply(const Interest& interest, const RepoCommandParameter& parameter,
                            uint64_t statusCode, uint64_t nDeletedDatas)
{
  RepoCommandResponse response;
  if (parameter.hasProcessId()) {
    response.setProcessId(parameter.getProcessId());
    response.setStatusCode(statusCode);
    response.setDeleteNum(nDeletedDatas);
  }
  else {
    response.setStatusCode(403);
  }
  reply(interest, response);
}

void
DeleteHandle::negativeReply(const Interest& interest, uint64_t statusCode)
{
  RepoCommandResponse response;
  response.setStatusCode(statusCode);
  reply(interest, response);
}

void
DeleteHandle::processSingleDeleteCommand(const Interest& interest,
                                         RepoCommandParameter& parameter)
{
  uint64_t nDeletedDatas = 0;
  if (getStorageHandle().deleteData(parameter.getName())) {
    nDeletedDatas++;
  }
  positiveReply(interest, parameter, 200, nDeletedDatas);
}

void
DeleteHandle::processSelectorDeleteCommand(const Interest& interest,
                                           RepoCommandParameter& parameter)
{
  uint64_t nDeletedDatas = 0;
  Name name = parameter.getName();
  Selectors selectors = parameter.getSelectors();
  vector<Name> names;
  getStorageHandle().readNameAny(name, selectors, names);

  for (vector<Name>::iterator it = names.begin(); it != names.end(); ++it) {
    if (getStorageHandle().deleteData(*it)) {
      nDeletedDatas++;
    }
  }

  //All data has been deleted, return 200
  positiveReply(interest, parameter, 200, nDeletedDatas);
}

void
DeleteHandle::processSegmentDeleteCommand(const Interest& interest,
                                          RepoCommandParameter& parameter)
{
  if (!parameter.hasStartBlockId())
    parameter.setStartBlockId(0);

  if (parameter.hasEndBlockId()) {
    SegmentNo startBlockId = parameter.getStartBlockId();
    SegmentNo endBlockId = parameter.getEndBlockId();

    if (startBlockId > endBlockId) {
      negativeReply(interest, 403);
      return;
    }

    Name prefix = parameter.getName();
    uint64_t nDeletedDatas = 0;
    for (SegmentNo i = startBlockId; i <= endBlockId; i++) {
      Name name = prefix;
      name.appendSegment(i);
      if (getStorageHandle().deleteData(name)) {
        nDeletedDatas++;
      }
    }
    //All the data deleted, return 200
    positiveReply(interest, parameter, 200, nDeletedDatas);
  }
  else {
    BOOST_ASSERT(false); // segmented deletion without EndBlockId, not implemented
  }
}

} //namespace repo
