/* This Source Code Form is subject to the terms of the Mozilla Public
 * License, v. 2.0. If a copy of the MPL was not distributed with this
 * file, You can obtain one at https://mozilla.org/MPL/2.0/. */

use std::cell::Cell;
use std::str::{self, FromStr};

use dom_struct::dom_struct;
use http::header::{HeaderMap as HyperHeaders, HeaderName, HeaderValue};
use js::rust::HandleObject;
use net_traits::fetch::headers::{
    extract_mime_type, get_decode_and_split_header_value, get_value_from_header_list,
    is_forbidden_method,
};
use net_traits::request::is_cors_safelisted_request_header;
use net_traits::trim_http_whitespace;

use crate::dom::bindings::cell::DomRefCell;
use crate::dom::bindings::codegen::Bindings::HeadersBinding::{HeadersInit, HeadersMethods};
use crate::dom::bindings::error::{Error, ErrorResult, Fallible};
use crate::dom::bindings::iterable::Iterable;
use crate::dom::bindings::reflector::{Reflector, reflect_dom_object_with_proto};
use crate::dom::bindings::root::DomRoot;
use crate::dom::bindings::str::{ByteString, is_token};
use crate::dom::globalscope::GlobalScope;
use crate::script_runtime::CanGc;

#[dom_struct]
pub(crate) struct Headers {
    reflector_: Reflector,
    guard: Cell<Guard>,
    #[ignore_malloc_size_of = "Defined in hyper"]
    #[no_trace]
    header_list: DomRefCell<HyperHeaders>,
}

/// <https://fetch.spec.whatwg.org/#concept-headers-guard>
#[derive(Clone, Copy, Debug, JSTraceable, MallocSizeOf, PartialEq)]
pub(crate) enum Guard {
    Immutable,
    Request,
    RequestNoCors,
    Response,
    None,
}

impl Headers {
    pub(crate) fn new_inherited() -> Headers {
        Headers {
            reflector_: Reflector::new(),
            guard: Cell::new(Guard::None),
            header_list: DomRefCell::new(HyperHeaders::new()),
        }
    }

    pub(crate) fn new(global: &GlobalScope, can_gc: CanGc) -> DomRoot<Headers> {
        Self::new_with_proto(global, None, can_gc)
    }

    fn new_with_proto(
        global: &GlobalScope,
        proto: Option<HandleObject>,
        can_gc: CanGc,
    ) -> DomRoot<Headers> {
        reflect_dom_object_with_proto(Box::new(Headers::new_inherited()), global, proto, can_gc)
    }
}

impl HeadersMethods<crate::DomTypeHolder> for Headers {
    /// <https://fetch.spec.whatwg.org/#dom-headers>
    fn Constructor(
        global: &GlobalScope,
        proto: Option<HandleObject>,
        can_gc: CanGc,
        init: Option<HeadersInit>,
    ) -> Fallible<DomRoot<Headers>> {
        let dom_headers_new = Headers::new_with_proto(global, proto, can_gc);
        dom_headers_new.fill(init)?;
        Ok(dom_headers_new)
    }

    /// <https://fetch.spec.whatwg.org/#concept-headers-append>
    fn Append(&self, name: ByteString, value: ByteString) -> ErrorResult {
        // 1. Normalize value.
        let value = trim_http_whitespace(&value);

        // 2. If validating (name, value) for headers returns false, then return.
        let Some((mut valid_name, valid_value)) =
            self.validate_name_and_value(name, ByteString::new(value.into()))?
        else {
            return Ok(());
        };

        valid_name = valid_name.to_lowercase();

        // 3. If headers’s guard is "request-no-cors":
        if self.guard.get() == Guard::RequestNoCors {
            // 3.1. Let temporaryValue be the result of getting name from headers’s header list.
            let tmp_value = if let Some(mut value) =
                get_value_from_header_list(&valid_name, &self.header_list.borrow())
            {
                // 3.3. Otherwise, set temporaryValue to temporaryValue, followed by 0x2C 0x20, followed by value.
                value.extend(b", ");
                value.extend(valid_value.to_vec());
                value
            } else {
                // 3.2. If temporaryValue is null, then set temporaryValue to value.
                valid_value.to_vec()
            };
            // 3.4. If (name, temporaryValue) is not a no-CORS-safelisted request-header, then return.
            if !is_cors_safelisted_request_header(&valid_name, &tmp_value) {
                return Ok(());
            }
        }

        // 4. Append (name, value) to headers’s header list.
        match HeaderValue::from_bytes(&valid_value) {
            Ok(value) => {
                self.header_list
                    .borrow_mut()
                    .append(HeaderName::from_str(&valid_name).unwrap(), value);
            },
            Err(_) => {
                // can't add the header, but we don't need to panic the browser over it
                warn!(
                    "Servo thinks \"{:?}\" is a valid HTTP header value but HeaderValue doesn't.",
                    valid_value
                );
            },
        };

        // 5. If headers’s guard is "request-no-cors", then remove privileged no-CORS request-headers from headers.
        if self.guard.get() == Guard::RequestNoCors {
            self.remove_privileged_no_cors_request_headers();
        }

        Ok(())
    }

    /// <https://fetch.spec.whatwg.org/#dom-headers-delete>
    fn Delete(&self, name: ByteString) -> ErrorResult {
        // Step 1 If validating (name, ``) for this returns false, then return.
        let name_and_value = self.validate_name_and_value(name, ByteString::new(vec![]))?;
        let Some((mut valid_name, _valid_value)) = name_and_value else {
            return Ok(());
        };

        valid_name = valid_name.to_lowercase();

        // Step 2 If this’s guard is "request-no-cors", name is not a no-CORS-safelisted request-header name,
        // and name is not a privileged no-CORS request-header name, then return.
        if self.guard.get() == Guard::RequestNoCors &&
            !is_cors_safelisted_request_header(&valid_name, &b"invalid".to_vec())
        {
            return Ok(());
        }

        // 3. If this’s header list does not contain name, then return.
        // 4. Delete name from this’s header list.
        self.header_list.borrow_mut().remove(valid_name);

        // 5. If this’s guard is "request-no-cors", then remove privileged no-CORS request-headers from this.
        if self.guard.get() == Guard::RequestNoCors {
            self.remove_privileged_no_cors_request_headers();
        }

        Ok(())
    }

    /// <https://fetch.spec.whatwg.org/#dom-headers-get>
    fn Get(&self, name: ByteString) -> Fallible<Option<ByteString>> {
        // 1. If name is not a header name, then throw a TypeError.
        let valid_name = validate_name(name)?;

        // 2. Return the result of getting name from this’s header list.
        Ok(
            get_value_from_header_list(&valid_name, &self.header_list.borrow())
                .map(ByteString::new),
        )
    }

    /// <https://fetch.spec.whatwg.org/#dom-headers-getsetcookie>
    fn GetSetCookie(&self) -> Vec<ByteString> {
        // 1. If this’s header list does not contain `Set-Cookie`, then return « ».
        // 2. Return the values of all headers in this’s header list whose name is a
        // byte-case-insensitive match for `Set-Cookie`, in order.
        self.header_list
            .borrow()
            .get_all("set-cookie")
            .iter()
            .map(|v| ByteString::new(v.as_bytes().to_vec()))
            .collect()
    }

    /// <https://fetch.spec.whatwg.org/#dom-headers-has>
    fn Has(&self, name: ByteString) -> Fallible<bool> {
        // 1. If name is not a header name, then throw a TypeError.
        let valid_name = validate_name(name)?;
        // 2. Return true if this’s header list contains name; otherwise false.
        Ok(self.header_list.borrow_mut().get(&valid_name).is_some())
    }

    /// <https://fetch.spec.whatwg.org/#dom-headers-set>
    fn Set(&self, name: ByteString, value: ByteString) -> Fallible<()> {
        // 1. Normalize value
        let value = trim_http_whitespace(&value);

        // 2. If validating (name, value) for this returns false, then return.
        let Some((mut valid_name, valid_value)) =
            self.validate_name_and_value(name, ByteString::new(value.into()))?
        else {
            return Ok(());
        };
        valid_name = valid_name.to_lowercase();

        // 3. If this’s guard is "request-no-cors" and (name, value) is not a
        // no-CORS-safelisted request-header, then return.
        if self.guard.get() == Guard::RequestNoCors &&
            !is_cors_safelisted_request_header(&valid_name, &valid_value.to_vec())
        {
            return Ok(());
        }

        // 4. Set (name, value) in this’s header list.
        // https://fetch.spec.whatwg.org/#concept-header-list-set
        match HeaderValue::from_bytes(&valid_value) {
            Ok(value) => {
                self.header_list
                    .borrow_mut()
                    .insert(HeaderName::from_str(&valid_name).unwrap(), value);
            },
            Err(_) => {
                // can't add the header, but we don't need to panic the browser over it
                warn!(
                    "Servo thinks \"{:?}\" is a valid HTTP header value but HeaderValue doesn't.",
                    valid_value
                );
            },
        };

        // 5. If this’s guard is "request-no-cors", then remove privileged no-CORS request-headers from this.
        if self.guard.get() == Guard::RequestNoCors {
            self.remove_privileged_no_cors_request_headers();
        }

        Ok(())
    }
}

impl Headers {
    pub(crate) fn copy_from_headers(&self, headers: DomRoot<Headers>) -> ErrorResult {
        for (name, value) in headers.header_list.borrow().iter() {
            self.Append(
                ByteString::new(Vec::from(name.as_str())),
                ByteString::new(Vec::from(value.as_bytes())),
            )?;
        }
        Ok(())
    }

    /// <https://fetch.spec.whatwg.org/#concept-headers-fill>
    pub(crate) fn fill(&self, filler: Option<HeadersInit>) -> ErrorResult {
        match filler {
            Some(HeadersInit::ByteStringSequenceSequence(v)) => {
                for mut seq in v {
                    if seq.len() == 2 {
                        let val = seq.pop().unwrap();
                        let name = seq.pop().unwrap();
                        self.Append(name, val)?;
                    } else {
                        return Err(Error::Type(format!(
                            "Each header object must be a sequence of length 2 - found one with length {}",
                            seq.len()
                        )));
                    }
                }
                Ok(())
            },
            Some(HeadersInit::ByteStringByteStringRecord(m)) => {
                for (key, value) in m.iter() {
                    self.Append(key.clone(), value.clone())?;
                }
                Ok(())
            },
            None => Ok(()),
        }
    }

    pub(crate) fn for_request(global: &GlobalScope, can_gc: CanGc) -> DomRoot<Headers> {
        let headers_for_request = Headers::new(global, can_gc);
        headers_for_request.guard.set(Guard::Request);
        headers_for_request
    }

    pub(crate) fn for_response(global: &GlobalScope, can_gc: CanGc) -> DomRoot<Headers> {
        let headers_for_response = Headers::new(global, can_gc);
        headers_for_response.guard.set(Guard::Response);
        headers_for_response
    }

    pub(crate) fn set_guard(&self, new_guard: Guard) {
        self.guard.set(new_guard)
    }

    pub(crate) fn get_guard(&self) -> Guard {
        self.guard.get()
    }

    pub(crate) fn set_headers(&self, hyper_headers: HyperHeaders) {
        *self.header_list.borrow_mut() = hyper_headers;
    }

    pub(crate) fn get_headers_list(&self) -> HyperHeaders {
        self.header_list.borrow_mut().clone()
    }

    /// <https://fetch.spec.whatwg.org/#concept-header-extract-mime-type>
    pub(crate) fn extract_mime_type(&self) -> Vec<u8> {
        extract_mime_type(&self.header_list.borrow()).unwrap_or_default()
    }

    /// <https://fetch.spec.whatwg.org/#concept-header-list-sort-and-combine>
    pub(crate) fn sort_and_combine(&self) -> Vec<(String, Vec<u8>)> {
        let borrowed_header_list = self.header_list.borrow();
        let mut header_vec = vec![];

        for name in borrowed_header_list.keys() {
            let name = name.as_str();
            if name == "set-cookie" {
                for value in borrowed_header_list.get_all(name).iter() {
                    header_vec.push((name.to_owned(), value.as_bytes().to_vec()));
                }
            } else if let Some(value) = get_value_from_header_list(name, &borrowed_header_list) {
                header_vec.push((name.to_owned(), value));
            }
        }

        header_vec.sort_by(|a, b| a.0.cmp(&b.0));
        header_vec
    }

    /// <https://fetch.spec.whatwg.org/#ref-for-privileged-no-cors-request-header-name>
    pub(crate) fn remove_privileged_no_cors_request_headers(&self) {
        // <https://fetch.spec.whatwg.org/#privileged-no-cors-request-header-name>
        self.header_list.borrow_mut().remove("range");
    }

    /// <https://fetch.spec.whatwg.org/#headers-validate>
    pub(crate) fn validate_name_and_value(
        &self,
        name: ByteString,
        value: ByteString,
    ) -> Fallible<Option<(String, ByteString)>> {
        // 1. If name is not a header name or value is not a header value, then throw a TypeError.
        let valid_name = validate_name(name)?;
        if !is_legal_header_value(&value) {
            return Err(Error::Type("Header value is not valid".to_string()));
        }
        // 2. If headers’s guard is "immutable", then throw a TypeError.
        if self.guard.get() == Guard::Immutable {
            return Err(Error::Type("Guard is immutable".to_string()));
        }
        // 3. If headers’s guard is "request" and (name, value) is a forbidden request-header, then return false.
        if self.guard.get() == Guard::Request && is_forbidden_request_header(&valid_name, &value) {
            return Ok(None);
        }
        // 4. If headers’s guard is "response" and name is a forbidden response-header name, then return false.
        if self.guard.get() == Guard::Response && is_forbidden_response_header(&valid_name) {
            return Ok(None);
        }

        Ok(Some((valid_name, value)))
    }
}

impl Iterable for Headers {
    type Key = ByteString;
    type Value = ByteString;

    fn get_iterable_length(&self) -> u32 {
        let sorted_header_vec = self.sort_and_combine();
        sorted_header_vec.len() as u32
    }

    fn get_value_at_index(&self, n: u32) -> ByteString {
        let sorted_header_vec = self.sort_and_combine();
        let value = sorted_header_vec[n as usize].1.clone();
        ByteString::new(value)
    }

    fn get_key_at_index(&self, n: u32) -> ByteString {
        let sorted_header_vec = self.sort_and_combine();
        let key = sorted_header_vec[n as usize].0.clone();
        ByteString::new(key.into_bytes().to_vec())
    }
}

/// This function will internally convert `name` to lowercase for matching, so explicitly converting
/// before calling is not necessary
///
/// <https://fetch.spec.whatwg.org/#forbidden-request-header>
pub(crate) fn is_forbidden_request_header(name: &str, value: &[u8]) -> bool {
    let forbidden_header_names = [
        "accept-charset",
        "accept-encoding",
        "access-control-request-headers",
        "access-control-request-method",
        "connection",
        "content-length",
        "cookie",
        "cookie2",
        "date",
        "dnt",
        "expect",
        "host",
        "keep-alive",
        "origin",
        "referer",
        "set-cookie",
        "te",
        "trailer",
        "transfer-encoding",
        "upgrade",
        "via",
        // This list is defined in the fetch spec, however the draft spec for private-network-access
        // proposes this additional forbidden name, which is currently included in WPT tests. See:
        // https://wicg.github.io/private-network-access/#forbidden-header-names
        "access-control-request-private-network",
    ];

    // Step 1: If name is a byte-case-insensitive match for one of (forbidden_header_names), return
    // true
    let lowercase_name = name.to_lowercase();

    if forbidden_header_names.contains(&lowercase_name.as_str()) {
        return true;
    }

    let forbidden_header_prefixes = ["sec-", "proxy-"];

    // Step 2: If name when byte-lowercased starts with `proxy-` or `sec-`, then return true.
    if forbidden_header_prefixes
        .iter()
        .any(|prefix| lowercase_name.starts_with(prefix))
    {
        return true;
    }

    let potentially_forbidden_header_names = [
        "x-http-method",
        "x-http-method-override",
        "x-method-override",
    ];

    // Step 3: If name is a byte-case-insensitive match for one of (potentially_forbidden_header_names)
    if potentially_forbidden_header_names
        .iter()
        .any(|header| *header == lowercase_name)
    {
        // Step 3.1: Let parsedValues be the result of getting, decoding, and splitting value.
        let parsed_values = get_decode_and_split_header_value(value.to_vec());

        // Step 3.2: For each method of parsedValues: if the isomorphic encoding of method is a
        // forbidden method, then return true.
        return parsed_values
            .iter()
            .any(|s| is_forbidden_method(s.as_bytes()));
    }

    // Step 4: Return false.
    false
}

/// <https://fetch.spec.whatwg.org/#forbidden-response-header-name>
fn is_forbidden_response_header(name: &str) -> bool {
    // A forbidden response-header name is a header name that is a byte-case-insensitive match for one of
    let name = name.to_ascii_lowercase();
    matches!(name.as_str(), "set-cookie" | "set-cookie2")
}

fn validate_name(name: ByteString) -> Fallible<String> {
    if !is_field_name(&name) {
        return Err(Error::Type("Name is not valid".to_string()));
    }
    match String::from_utf8(name.into()) {
        Ok(ns) => Ok(ns),
        _ => Err(Error::Type("Non-UTF8 header name found".to_string())),
    }
}

/// <http://tools.ietf.org/html/rfc7230#section-3.2>
fn is_field_name(name: &ByteString) -> bool {
    is_token(name)
}

// As of December 2019, WHATWG has no formal grammar production for value;
// https://fetch.spec.whatg.org/#concept-header-value just says not to have
// newlines, nulls, or leading/trailing whitespace. It even allows
// octets that aren't a valid UTF-8 encoding, and WPT tests reflect this.
// The HeaderValue class does not fully reflect this, so headers
// containing bytes with values 1..31 or 127 can't be created, failing
// WPT tests but probably not affecting anything important on the real Internet.
/// <https://fetch.spec.whatg.org/#concept-header-value>
fn is_legal_header_value(value: &[u8]) -> bool {
    let value_len = value.len();
    if value_len == 0 {
        return true;
    }
    match value[0] {
        b' ' | b'\t' => return false,
        _ => {},
    };
    match value[value_len - 1] {
        b' ' | b'\t' => return false,
        _ => {},
    };
    for &ch in value {
        match ch {
            b'\0' | b'\n' | b'\r' => return false,
            _ => {},
        }
    }
    true
    // If accepting non-UTF8 header values causes breakage,
    // removing the above "true" and uncommenting the below code
    // would ameliorate it while still accepting most reasonable headers:
    // match str::from_utf8(value) {
    //    Ok(_) => true,
    //    Err(_) => {
    //        warn!(
    //            "Rejecting spec-legal but non-UTF8 header value: {:?}",
    //            value
    //        );
    //        false
    //    },
    // }
}

/// <https://tools.ietf.org/html/rfc5234#appendix-B.1>
pub(crate) fn is_vchar(x: u8) -> bool {
    matches!(x, 0x21..=0x7E)
}

/// <http://tools.ietf.org/html/rfc7230#section-3.2.6>
pub(crate) fn is_obs_text(x: u8) -> bool {
    matches!(x, 0x80..=0xFF)
}
