// Copyright 2020 The Chromium OS Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

use std::collections::HashMap;
use std::fmt;
use std::io::{self, BufRead, BufReader, BufWriter, Cursor, Read, Write};
use std::num::ParseIntError;
use std::str::FromStr;

use sys_util::{debug, error};
use tiny_http::{Header, Method};

use crate::io_adapters::{ChunkedWriter, CompleteReader, LoggingReader};
use crate::usb_connector::UsbConnection;
use crate::util::read_until_delimiter;

// Minimum Request body size, in bytes, before we switch to forwarding requests
// using a chunked Transfer-Encoding.
const CHUNKED_THRESHOLD: usize = 1 << 15;
const VERSION: Option<&'static str> = option_env!("CARGO_PKG_VERSION");

#[derive(Debug)]
pub enum Error {
    DuplicateBodyReader,
    EmptyField(String),
    ForwardRequestBody(io::Error),
    MalformedRequest,
    MalformedContentLength(String, ParseIntError),
    ParseResponse(httparse::Error),
    ReadResponseHeader(io::Error),
    WriteRequestHeader(io::Error),
    WriteResponse(io::Error),
}

impl std::error::Error for Error {}

impl fmt::Display for Error {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        use Error::*;
        match self {
            DuplicateBodyReader => write!(f, "Attempted to call body_reader() multiple times."),
            EmptyField(field) => write!(f, "HTTP Response field {} was unexpectedly empty", field),
            ForwardRequestBody(err) => write!(f, "Forwarding request body failed: {}", err),
            MalformedRequest => write!(f, "HTTP request is malformed"),
            MalformedContentLength(value, err) => write!(
                f,
                "Failed to parse response Content-Length '{}': {}",
                value, err
            ),
            ParseResponse(err) => write!(f, "Failed to parse HTTP Response header: {}", err),
            ReadResponseHeader(err) => write!(f, "Reading response header failed: {}", err),
            WriteRequestHeader(err) => write!(f, "Writing request header failed: {}", err),
            WriteResponse(err) => write!(f, "Responding to request failed: {}", err),
        }
    }
}

type Result<T> = std::result::Result<T, Error>;

#[derive(Copy, Clone, PartialEq)]
enum BodyLength {
    Chunked,
    Exactly(usize),
}

struct ResponseReader<R: BufRead + Sized> {
    verbose_log: bool,
    reader: R,
    body_length: BodyLength,
    header_was_read: bool,
    created_body_reader: bool,
}

impl<R> ResponseReader<R>
where
    R: BufRead + Sized,
{
    fn new(verbose_log: bool, reader: R) -> ResponseReader<R> {
        ResponseReader {
            verbose_log,
            reader,
            // Assume body is empty unless we see a header to the contrary.
            body_length: BodyLength::Exactly(0),
            header_was_read: false,
            created_body_reader: false,
        }
    }

    fn read_header(&mut self) -> Result<(tiny_http::StatusCode, Vec<Header>)> {
        self.header_was_read = true;

        let buf = read_until_delimiter(&mut self.reader, b"\r\n\r\n")
            .map_err(Error::ReadResponseHeader)?;
        let mut headers = [httparse::EMPTY_HEADER; 32];
        let mut response = httparse::Response::new(&mut headers);
        let (status, headers) = match response.parse(&buf).map_err(Error::ParseResponse)? {
            httparse::Status::Complete(i) if i == buf.len() => {
                let code = response
                    .code
                    .ok_or_else(|| Error::EmptyField("code".to_owned()))?;
                let status = tiny_http::StatusCode::from(code);
                let version = response
                    .version
                    .ok_or_else(|| Error::EmptyField("version".to_owned()))?;
                debug!(
                    "> HTTP/1.{} {} {}",
                    version,
                    code,
                    status.default_reason_phrase()
                );
                let mut parsed_headers = Vec::new();
                for header in headers.iter().take_while(|&&h| h != httparse::EMPTY_HEADER) {
                    if let Ok(h) = Header::from_bytes(header.name, header.value) {
                        if self.verbose_log {
                            debug!("  {}: {}", h.field, h.value);
                        }
                        parsed_headers.push(h);
                    } else {
                        error!(
                            "Ignoring malformed header {}:{:#?}",
                            header.name, header.value
                        );
                    }
                }
                (status, parsed_headers)
            }
            _ => return Err(Error::MalformedRequest),
        };

        // Determine the size of the body content.
        for header in headers.iter() {
            if header.field.equiv("Content-Length") {
                let length = usize::from_str(header.value.as_str()).map_err(|e| {
                    Error::MalformedContentLength(header.value.as_str().to_string(), e)
                })?;
                self.body_length = BodyLength::Exactly(length);
                break;
            }

            if header.field.equiv("Transfer-Encoding") {
                self.body_length = BodyLength::Chunked;
                break;
            }
        }

        Ok((status, headers))
    }

    fn body_reader<'r>(&'r mut self) -> Result<Box<dyn Read + 'r>> {
        if self.created_body_reader {
            return Err(Error::DuplicateBodyReader);
        }

        self.created_body_reader = true;
        match self.body_length {
            BodyLength::Exactly(length) => {
                let reader = (&mut self.reader).take(length as u64);
                Ok(Box::new(CompleteReader::new(reader)))
            }
            BodyLength::Chunked => {
                let reader = chunked_transfer::Decoder::new(&mut self.reader);
                Ok(Box::new(CompleteReader::new(reader)))
            }
        }
    }
}

impl<R> Drop for ResponseReader<R>
where
    R: BufRead,
{
    fn drop(&mut self) {
        if !self.created_body_reader {
            debug!("Draining in drop");
            if !self.header_was_read {
                // Read header to figure out how long the body is.
                let _ = self.read_header();
            }

            // Create a body reader which will totally read the response on drop.
            let _ = self.body_reader();
        }
    }
}

fn is_end_to_end(header: &Header) -> bool {
    !matches!(
        header.field.as_str().as_str(),
        "Connection"
        | "Expect" // Technically end-to-end, but we want to filter it.
        | "Keep-Alive"
        | "Proxy-Authenticate"
        | "Proxy-Authorization"
        | "TE"
        | "Trailers"
        | "Transfer-Encoding"
        | "Upgrade"
    )
}

fn supports_request_body(method: &Method) -> bool {
    !matches!(
        method,
        Method::Get | Method::Head | Method::Delete | Method::Options | Method::Trace
    )
}

#[derive(Eq)]
struct HeaderField {
    value: String,
}

impl HeaderField {
    fn new(value: &str) -> Self {
        Self {
            value: value.to_string(),
        }
    }
}

impl std::cmp::PartialEq for HeaderField {
    fn eq(&self, other: &Self) -> bool {
        self.value.eq_ignore_ascii_case(&other.value)
    }
}

impl std::hash::Hash for HeaderField {
    fn hash<H: std::hash::Hasher>(&self, state: &mut H) {
        self.value.to_ascii_lowercase().hash(state);
    }
}

impl fmt::Display for HeaderField {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        write!(f, "{}", self.value)
    }
}

struct Headers {
    values: HashMap<HeaderField, Vec<String>>,
}

impl Headers {
    pub fn new() -> Self {
        Headers {
            values: HashMap::new(),
        }
    }

    pub fn delete_header(&mut self, k: &str) -> Option<Vec<String>> {
        self.values.remove(&HeaderField::new(k))
    }

    pub fn add_header(&mut self, k: &str, v: &str) {
        self.values
            .entry(HeaderField::new(k))
            .or_default()
            .push(v.to_string());
    }

    pub fn has_header(&self, k: &str) -> bool {
        self.values.contains_key(&HeaderField::new(k))
    }
}

struct Request {
    method: String,
    url: String,
    headers: Headers,
    body_length: BodyLength,
    forwarded_body_length: BodyLength,
}

// Converts a tiny_http::Request into our internal Request format.
// Filter out Hop-by-hop headers and add Content-Length or Transfer-Encoding
// headers as needed.
fn rewrite_request(request: &tiny_http::Request) -> Request {
    let mut headers = Headers::new();
    // If the incoming request specifies a Transfer-Encoding, it must be chunked.
    let request_is_chunked = request
        .headers()
        .iter()
        .any(|h| h.field.equiv("Transfer-Encoding"));

    for header in request.headers().iter().filter(|&h| is_end_to_end(h)) {
        // Call as_str() twice for conversion from header name to &AsciiStr to &str.
        headers.add_header(header.field.as_str().as_str(), header.value.as_str());
    }

    let body_length = if !supports_request_body(request.method()) {
        BodyLength::Exactly(0)
    } else if request_is_chunked {
        BodyLength::Chunked
    } else if let Some(length) = request.body_length() {
        BodyLength::Exactly(length)
    } else {
        BodyLength::Exactly(0)
    };

    headers.delete_header("User-Agent");
    let user_agent = format!("ippusb_bridge/{}", VERSION.unwrap_or("unknown"));
    headers.add_header("User-Agent", &user_agent);

    // If the request body is relatively small, don't use a chunked encoding for
    // the proxied request.
    let forwarded_body_length = match body_length {
        BodyLength::Exactly(length) if length < CHUNKED_THRESHOLD => body_length,
        _ => BodyLength::Chunked,
    };

    if forwarded_body_length == BodyLength::Chunked {
        // Content-Length and chunked encoding are mutually exclusive.
        // We don't need to delete any existing Transfer-Encoding since it's a
        // Hop-by-hop header and is already filtered out above.
        headers.delete_header("Content-Length");
        headers.add_header("Transfer-Encoding", "chunked");
    } else if !headers.has_header("Content-Length") {
        headers.add_header("Content-Length", "0");
    }

    Request {
        method: request.method().to_string(),
        url: request.url().to_string(),
        headers,
        body_length,
        forwarded_body_length,
    }
}

fn serialize_request_header(
    verbose_log: bool,
    request: &Request,
    writer: &mut dyn Write,
) -> io::Result<()> {
    write!(writer, "{} {} HTTP/1.1\r\n", request.method, request.url)?;
    if verbose_log {
        debug!("{} {} HTTP/1.1\\r\n", request.method, request.url);
    }
    for (field, values) in request.headers.values.iter() {
        for value in values.iter() {
            write!(writer, "{}: {}\r\n", field, value)?;
            if verbose_log {
                debug!("  {}: {}\\r", field, value);
            }
        }
    }

    write!(writer, "\r\n")?;
    if verbose_log {
        debug!("\\r");
    }
    writer.flush()
}

pub fn handle_request(
    verbose_log: bool,
    usb: UsbConnection,
    mut request: tiny_http::Request,
) -> Result<()> {
    debug!(
        "< {} {} HTTP/1.{}",
        request.method(),
        request.url(),
        request.http_version().1
    );

    // Filter out headers that should not be forwarded, and update Content-Length and
    // Transfer-Encoding headers based on how the body (if any) will be transferred.
    let new_request = rewrite_request(&request);

    let mut logging_reader = LoggingReader::new(request.as_reader(), "client");
    let mut request_body: Box<dyn Read> = match new_request.forwarded_body_length {
        BodyLength::Exactly(length) => {
            // If we're not using chunked, we must have the entire request body before beginning to
            // forward the request. If we didn't and the client were to drop in the middle of
            // forwarding a request, we would have no way of cleanly terminating the connection.
            let mut buf = Vec::with_capacity(length);
            io::copy(&mut logging_reader, &mut buf).map_err(Error::ForwardRequestBody)?;
            Box::new(Cursor::new(buf))
        }
        _ => Box::new(logging_reader),
    };

    let mut usb_writer = BufWriter::new(&usb);
    // Write the modified request header to the printer.
    serialize_request_header(verbose_log, &new_request, &mut usb_writer)
        .map_err(Error::WriteRequestHeader)?;

    // Now that we have written data to the printer, we must ensure that we read
    // a complete HTTP response from the printer. Otherwise, that data may
    // remain in the printer's buffers and be sent to some other client.
    // ResponseReader ensures that this happens internally.
    let usb_reader = BufReader::new(LoggingReader::new(&usb, "printer"));
    let mut response_reader = ResponseReader::new(verbose_log, usb_reader);

    if new_request.body_length != BodyLength::Exactly(0) {
        debug!("* Forwarding client request body");
        let mut writer: Box<dyn Write> = match new_request.forwarded_body_length {
            BodyLength::Chunked => Box::new(ChunkedWriter::new(usb_writer)),
            _ => Box::new(usb_writer),
        };
        io::copy(&mut request_body, &mut writer).map_err(Error::ForwardRequestBody)?;
        writer.flush().map_err(Error::ForwardRequestBody)?;
    }
    drop(request_body);

    debug!("* Reading printer response header");
    let (status, headers) = response_reader.read_header()?;

    debug!("* Forwarding printer response body");
    let body_reader = response_reader.body_reader()?;
    let response = tiny_http::Response::new(status, headers, body_reader, None, None);
    request.respond(response).map_err(Error::WriteResponse)?;

    debug!("* Finished processing request");
    Ok(())
}
