/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
/**
 * Copyright (c) 2013-2016 Regents of the University of California.
 *
 * This file is part of ndn-cxx library (NDN C++ library with eXperimental eXtensions).
 *
 * ndn-cxx library is free software: you can redistribute it and/or modify it under the
 * terms of the GNU Lesser General Public License as published by the Free Software
 * Foundation, either version 3 of the License, or (at your option) any later version.
 *
 * ndn-cxx library 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 Lesser General Public License for more details.
 *
 * You should have received copies of the GNU General Public License and GNU Lesser
 * General Public License along with ndn-cxx, e.g., in COPYING.md file.  If not, see
 * <http://www.gnu.org/licenses/>.
 *
 * See AUTHORS.md for complete list of ndn-cxx authors and contributors.
 */

#include "nfd-controller.hpp"
#include "nfd-control-response.hpp"
#include "../util/segment-fetcher.hpp"

namespace ndn {
namespace nfd {

using ndn::util::SegmentFetcher;

const uint32_t Controller::ERROR_TIMEOUT = 10060; // WinSock ESAETIMEDOUT
const uint32_t Controller::ERROR_NACK = 10800; // 10000 + TLV-TYPE of Nack header
const uint32_t Controller::ERROR_VALIDATION = 10021; // 10000 + TLS1_ALERT_DECRYPTION_FAILED
const uint32_t Controller::ERROR_SERVER = 500;
const uint32_t Controller::ERROR_LBOUND = 400;
ValidatorNull Controller::s_validatorNull;

Controller::Controller(Face& face, KeyChain& keyChain, Validator& validator)
  : m_face(face)
  , m_keyChain(keyChain)
  , m_validator(validator)
{
}

void
Controller::startCommand(const shared_ptr<ControlCommand>& command,
                         const ControlParameters& parameters,
                         const CommandSucceedCallback& onSuccess1,
                         const CommandFailCallback& onFailure1,
                         const CommandOptions& options)
{
  const CommandSucceedCallback& onSuccess = onSuccess1 ?
    onSuccess1 : [] (const ControlParameters&) {};
  const CommandFailCallback& onFailure = onFailure1 ?
    onFailure1 : [] (uint32_t, const std::string&) {};

  Name requestName = command->getRequestName(options.getPrefix(), parameters);
  Interest interest(requestName);
  interest.setInterestLifetime(options.getTimeout());
  m_keyChain.sign(interest, options.getSigningInfo());

  m_face.expressInterest(interest,
                         bind(&Controller::processCommandResponse, this, _2,
                              command, onSuccess, onFailure),
                         bind(onFailure, ERROR_NACK, "network Nack received"),
                         bind(onFailure, ERROR_TIMEOUT, "request timed out"));
}

void
Controller::processCommandResponse(const Data& data,
                                   const shared_ptr<ControlCommand>& command,
                                   const CommandSucceedCallback& onSuccess,
                                   const CommandFailCallback& onFailure)
{
  m_validator.validate(data,
    [=] (const shared_ptr<const Data>& data) {
      this->processValidatedCommandResponse(*data, command, onSuccess, onFailure);
    },
    [=] (const shared_ptr<const Data>&, const std::string& msg) {
      onFailure(ERROR_VALIDATION, msg);
    }
  );
}

void
Controller::processValidatedCommandResponse(const Data& data,
                                            const shared_ptr<ControlCommand>& command,
                                            const CommandSucceedCallback& onSuccess,
                                            const CommandFailCallback& onFailure)
{
  ControlResponse response;
  try {
    response.wireDecode(data.getContent().blockFromValue());
  }
  catch (const tlv::Error& e) {
    onFailure(ERROR_SERVER, e.what());
    return;
  }

  uint32_t code = response.getCode();
  if (code >= ERROR_LBOUND) {
    onFailure(code, response.getText());
    return;
  }

  ControlParameters parameters;
  try {
    parameters.wireDecode(response.getBody());
  }
  catch (const tlv::Error& e) {
    onFailure(ERROR_SERVER, e.what());
    return;
  }

  try {
    command->validateResponse(parameters);
  }
  catch (const ControlCommand::ArgumentError& e) {
    onFailure(ERROR_SERVER, e.what());
    return;
  }

  onSuccess(parameters);
}

void
Controller::fetchDataset(const Name& prefix,
                         const std::function<void(const ConstBufferPtr&)>& processResponse,
                         const CommandFailCallback& onFailure,
                         const CommandOptions& options)
{
  Interest baseInterest(prefix);
  baseInterest.setInterestLifetime(options.getTimeout());

  SegmentFetcher::fetch(m_face, baseInterest, m_validator, processResponse,
                        bind(&Controller::processDatasetFetchError, this, onFailure, _1, _2));
}

void
Controller::processDatasetFetchError(const CommandFailCallback& onFailure,
                                     uint32_t code, std::string msg)
{
  switch (static_cast<SegmentFetcher::ErrorCode>(code)) {
    // It's intentional to cast as SegmentFetcher::ErrorCode, and to not have a 'default' clause.
    // This forces the switch statement to handle every defined SegmentFetcher::ErrorCode,
    // and breaks compilation if it does not.
    case SegmentFetcher::ErrorCode::INTEREST_TIMEOUT:
      onFailure(ERROR_TIMEOUT, msg);
      break;
    case SegmentFetcher::ErrorCode::DATA_HAS_NO_SEGMENT:
      onFailure(ERROR_SERVER, msg);
      break;
    case SegmentFetcher::ErrorCode::SEGMENT_VALIDATION_FAIL:
      /// \todo When SegmentFetcher exposes validator error code, Controller::ERROR_VALIDATION
      ///       should be replaced with a range that corresponds to validator error codes.
      onFailure(ERROR_VALIDATION, msg);
      break;
    case SegmentFetcher::ErrorCode::NACK_ERROR:
      onFailure(ERROR_NACK, msg);
      break;
  }
}

} // namespace nfd
} // namespace ndn
