use crate::rust::prelude::*;
use crate::traversal::*;
use crate::*;
pub struct RawPayload<'a, E: CustomExtension> {
    full_payload: Cow<'a, [u8]>,
    root_value_kind: ValueKind<E::CustomValueKind>,
    custom_extension: PhantomData<E>,
}
impl<'a, E: CustomExtension> RawPayload<'a, E> {
                            pub fn new_from_valid_slice(payload_bytes: &'a [u8]) -> Self {
        Self {
            full_payload: Cow::Borrowed(payload_bytes),
            root_value_kind: ValueKind::<E::CustomValueKind>::from_u8(payload_bytes[1]).unwrap(),
            custom_extension: PhantomData,
        }
    }
                                pub fn new_from_valid_slice_with_checks(payload_bytes: &'a [u8]) -> Option<Self> {
        if payload_bytes.len() < 2 || payload_bytes[0] != E::PAYLOAD_PREFIX {
            return None;
        }
        let Some(value_kind) = ValueKind::<E::CustomValueKind>::from_u8(payload_bytes[1]) else {
            return None;
        };
        Some(Self {
            full_payload: Cow::Borrowed(payload_bytes),
            root_value_kind: value_kind,
            custom_extension: PhantomData,
        })
    }
                            pub fn new_from_valid_owned(payload_bytes: Vec<u8>) -> Self {
        let root_value_kind = ValueKind::<E::CustomValueKind>::from_u8(payload_bytes[1]).unwrap();
        Self {
            full_payload: Cow::Owned(payload_bytes),
            root_value_kind,
            custom_extension: PhantomData,
        }
    }
                                pub fn new_from_valid_owned_with_checks(payload_bytes: Vec<u8>) -> Option<Self> {
        if payload_bytes.len() < 2 || payload_bytes[0] != E::PAYLOAD_PREFIX {
            return None;
        }
        let Some(value_kind) = ValueKind::<E::CustomValueKind>::from_u8(payload_bytes[1]) else {
            return None;
        };
        Some(Self {
            full_payload: Cow::Owned(payload_bytes),
            root_value_kind: value_kind,
            custom_extension: PhantomData,
        })
    }
    pub fn as_encoded_value<'b>(&'b self) -> RawValue<'b, E> {
        RawValue::new_from_valid_value_body_slice(
            self.root_value_kind,
            self.encoded_root_body_bytes(),
        )
    }
    pub fn decode_into<
        T: for<'b> Decode<E::CustomValueKind, VecDecoder<'b, E::CustomValueKind>>,
    >(
        &self,
        depth_limit: usize,
    ) -> Result<T, DecodeError> {
        let mut decoder = VecDecoder::new(self.encoded_root_body_bytes(), depth_limit);
        T::decode_body_with_value_kind(&mut decoder, self.root_value_kind)
    }
    pub fn root_value_kind(&self) -> ValueKind<E::CustomValueKind> {
        self.root_value_kind
    }
    pub fn payload_bytes(&self) -> &[u8] {
        &self.full_payload
    }
    pub fn encoded_root_value_bytes(&self) -> &[u8] {
        &self.full_payload[1..]
    }
    pub fn encoded_root_body_bytes(&self) -> &[u8] {
        &self.full_payload[2..]
    }
}
impl<'a, E: CustomExtension> TryFrom<&'a [u8]> for RawPayload<'a, E> {
    type Error = ();
    fn try_from(value: &'a [u8]) -> Result<Self, Self::Error> {
        RawPayload::new_from_valid_slice_with_checks(value).ok_or(())
    }
}
impl<Ext: CustomExtension, E: Encoder<Ext::CustomValueKind>> Encode<Ext::CustomValueKind, E>
    for RawPayload<'_, Ext>
{
    fn encode_value_kind(&self, encoder: &mut E) -> Result<(), EncodeError> {
        encoder.write_value_kind(self.root_value_kind)
    }
    fn encode_body(&self, encoder: &mut E) -> Result<(), EncodeError> {
        encoder.write_slice(self.encoded_root_body_bytes())
    }
}
#[derive(Debug, Clone)]
pub struct RawValue<'a, E: CustomExtension> {
    value_kind: ValueKind<E::CustomValueKind>,
    value_body: Cow<'a, [u8]>,
    custom_extension: PhantomData<E>,
}
impl<'a, E: CustomExtension> RawValue<'a, E> {
                pub fn new_from_valid_full_value_slice(encoded_full_value: &'a [u8]) -> Self {
        let value_kind = ValueKind::from_u8(encoded_full_value[0]).unwrap();
        Self {
            value_kind,
            value_body: Cow::Borrowed(&encoded_full_value[1..]),
            custom_extension: PhantomData,
        }
    }
        pub fn new_from_valid_value_body_slice(
        value_kind: ValueKind<E::CustomValueKind>,
        encoded_value_body: &'a [u8],
    ) -> Self {
        Self {
            value_kind,
            value_body: Cow::Borrowed(encoded_value_body),
            custom_extension: PhantomData,
        }
    }
        pub fn new_from_valid_owned_value_body(
        value_kind: ValueKind<E::CustomValueKind>,
        encoded_value_body: Vec<u8>,
    ) -> Self {
        Self {
            value_kind,
            value_body: Cow::Owned(encoded_value_body),
            custom_extension: PhantomData,
        }
    }
    pub fn value_kind(&self) -> ValueKind<E::CustomValueKind> {
        self.value_kind
    }
    pub fn value_body_bytes(&self) -> &[u8] {
        &self.value_body
    }
}
impl<Ext: CustomExtension, E: Encoder<Ext::CustomValueKind>> Encode<Ext::CustomValueKind, E>
    for RawValue<'_, Ext>
{
    fn encode_value_kind(&self, encoder: &mut E) -> Result<(), EncodeError> {
        encoder.write_value_kind(self.value_kind)
    }
    fn encode_body(&self, encoder: &mut E) -> Result<(), EncodeError> {
        encoder.write_slice(self.value_body.as_ref())
    }
}
impl<Ext: CustomExtension, D: Decoder<Ext::CustomValueKind>> Decode<Ext::CustomValueKind, D>
    for RawValue<'_, Ext>
{
    fn decode_body_with_value_kind(
        decoder: &mut D,
        value_kind: ValueKind<Ext::CustomValueKind>,
    ) -> Result<Self, DecodeError> {
                        let length = calculate_value_tree_body_byte_length::<Ext>(
            decoder.peek_remaining(),
            value_kind,
            decoder.get_stack_depth(),
            decoder.get_depth_limit(),
        )?;
                Ok(Self::new_from_valid_owned_value_body(
            value_kind,
            decoder.read_slice(length)?.to_vec(),
        ))
    }
}
impl<Ext: CustomExtension, C: CustomTypeKind<RustTypeId>> Describe<C> for RawValue<'_, Ext> {
    const TYPE_ID: RustTypeId = RustTypeId::WellKnown(basic_well_known_types::ANY_TYPE);
    fn type_data() -> TypeData<C, RustTypeId> {
        basic_well_known_types::any_type_data()
    }
}
#[cfg(test)]
mod tests {
    use super::*;
    #[derive(BasicSbor)]
    struct RawValueStruct {
        field1: BasicOwnedRawValue,
        field2: (BasicOwnedRawValue, BasicOwnedRawValue),
    }
    #[test]
    pub fn can_encode_and_decode_raw_value() {
        let encoded = basic_encode(&BasicValue::Tuple {
            fields: vec![
                                BasicValue::Enum {
                    discriminator: 1,
                    fields: vec![],
                },
                                BasicValue::Tuple {
                    fields: vec![BasicValue::U8 { value: 1 }, BasicValue::U16 { value: 5125 }],
                },
            ],
        })
        .unwrap();
        let decoded: RawValueStruct = basic_decode(&encoded).unwrap();
                assert_eq!(decoded.field2.1.value_kind, ValueKind::U16);
        assert_eq!(
            decoded.field2.1.value_body_bytes(),
                        &basic_encode(&5125u16).unwrap()[2..],
        );
                let encoded2 = basic_encode(&decoded).unwrap();
        assert_eq!(encoded, encoded2);
    }
}