
#ifndef BOOST_NETWORK_PROTOCOL_HTTP_MESSAGE_WRAPPER_HEADERS_HPP_20100811
#define BOOST_NETWORK_PROTOCOL_HTTP_MESSAGE_WRAPPER_HEADERS_HPP_20100811

// Copyright Dean Michael Berris 2010.
// 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 <boost/network/traits/headers_container.hpp>
#include <boost/network/traits/string.hpp>

namespace boost {
namespace network {
namespace http {

template <class Message>
struct headers_range {
  typedef typename headers_container<typename Message::tag>::type
      headers_container_type;
  typedef typename boost::iterator_range<
      typename headers_container_type::const_iterator> type;
};

template <class Tag>
struct basic_request;

template <class Tag>
struct basic_response;

namespace impl {

template <class Tag>
struct request_headers_wrapper {
  typedef typename string<Tag>::type string_type;
  typedef typename headers_range<basic_request<Tag> >::type range_type;
  typedef typename headers_container<Tag>::type headers_container_type;
  typedef typename headers_container_type::const_iterator const_iterator;
  typedef typename headers_container_type::iterator iterator;

  explicit request_headers_wrapper(basic_request<Tag> const& message)
      : message_(message) {}

  range_type operator[](string_type const& key) const {
    return message_.headers().equal_range(key);
  }

  typename headers_container_type::size_type count(string_type const& key)
      const {
    return message_.headers().count(key);
  }

  const_iterator begin() const { return message_.headers().begin(); }

  const_iterator end() const { return message_.headers().end(); }

  operator range_type() {
    return make_iterator_range(message_.headers().begin(),
                               message_.headers().end());
  }

  operator headers_container_type() { return message_.headers(); }

 private:
  basic_request<Tag> const& message_;
};

template <class Tag>
struct response_headers_wrapper {
  typedef typename string<Tag>::type string_type;
  typedef typename headers_range<basic_response<Tag> >::type range_type;
  typedef typename headers_container<Tag>::type headers_container_type;
  typedef typename headers_container_type::const_iterator const_iterator;
  typedef typename headers_container_type::iterator iterator;

  explicit response_headers_wrapper(basic_response<Tag> const& message)
      : message_(message) {}

  range_type operator[](string_type const& key) const {
    return message_.headers().equal_range(key);
  }

  typename headers_container_type::size_type count(string_type const& key)
      const {
    return message_.headers().count(key);
  }

  const_iterator begin() const { return message_.headers().begin(); }

  const_iterator end() const { return message_.headers().end(); }

  operator range_type() {
    return make_iterator_range(message_.headers().begin(),
                               message_.headers().end());
  }

  operator headers_container_type() { return message_.headers(); }

 private:
  basic_response<Tag> const& message_;
};

}  // namespace impl

template <class Tag>
inline impl::request_headers_wrapper<Tag> headers(
    basic_request<Tag> const& request_) {
  return impl::request_headers_wrapper<Tag>(request_);
}

template <class Tag>
inline impl::response_headers_wrapper<Tag> headers(
    basic_response<Tag> const& response_) {
  return impl::response_headers_wrapper<Tag>(response_);
}

}  // namepace http

}  // namespace network

}  // namespace boost

#endif  // BOOST_NETWORK_PROTOCOL_HTTP_MESSAGE_WRAPPER_HEADERS_HPP_20100811
