/* -*- 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 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 <QtQml/QQmlApplicationEngine>
#include <QtWidgets/QApplication>
#include <QtWidgets/QPushButton>
#include <QtQml/QQmlContext>

#include "forwarder-status.hpp"
#include "fib-status.hpp"
#include "tray-menu.hpp"

#include <ndn-cxx/face.hpp>
#include <ndn-cxx/util/scheduler.hpp>
#include <ndn-cxx/mgmt/nfd/controller.hpp>
#include <ndn-cxx/mgmt/nfd/status-dataset.hpp>

#include <boost/thread.hpp>

namespace ndn {

class Ncc
{
public:
  Ncc()
    : m_isActive(true)
    , m_face(nullptr, m_keyChain)
    , m_controller(m_face, m_keyChain)
    , m_scheduler(m_face.getIoService())
    , m_fibModel(m_face)
    , m_tray(m_engine.rootContext(), m_face)
  {
    QQmlContext* context = m_engine.rootContext();

    context->setContextProperty("forwarderModel", &m_forwarderStatusModel);
    context->setContextProperty("fibModel", &m_fibModel);
    context->setContextProperty("trayModel", &m_tray);

    m_engine.load((QUrl("qrc:/main.qml")));

    m_nfdThread = boost::thread(&Ncc::nfdConnectionLoop, this);
  }

  void
  nfdConnectionLoop()
  {
    try {
#ifdef BOOST_THREAD_USES_CHRONO
      time::seconds retryTimeout = time::seconds(5);
#else
      boost::posix_time::time_duration retryTimeout = boost::posix_time::seconds(1);
#endif

      while (m_isActive) {
        try {
          while (m_isActive) {
            m_controller.fetch<ndn::nfd::ForwarderGeneralStatusDataset>(bind(&Ncc::onStatusRetrieved, this, _1),
                                                                        bind(&Ncc::onStatusTimeout, this));
            m_face.processEvents(time::milliseconds::zero(), true);
          }
        }
        catch (const std::exception&e) {
          emit m_tray.nfdActivityUpdate(false);
          m_face.shutdown();
#ifdef BOOST_THREAD_USES_CHRONO
          boost::this_thread::sleep_for(retryTimeout);
#else
          boost::this_thread::sleep(retryTimeout);
#endif
        }
      }
    }
    catch (const boost::thread_interrupted&) {
      // done
    }
  }

  void
  onStatusRetrieved(const nfd::ForwarderStatus& status)
  {
    emit m_tray.nfdActivityUpdate(true);
    emit m_forwarderStatusModel.onDataReceived(status);

    m_scheduler.scheduleEvent(time::seconds(6), bind(&Ncc::requestNfdStatus, this));
  }

  void
  onStatusTimeout()
  {
    emit m_tray.nfdActivityUpdate(false);

    std::cerr << "Should not really happen, most likely a serious problem" << std::endl;
    m_scheduler.scheduleEvent(time::seconds(6), bind(&Ncc::requestNfdStatus, this));
  }

  void
  stop()
  {
    m_isActive = false;
    m_face.shutdown();
    m_scheduler.cancelAllEvents();
    m_nfdThread.interrupt();
    m_nfdThread.join();
  }

private:
  void
  requestNfdStatus()
  {
    m_controller.fetch<ndn::nfd::ForwarderGeneralStatusDataset>(bind(&Ncc::onStatusRetrieved, this, _1),
                                                       bind(&Ncc::onStatusTimeout, this));
  }

private:
  volatile bool m_isActive;
  boost::thread m_nfdThread;

  KeyChain m_keyChain;
  Face m_face;
  nfd::Controller m_controller;
  Scheduler m_scheduler;

  QQmlApplicationEngine m_engine;

  ForwarderStatusModel m_forwarderStatusModel;
  FibStatusModel m_fibModel;
  TrayMenu m_tray;
};

} // namespace ndn

Q_DECLARE_METATYPE(ndn::shared_ptr<const ndn::Data>)
Q_DECLARE_METATYPE(ndn::nfd::ForwarderStatus)

int
main(int argc, char *argv[])
{
  qRegisterMetaType<ndn::shared_ptr<const ndn::Data>>();
  qRegisterMetaType<ndn::nfd::ForwarderStatus>();

  QApplication::setAttribute(Qt::AA_UseHighDpiPixmaps);
  QApplication app(argc, argv);

  ndn::Ncc controlCenterGui;

  QApplication::setQuitOnLastWindowClosed(false);
  int retval = app.exec();

  controlCenterGui.stop();

  return retval;
}
