// Copyright 2021 Google LLC
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//      http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
//
////////////////////////////////////////////////////////////////////////////////

//! COSE Headers functionality.

use crate::{
    cbor::value::Value,
    common::AsCborValue,
    iana,
    iana::EnumI64,
    util::{cbor_type_error, to_cbor_array, ValueTryAs},
    Algorithm, CborSerializable, CoseError, CoseSignature, Label, RegisteredLabel, Result,
};
use alloc::{collections::BTreeSet, string::String, vec, vec::Vec};

#[cfg(test)]
mod tests;

/// Content type.
pub type ContentType = crate::RegisteredLabel<iana::CoapContentFormat>;

/// Structure representing a common COSE header map.
///
/// ```cddl
///   header_map = {
///       Generic_Headers,
///       * label => values
///   }
///
///   Generic_Headers = (
///       ? 1 => int / tstr,  ; algorithm identifier
///       ? 2 => [+label],    ; criticality
///       ? 3 => tstr / int,  ; content type
///       ? 4 => bstr,        ; key identifier
///       ? 5 => bstr,        ; IV
///       ? 6 => bstr,        ; Partial IV
///       ? 7 => COSE_Signature / [+COSE_Signature] ; Counter signature
///   )
///  ```
#[derive(Clone, Debug, Default, PartialEq)]
pub struct Header {
    /// Cryptographic algorithm to use
    pub alg: Option<Algorithm>,
    /// Critical headers to be understood
    pub crit: Vec<RegisteredLabel<iana::HeaderParameter>>,
    /// Content type of the payload
    pub content_type: Option<ContentType>,
    /// Key identifier.
    pub key_id: Vec<u8>,
    /// Full initialization vector
    pub iv: Vec<u8>,
    /// Partial initialization vector
    pub partial_iv: Vec<u8>,
    /// Counter signature
    pub counter_signatures: Vec<CoseSignature>,
    /// Any additional header (label,value) pairs.  If duplicate labels are present, CBOR-encoding
    /// will fail.
    pub rest: Vec<(Label, Value)>,
}

impl Header {
    /// Indicate whether the `Header` is empty.
    pub fn is_empty(&self) -> bool {
        self.alg.is_none()
            && self.crit.is_empty()
            && self.content_type.is_none()
            && self.key_id.is_empty()
            && self.iv.is_empty()
            && self.partial_iv.is_empty()
            && self.counter_signatures.is_empty()
            && self.rest.is_empty()
    }
}

impl crate::CborSerializable for Header {}

const ALG: Label = Label::Int(iana::HeaderParameter::Alg as i64);
const CRIT: Label = Label::Int(iana::HeaderParameter::Crit as i64);
const CONTENT_TYPE: Label = Label::Int(iana::HeaderParameter::ContentType as i64);
const KID: Label = Label::Int(iana::HeaderParameter::Kid as i64);
const IV: Label = Label::Int(iana::HeaderParameter::Iv as i64);
const PARTIAL_IV: Label = Label::Int(iana::HeaderParameter::PartialIv as i64);
const COUNTER_SIG: Label = Label::Int(iana::HeaderParameter::CounterSignature as i64);

impl AsCborValue for Header {
    fn from_cbor_value(value: Value) -> Result<Self> {
        let m = value.try_as_map()?;
        let mut headers = Self::default();
        let mut seen = BTreeSet::new();
        for (l, value) in m.into_iter() {
            // The `ciborium` CBOR library does not police duplicate map keys.
            // RFC 8152 section 14 requires that COSE does police duplicates, so do it here.
            let label = Label::from_cbor_value(l)?;
            if seen.contains(&label) {
                return Err(CoseError::DuplicateMapKey);
            }
            seen.insert(label.clone());
            match label {
                ALG => headers.alg = Some(Algorithm::from_cbor_value(value)?),

                CRIT => match value {
                    Value::Array(a) => {
                        if a.is_empty() {
                            return Err(CoseError::UnexpectedItem(
                                "empty array",
                                "non-empty array",
                            ));
                        }
                        for v in a {
                            headers.crit.push(
                                RegisteredLabel::<iana::HeaderParameter>::from_cbor_value(v)?,
                            );
                        }
                    }
                    v => return cbor_type_error(&v, "array value"),
                },

                CONTENT_TYPE => {
                    headers.content_type = Some(ContentType::from_cbor_value(value)?);
                    if let Some(ContentType::Text(text)) = &headers.content_type {
                        if text.is_empty() {
                            return Err(CoseError::UnexpectedItem("empty tstr", "non-empty tstr"));
                        }
                        if text.trim() != text {
                            return Err(CoseError::UnexpectedItem(
                                "leading/trailing whitespace",
                                "no leading/trailing whitespace",
                            ));
                        }
                        // Basic check that the content type is of form type/subtype.
                        // We don't check the precise definition though (RFC 6838 s4.2)
                        if text.matches('/').count() != 1 {
                            return Err(CoseError::UnexpectedItem(
                                "arbitrary text",
                                "text of form type/subtype",
                            ));
                        }
                    }
                }

                KID => {
                    headers.key_id = value.try_as_nonempty_bytes()?;
                }

                IV => {
                    headers.iv = value.try_as_nonempty_bytes()?;
                }

                PARTIAL_IV => {
                    headers.partial_iv = value.try_as_nonempty_bytes()?;
                }
                COUNTER_SIG => {
                    let sig_or_sigs = value.try_as_array()?;
                    if sig_or_sigs.is_empty() {
                        return Err(CoseError::UnexpectedItem(
                            "empty sig array",
                            "non-empty sig array",
                        ));
                    }
                    // The encoding of counter signature[s] is pesky:
                    // - a single counter signature is encoded as `COSE_Signature` (a 3-tuple)
                    // - multiple counter signatures are encoded as `[+ COSE_Signature]`
                    //
                    // Determine which is which by looking at the first entry of the array:
                    // - If it's a bstr, sig_or_sigs is a single signature.
                    // - If it's an array, sig_or_sigs is an array of signatures
                    match &sig_or_sigs[0] {
                        Value::Bytes(_) => headers
                            .counter_signatures
                            .push(CoseSignature::from_cbor_value(Value::Array(sig_or_sigs))?),
                        Value::Array(_) => {
                            for sig in sig_or_sigs.into_iter() {
                                headers
                                    .counter_signatures
                                    .push(CoseSignature::from_cbor_value(sig)?);
                            }
                        }
                        v => return cbor_type_error(v, "array or bstr value"),
                    }
                }

                label => headers.rest.push((label, value)),
            }
            // RFC 8152 section 3.1: "The 'Initialization Vector' and 'Partial Initialization
            // Vector' parameters MUST NOT both be present in the same security layer."
            if !headers.iv.is_empty() && !headers.partial_iv.is_empty() {
                return Err(CoseError::UnexpectedItem(
                    "IV and partial-IV specified",
                    "only one of IV and partial IV",
                ));
            }
        }
        Ok(headers)
    }

    fn to_cbor_value(mut self) -> Result<Value> {
        let mut map = Vec::<(Value, Value)>::new();
        if let Some(alg) = self.alg {
            map.push((ALG.to_cbor_value()?, alg.to_cbor_value()?));
        }
        if !self.crit.is_empty() {
            map.push((CRIT.to_cbor_value()?, to_cbor_array(self.crit)?));
        }
        if let Some(content_type) = self.content_type {
            map.push((CONTENT_TYPE.to_cbor_value()?, content_type.to_cbor_value()?));
        }
        if !self.key_id.is_empty() {
            map.push((KID.to_cbor_value()?, Value::Bytes(self.key_id)));
        }
        if !self.iv.is_empty() {
            map.push((IV.to_cbor_value()?, Value::Bytes(self.iv)));
        }
        if !self.partial_iv.is_empty() {
            map.push((PARTIAL_IV.to_cbor_value()?, Value::Bytes(self.partial_iv)));
        }
        if !self.counter_signatures.is_empty() {
            if self.counter_signatures.len() == 1 {
                // A single counter signature is encoded differently.
                map.push((
                    COUNTER_SIG.to_cbor_value()?,
                    self.counter_signatures.remove(0).to_cbor_value()?,
                ));
            } else {
                map.push((
                    COUNTER_SIG.to_cbor_value()?,
                    to_cbor_array(self.counter_signatures)?,
                ));
            }
        }
        let mut seen = BTreeSet::new();
        for (label, value) in self.rest.into_iter() {
            if seen.contains(&label) {
                return Err(CoseError::DuplicateMapKey);
            }
            seen.insert(label.clone());
            map.push((label.to_cbor_value()?, value));
        }
        Ok(Value::Map(map))
    }
}

/// Builder for [`Header`] objects.
#[derive(Debug, Default)]
pub struct HeaderBuilder(Header);

impl HeaderBuilder {
    builder! {Header}
    builder_set! {key_id: Vec<u8>}

    /// Set the algorithm.
    #[must_use]
    pub fn algorithm(mut self, alg: iana::Algorithm) -> Self {
        self.0.alg = Some(Algorithm::Assigned(alg));
        self
    }

    /// Add a critical header.
    #[must_use]
    pub fn add_critical(mut self, param: iana::HeaderParameter) -> Self {
        self.0.crit.push(RegisteredLabel::Assigned(param));
        self
    }

    /// Add a critical header.
    #[must_use]
    pub fn add_critical_label(mut self, label: RegisteredLabel<iana::HeaderParameter>) -> Self {
        self.0.crit.push(label);
        self
    }

    /// Set the content type to a numeric value.
    #[must_use]
    pub fn content_format(mut self, content_type: iana::CoapContentFormat) -> Self {
        self.0.content_type = Some(ContentType::Assigned(content_type));
        self
    }

    /// Set the content type to a text value.
    #[must_use]
    pub fn content_type(mut self, content_type: String) -> Self {
        self.0.content_type = Some(ContentType::Text(content_type));
        self
    }

    /// Set the IV, and clear any partial IV already set.
    #[must_use]
    pub fn iv(mut self, iv: Vec<u8>) -> Self {
        self.0.iv = iv;
        self.0.partial_iv.clear();
        self
    }

    /// Set the partial IV, and clear any IV already set.
    #[must_use]
    pub fn partial_iv(mut self, iv: Vec<u8>) -> Self {
        self.0.partial_iv = iv;
        self.0.iv.clear();
        self
    }

    /// Add a counter signature.
    #[must_use]
    pub fn add_counter_signature(mut self, sig: CoseSignature) -> Self {
        self.0.counter_signatures.push(sig);
        self
    }

    /// Set a header label:value pair. If duplicate labels are added to a [`Header`],
    /// subsequent attempts to CBOR-encode the header will fail.
    ///
    /// # Panics
    ///
    /// This function will panic if it used to set a header label from the range [1, 6].
    #[must_use]
    pub fn value(mut self, label: i64, value: Value) -> Self {
        if label >= iana::HeaderParameter::Alg.to_i64()
            && label <= iana::HeaderParameter::CounterSignature.to_i64()
        {
            panic!("value() method used to set core header parameter"); // safe: invalid input
        }
        self.0.rest.push((Label::Int(label), value));
        self
    }

    /// Set a header label:value pair where the `label` is text.
    #[must_use]
    pub fn text_value(mut self, label: String, value: Value) -> Self {
        self.0.rest.push((Label::Text(label), value));
        self
    }
}

/// Structure representing a protected COSE header map.
#[derive(Clone, Debug, Default, PartialEq)]
pub struct ProtectedHeader {
    /// If this structure was created by parsing serialized data, this field
    /// holds the entire contents of the original `bstr` data.
    pub original_data: Option<Vec<u8>>,
    /// Parsed header information.
    pub header: Header,
}

impl ProtectedHeader {
    /// Constructor from a [`Value`] that holds a `bstr` encoded header.
    #[inline]
    pub fn from_cbor_bstr(val: Value) -> Result<Self> {
        let data = val.try_as_bytes()?;
        let header = if data.is_empty() {
            // An empty bstr is used as a short cut for an empty header map.
            Header::default()
        } else {
            Header::from_slice(&data)?
        };
        Ok(ProtectedHeader {
            original_data: Some(data),
            header,
        })
    }

    /// Convert this header to a `bstr` encoded map, as a [`Value`], consuming the object along the
    /// way.
    #[inline]
    pub fn cbor_bstr(self) -> Result<Value> {
        Ok(Value::Bytes(
            if let Some(original_data) = self.original_data {
                original_data
            } else if self.is_empty() {
                vec![]
            } else {
                self.to_vec()?
            },
        ))
    }

    /// Indicate whether the `ProtectedHeader` is empty.
    pub fn is_empty(&self) -> bool {
        self.header.is_empty()
    }
}

impl crate::CborSerializable for ProtectedHeader {}

impl AsCborValue for ProtectedHeader {
    fn from_cbor_value(value: Value) -> Result<Self> {
        Ok(ProtectedHeader {
            original_data: None,
            header: Header::from_cbor_value(value)?,
        })
    }

    fn to_cbor_value(self) -> Result<Value> {
        self.header.to_cbor_value()
    }
}
