#ifndef BOOST_NETWORK_PROTOCOL_HTTP_POLICIES_SYNC_RESOLVER_20091214
#define BOOST_NETWORK_PROTOCOL_HTTP_POLICIES_SYNC_RESOLVER_20091214

//          Copyright Dean Michael Berris 2009.
// Distributed under the Boost Software License, Version 1.0.
//    (See accompanying file LICENSE_1_0.txt or copy at
//          http://www.boost.org/LICENSE_1_0.txt)

#include <utility>
#include <boost/network/protocol/http/traits/resolver.hpp>
#include <boost/fusion/adapted/std_pair.hpp>
#include <boost/fusion/include/tuple.hpp>
#include <boost/network/traits/string.hpp>
#include <boost/algorithm/string/case_conv.hpp>
#include <boost/unordered_map.hpp>

namespace boost {
namespace network {
namespace http {
namespace policies {

template <class Tag>
struct sync_resolver {

  typedef typename resolver<Tag>::type resolver_type;
  typedef typename resolver_type::iterator resolver_iterator;
  typedef typename resolver_type::query resolver_query;
  typedef std::pair<resolver_iterator, resolver_iterator>
      resolver_iterator_pair;

 protected:
  typedef typename string<Tag>::type string_type;
  typedef boost::unordered_map<string_type, resolver_iterator_pair>
      resolved_cache;
  resolved_cache endpoint_cache_;
  bool cache_resolved_;

  sync_resolver(bool cache_resolved) : cache_resolved_(cache_resolved) {}

  resolver_iterator_pair resolve(resolver_type& resolver_,
                                 string_type const& hostname,
                                 string_type const& port) {
    if (cache_resolved_) {
      typename resolved_cache::iterator cached_iterator =
          endpoint_cache_.find(hostname);
      if (cached_iterator == endpoint_cache_.end()) {
        bool inserted = false;
        boost::fusion::tie(cached_iterator, inserted) =
            endpoint_cache_.insert(std::make_pair(
                boost::to_lower_copy(hostname),
                std::make_pair(
                    resolver_.resolve(resolver_query(
                        hostname, port, resolver_query::numeric_service)),
                    resolver_iterator())));
      };
      return cached_iterator->second;
    };

    return std::make_pair(resolver_.resolve(resolver_query(
                              hostname, port, resolver_query::numeric_service)),
                          resolver_iterator());
  };
};

}  // namespace policies

}  // namespace http

}  // namespace network

}  // namespace boost

#endif  // BOOST_NETWORK_PROTOCOL_HTTP_POLICIES_SYNC_RESOLVER_20091214
