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

#include "fib-status.hpp"

#ifdef WAF
#include "fib-status.moc"
// #include "fib-status.cpp.moc"
#endif

#include <ndn-cxx/face.hpp>
#include <ndn-cxx/name.hpp>
#include <ndn-cxx/interest.hpp>
#include <ndn-cxx/encoding/buffer-stream.hpp>
#include <ndn-cxx/management/nfd-fib-entry.hpp>
#include <ndn-cxx/management/nfd-face-status.hpp>
#include <ndn-cxx/management/nfd-forwarder-status.hpp>

namespace ndn {

FibStatusModel::FibStatusModel(Face& face, QObject *parent/* = 0*/)
  : QAbstractListModel(parent)
  , m_face(face)
{
}

int
FibStatusModel::rowCount(const QModelIndex &parent/* = QModelIndex()*/) const
{
  return m_items.count();
}

void
FibStatusModel::addItem(const FibStatusItem &item)
{
  beginInsertRows(QModelIndex(), rowCount(), rowCount());
  m_items << item;
  endInsertRows();
}

QVariant
FibStatusModel::data(const QModelIndex & index, int role) const
{
  if (index.row() < 0 || index.row() >= m_items.count()) {
    return QVariant();
  }

  const FibStatusItem &item = m_items.at(index.row());
  if (role == PrefixRole) {
    return item.prefix();
  } else if (role == FaceIdRole) {
    return item.faceId();
  } else if (role == CostRole) {
    return item.cost();
  }

  return QVariant();
}

QHash<int, QByteArray>
FibStatusModel::roleNames() const
{
  QHash<int, QByteArray> roles;
  roles[PrefixRole] = "prefix";
  roles[FaceIdRole] = "faceId";
  roles[CostRole] = "cost";
  return roles;
}

void
FibStatusModel::clear()
{
  beginResetModel();
  m_items.clear();
  endResetModel();
}

Q_INVOKABLE void
FibStatusModel::fetchFibInformation()
{
  // m_buffer = make_shared<OBufferStream>();

  // Interest interest("/localhost/nfd/fib/list");
  // interest.setChildSelector(1);
  // interest.setMustBeFresh(true);
  // m_face.expressInterest(interest,
  //                        bind(&FibStatusModel::fetchSegments, this, _2,
  //                             &FibStatusModel::afterFetchedFibEnumerationInformation),
  //                        bind(&FibStatusModel::onTimeout, this));
  // try {
  //   m_face.processEvents();
  // } catch (Tlv::Error e) {
  //   std::cerr << e.what() << std::endl;
  //   clear();
  // }
}

void
FibStatusModel::afterFetchedFibEnumerationInformation()
{
//   beginResetModel();
//   m_items.clear();
//   ConstBufferPtr buf = m_buffer->buf();

//   Block block;
//   size_t offset = 0;
//   while (offset < buf->size()) {
//     bool ok = Block::fromBuffer(buf, offset, block);
//     if (!ok) {
//       std::cerr << "ERROR: cannot decode FibEntry TLV" << std::endl;
//       break;
//     }
//     offset += block.size();

//     nfd::FibEntry fibEntry(block);

//     for (std::list<nfd::NextHopRecord>::const_iterator
//            nextHop = fibEntry.getNextHopRecords().begin();
//          nextHop != fibEntry.getNextHopRecords().end();
//          ++nextHop) {
//       addItem(FibStatusItem(QString::fromStdString(fibEntry.getPrefix().toUri()),
//                             nextHop->getFaceId(), nextHop->getCost()));
//     }
//   }
//   endResetModel();
}


void
FibStatusModel::fetchSegments(const Data& data, void (FibStatusModel::*onDone)())
{
  // m_buffer->write(reinterpret_cast<const char*>(data.getContent().value()),
  //                 data.getContent().value_size());

  // uint64_t currentSegment = data.getName().get(-1).toSegment();

  // const name::Component& finalBlockId = data.getMetaInfo().getFinalBlockId();
  // if (finalBlockId.empty() ||
  //     finalBlockId.toSegment() > currentSegment) {
  //   m_face.expressInterest(data.getName().getPrefix(-1).appendSegment(currentSegment+1),
  //                          bind(&FibStatusModel::fetchSegments, this, _2, onDone),
  //                          bind(&FibStatusModel::onTimeout, this));
  // } else {
  //   return (this->*onDone)();
  // }
}

void
FibStatusModel::onTimeout()
{
  std::cerr << "Request timed out" << std::endl;
}

} // namespace ndn
