/* -*- 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 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 "dns.hpp"

#include "scheduler.hpp"

namespace ndn {
namespace dns {

typedef boost::asio::ip::udp::endpoint EndPoint;
typedef boost::asio::ip::basic_resolver<boost::asio::ip::udp> BoostResolver;

class Resolver : noncopyable
{
public:
  Resolver(const SuccessCallback& onSuccess,
           const ErrorCallback& onError,
           const ndn::dns::AddressSelector& addressSelector,
           boost::asio::io_service& ioService)
    : m_resolver(ioService)
    , m_addressSelector(addressSelector)
    , m_onSuccess(onSuccess)
    , m_onError(onError)
    , m_scheduler(ioService)
  {
  }

  void
  asyncResolve(const std::string& host,
               const time::nanoseconds& timeout,
               const shared_ptr<Resolver>& self)
  {
    BoostResolver::query query(host, NULL_PORT

#if not defined(__FreeBSD__)
                               , BoostResolver::query::all_matching
#endif
                               );

    m_resolver.async_resolve(query, bind(&Resolver::onResolveSuccess, this, _1, _2, self));

    m_resolveTimeout = m_scheduler.scheduleEvent(timeout,
                                                 bind(&Resolver::onResolveError, this,
                                                 "Timeout", self));
  }

  BoostResolver::iterator
  syncResolve(BoostResolver::query query)
  {
    return m_resolver.resolve(query);
  }

  void
  onResolveSuccess(const boost::system::error_code& error,
                   BoostResolver::iterator remoteEndpoint,
                   const shared_ptr<Resolver>& self)
  {
    m_scheduler.cancelEvent(m_resolveTimeout);

    if (error)
      {
        if (error == boost::system::errc::operation_canceled)
          {
            return;
          }

        return m_onError("Remote endpoint hostname or port cannot be resolved: " +
                         error.category().message(error.value()));
      }

    BoostResolver::iterator end;
    for (; remoteEndpoint != end; ++remoteEndpoint)
      {
        IpAddress address(EndPoint(*remoteEndpoint).address());

        if (m_addressSelector(address))
          {
            return m_onSuccess(address);
          }
      }

    m_onError("No endpoint matching the specified address selector found");
  }

  void
  onResolveError(const std::string& errorInfo, const shared_ptr<Resolver>& self)
  {
    m_resolver.cancel();
    m_onError(errorInfo);
  }

public:
  static const std::string NULL_PORT;

private:
  BoostResolver m_resolver;
  EventId m_resolveTimeout;

  ndn::dns::AddressSelector m_addressSelector;
  SuccessCallback m_onSuccess;
  ErrorCallback m_onError;

  Scheduler m_scheduler;
};

const std::string Resolver::NULL_PORT = "";

void
asyncResolve(const std::string& host,
             const SuccessCallback& onSuccess,
             const ErrorCallback& onError,
             boost::asio::io_service& ioService,
             const ndn::dns::AddressSelector& addressSelector,
             const time::nanoseconds& timeout)
{
  shared_ptr<Resolver> resolver = make_shared<Resolver>(onSuccess, onError,
                                                        addressSelector, ndn::ref(ioService));
  resolver->asyncResolve(host, timeout, resolver);
  // resolver will be destroyed when async operation finishes or global IO service stops
}

IpAddress
syncResolve(const std::string& host, boost::asio::io_service& ioService,
            const ndn::dns::AddressSelector& addressSelector)
{
  Resolver resolver(SuccessCallback(), ErrorCallback(), addressSelector, ioService);

  BoostResolver::query query(host, Resolver::NULL_PORT
#if not defined(__FreeBSD__)
                                 , BoostResolver::query::all_matching
#endif
                                 );

  BoostResolver::iterator remoteEndpoint = resolver.syncResolve(query);

  BoostResolver::iterator end;
  for (; remoteEndpoint != end; ++remoteEndpoint)
    {
      if (addressSelector(EndPoint(*remoteEndpoint).address()))
        {
          return EndPoint(*remoteEndpoint).address();
        }
    }
  throw Error("No endpoint matching the specified address selector found");
}

} // namespace dns
} // namespace ndn
