#ifndef BOOST_NETWORK_PROTOCOL_HTTP_MESSAGE_DIRECTIVES_STATUS_HPP_20100603
#define BOOST_NETWORK_PROTOCOL_HTTP_MESSAGE_DIRECTIVES_STATUS_HPP_20100603

// Copyright 2010 (c) Dean Michael Berris
// Copyright 2010 (c) Sinefunc, Inc.
// 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/tags.hpp>
#include <boost/network/support/is_async.hpp>
#include <boost/thread/future.hpp>
#include <boost/mpl/if.hpp>
#include <boost/variant/variant.hpp>
#include <boost/variant/static_visitor.hpp>
#include <boost/variant/apply_visitor.hpp>
#include <boost/cstdint.hpp>

namespace boost { namespace network { namespace http {

    template <class Tag>
    struct basic_response;
    
    struct status_directive {

        boost::variant<
            boost::uint16_t,
            boost::shared_future<boost::uint16_t>
        > status_;

        explicit status_directive(boost::uint16_t status)
            : status_(status) {}

        explicit status_directive(boost::shared_future<boost::uint16_t> const & status)
            : status_(status) {}

        status_directive(status_directive const & other)
            : status_(other.status_) {}

        template <class Tag>
        struct value
            : mpl::if_<
                is_async<Tag>,
                boost::shared_future<boost::uint16_t>,
                boost::uint16_t
            >
        {};

        template <class Tag>
        struct status_visitor : boost::static_visitor<> {
            basic_response<Tag> const & response;
            status_visitor(basic_response<Tag> const & response)
                : response(response) {}

            void operator()(typename value<Tag>::type const & status_) const {
                response.status(status_);
            }

            template <class T>
            void operator()(T const &) const {
                // FIXME fail here!
            }
        };

        template <class Tag> basic_response<Tag> const & operator() (basic_response<Tag> const & response) const {
            apply_visitor(status_visitor<Tag>(response), status_);
            return response;
        }

    };

    template <class T>
    inline status_directive const status(T const & status_) {
        return status_directive(status_);
    }

} // namespace http

} // namespace network

} // namespace boost

#endif // BOOST_NETWORK_PROTOCOL_HTTP_MESSAGE_DIRECTIVES_STATUS_HPP_20100603
