use std::fmt;
use Url;
use header::Headers;
use http::{Body, RequestHead};
use method::Method;
use uri::Uri;
use version::HttpVersion;
/// A client request to a remote server.
pub struct Request {
    method: Method,
    url: Url,
    version: HttpVersion,
    headers: Headers,
    body: Option
,
}
impl Request {
    /// Construct a new Request.
    #[inline]
    pub fn new(method: Method, url: Url) -> Request {
        Request {
            method: method,
            url: url,
            version: HttpVersion::default(),
            headers: Headers::new(),
            body: None,
        }
    }
    /// Read the Request Url.
    #[inline]
    pub fn url(&self) -> &Url { &self.url }
    /// Readthe Request Version.
    #[inline]
    pub fn version(&self) -> &HttpVersion { &self.version }
    /// Read the Request headers.
    #[inline]
    pub fn headers(&self) -> &Headers { &self.headers }
    /// Read the Request method.
    #[inline]
    pub fn method(&self) -> &Method { &self.method }
    /// Set the Method of this request.
    #[inline]
    pub fn set_method(&mut self, method: Method) { self.method = method; }
    /// Get a mutable reference to the Request headers.
    #[inline]
    pub fn headers_mut(&mut self) -> &mut Headers { &mut self.headers }
    /// Set the `Url` of this request.
    #[inline]
    pub fn set_url(&mut self, url: Url) { self.url = url; }
    /// Set the `HttpVersion` of this request.
    #[inline]
    pub fn set_version(&mut self, version: HttpVersion) { self.version = version; }
    /// Set the body of the request.
    #[inline]
    pub fn set_body>(&mut self, body: T) { self.body = Some(body.into()); }
}
impl fmt::Debug for Request {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        f.debug_struct("Request")
            .field("method", &self.method)
            .field("url", &self.url)
            .field("version", &self.version)
            .field("headers", &self.headers)
            .finish()
    }
}
pub fn split(req: Request) -> (RequestHead, Option) {
    let uri = Uri::new(&req.url[::url::Position::BeforePath..::url::Position::AfterQuery]).expect("url is uri");
    let head = RequestHead {
        subject: ::http::RequestLine(req.method, uri),
        headers: req.headers,
        version: req.version,
    };
    (head, req.body)
}
#[cfg(test)]
mod tests {
    /*
    use std::io::Write;
    use std::str::from_utf8;
    use url::Url;
    use method::Method::{Get, Head, Post};
    use mock::{MockStream, MockConnector};
    use net::Fresh;
    use header::{ContentLength,TransferEncoding,Encoding};
    use url::form_urlencoded;
    use super::Request;
    use http::h1::Http11Message;
    fn run_request(req: Request) -> Vec {
        let req = req.start().unwrap();
        let message = req.message;
        let mut message = message.downcast::().ok().unwrap();
        message.flush_outgoing().unwrap();
        let stream = *message
            .into_inner().downcast::().ok().unwrap();
        stream.write
    }
    fn assert_no_body(s: &str) {
        assert!(!s.contains("Content-Length:"));
        assert!(!s.contains("Transfer-Encoding:"));
    }
    #[test]
    fn test_get_empty_body() {
        let req = Request::with_connector(
            Get, Url::parse("http://example.dom").unwrap(), &mut MockConnector
        ).unwrap();
        let bytes = run_request(req);
        let s = from_utf8(&bytes[..]).unwrap();
        assert_no_body(s);
    }
    #[test]
    fn test_head_empty_body() {
        let req = Request::with_connector(
            Head, Url::parse("http://example.dom").unwrap(), &mut MockConnector
        ).unwrap();
        let bytes = run_request(req);
        let s = from_utf8(&bytes[..]).unwrap();
        assert_no_body(s);
    }
    #[test]
    fn test_url_query() {
        let url = Url::parse("http://example.dom?q=value").unwrap();
        let req = Request::with_connector(
            Get, url, &mut MockConnector
        ).unwrap();
        let bytes = run_request(req);
        let s = from_utf8(&bytes[..]).unwrap();
        assert!(s.contains("?q=value"));
    }
    #[test]
    fn test_post_content_length() {
        let url = Url::parse("http://example.dom").unwrap();
        let mut req = Request::with_connector(
            Post, url, &mut MockConnector
        ).unwrap();
        let mut body = String::new();
        form_urlencoded::Serializer::new(&mut body).append_pair("q", "value");
        req.headers_mut().set(ContentLength(body.len() as u64));
        let bytes = run_request(req);
        let s = from_utf8(&bytes[..]).unwrap();
        assert!(s.contains("Content-Length:"));
    }
    #[test]
    fn test_post_chunked() {
        let url = Url::parse("http://example.dom").unwrap();
        let req = Request::with_connector(
            Post, url, &mut MockConnector
        ).unwrap();
        let bytes = run_request(req);
        let s = from_utf8(&bytes[..]).unwrap();
        assert!(!s.contains("Content-Length:"));
    }
    #[test]
    fn test_host_header() {
        let url = Url::parse("http://example.dom").unwrap();
        let req = Request::with_connector(
            Get, url, &mut MockConnector
        ).unwrap();
        let bytes = run_request(req);
        let s = from_utf8(&bytes[..]).unwrap();
        assert!(s.contains("Host: example.dom"));
    }
    #[test]
    fn test_proxy() {
        let url = Url::parse("http://example.dom").unwrap();
        let mut req = Request::with_connector(
            Get, url, &mut MockConnector
        ).unwrap();
        req.message.set_proxied(true);
        let bytes = run_request(req);
        let s = from_utf8(&bytes[..]).unwrap();
        let request_line = "GET http://example.dom/ HTTP/1.1";
        assert_eq!(&s[..request_line.len()], request_line);
        assert!(s.contains("Host: example.dom"));
    }
    #[test]
    fn test_post_chunked_with_encoding() {
        let url = Url::parse("http://example.dom").unwrap();
        let mut req = Request::with_connector(
            Post, url, &mut MockConnector
        ).unwrap();
        req.headers_mut().set(TransferEncoding(vec![Encoding::Chunked]));
        let bytes = run_request(req);
        let s = from_utf8(&bytes[..]).unwrap();
        assert!(!s.contains("Content-Length:"));
        assert!(s.contains("Transfer-Encoding:"));
    }
    #[test]
    fn test_write_error_closes() {
        let url = Url::parse("http://hyper.rs").unwrap();
        let req = Request::with_connector(
            Get, url, &mut MockConnector
        ).unwrap();
        let mut req = req.start().unwrap();
        req.message.downcast_mut::().unwrap()
            .get_mut().downcast_mut::().unwrap()
            .error_on_write = true;
        req.write(b"foo").unwrap();
        assert!(req.flush().is_err());
        assert!(req.message.downcast_ref::().unwrap()
            .get_ref().downcast_ref::().unwrap()
            .is_closed);
    }
    */
}