// @generated by jacquard-lexicon. DO NOT EDIT.
//
// Lexicon: place.stream.beta.invite
//
// This file was automatically generated from Lexicon schemas.
// Any manual changes will be overwritten on the next regeneration.

#[allow(unused_imports)]
use alloc::collections::BTreeMap;

#[allow(unused_imports)]
use core::marker::PhantomData;
use jacquard_common::{CowStr, BosStr, DefaultStr, FromStaticStr};

#[allow(unused_imports)]
use jacquard_common::deps::codegen::unicode_segmentation::UnicodeSegmentation;
use jacquard_common::deps::smol_str::SmolStr;
use jacquard_common::types::collection::{Collection, RecordError};
use jacquard_common::types::string::{Did, AtUri, Cid, Datetime};
use jacquard_common::types::uri::{RecordUri, UriError};
use jacquard_common::types::value::Data;
use jacquard_common::xrpc::XrpcResp;
use jacquard_derive::{IntoStatic, lexicon};
use jacquard_lexicon::lexicon::LexiconDoc;
use jacquard_lexicon::schema::LexiconSchema;

#[allow(unused_imports)]
use jacquard_lexicon::validation::{ConstraintError, ValidationPath};
use serde::{Serialize, Deserialize};
/// Grants a single account access to a named beta feature on this network. Records live in a project-operated repo (the streamplace node's `--beta-invite-did`); operators trust invites only from that one account, by configuration. Each (did, feature) pair gets its own record so individual features can be revoked independently by deleting the corresponding record.

#[derive(Serialize, Deserialize, Debug, Clone, PartialEq, Eq, IntoStatic)]
#[serde(
    rename_all = "camelCase",
    rename = "place.stream.beta.invite",
    tag = "$type",
    bound(deserialize = "S: Deserialize<'de> + BosStr")
)]
pub struct Invite<S: BosStr = DefaultStr> {
    ///Client-declared timestamp when this invite was issued.
    pub created_at: Datetime,
    ///Account being granted access to the named beta feature.
    pub did: Did<S>,
    ///Identifier of the beta feature being granted (e.g. "vod").
    pub feature: S,
    #[serde(flatten, default, skip_serializing_if = "Option::is_none")]
    pub extra_data: Option<BTreeMap<SmolStr, Data<S>>>,
}

/// Typed wrapper for GetRecord response with this collection's record type.

#[derive(Serialize, Deserialize, Debug, Clone, PartialEq, Eq, IntoStatic)]
#[serde(rename_all = "camelCase")]
pub struct InviteGetRecordOutput<S: BosStr = DefaultStr> {
    #[serde(skip_serializing_if = "Option::is_none")]
    pub cid: Option<Cid<S>>,
    pub uri: AtUri<S>,
    pub value: Invite<S>,
}

impl<S: BosStr> Invite<S> {
    pub fn uri(uri: S) -> Result<RecordUri<S, InviteRecord>, UriError> {
        RecordUri::try_from_uri(AtUri::new(uri)?)
    }
}

/// Marker type for deserializing records from this collection.

#[derive(Debug, Serialize, Deserialize)]
pub struct InviteRecord;
impl XrpcResp for InviteRecord {
    const NSID: &'static str = "place.stream.beta.invite";
    const ENCODING: &'static str = "application/json";
    type Output<S: BosStr> = InviteGetRecordOutput<S>;
    type Err = RecordError;
}

impl<S: BosStr> From<InviteGetRecordOutput<S>> for Invite<S> {
    fn from(output: InviteGetRecordOutput<S>) -> Self {
        output.value
    }
}

impl<S: BosStr> Collection for Invite<S> {
    const NSID: &'static str = "place.stream.beta.invite";
    type Record = InviteRecord;
}

impl Collection for InviteRecord {
    const NSID: &'static str = "place.stream.beta.invite";
    type Record = InviteRecord;
}

impl<S: BosStr> LexiconSchema for Invite<S> {
    fn nsid() -> &'static str {
        "place.stream.beta.invite"
    }
    fn def_name() -> &'static str {
        "main"
    }
    fn lexicon_doc() -> LexiconDoc<'static> {
        lexicon_doc_place_stream_beta_invite()
    }
    fn validate(&self) -> Result<(), ConstraintError> {
        Ok(())
    }
}

pub mod invite_state {

    pub use crate::builder_types::{Set, Unset, IsSet, IsUnset};
    #[allow(unused)]
    use ::core::marker::PhantomData;
    mod sealed {
        pub trait Sealed {}
    }
    /// State trait tracking which required fields have been set
    pub trait State: sealed::Sealed {
        type CreatedAt;
        type Did;
        type Feature;
    }
    /// Empty state - all required fields are unset
    pub struct Empty(());
    impl sealed::Sealed for Empty {}
    impl State for Empty {
        type CreatedAt = Unset;
        type Did = Unset;
        type Feature = Unset;
    }
    ///State transition - sets the `created_at` field to Set
    pub struct SetCreatedAt<St: State = Empty>(PhantomData<fn() -> St>);
    impl<St: State> sealed::Sealed for SetCreatedAt<St> {}
    impl<St: State> State for SetCreatedAt<St> {
        type CreatedAt = Set<members::created_at>;
        type Did = St::Did;
        type Feature = St::Feature;
    }
    ///State transition - sets the `did` field to Set
    pub struct SetDid<St: State = Empty>(PhantomData<fn() -> St>);
    impl<St: State> sealed::Sealed for SetDid<St> {}
    impl<St: State> State for SetDid<St> {
        type CreatedAt = St::CreatedAt;
        type Did = Set<members::did>;
        type Feature = St::Feature;
    }
    ///State transition - sets the `feature` field to Set
    pub struct SetFeature<St: State = Empty>(PhantomData<fn() -> St>);
    impl<St: State> sealed::Sealed for SetFeature<St> {}
    impl<St: State> State for SetFeature<St> {
        type CreatedAt = St::CreatedAt;
        type Did = St::Did;
        type Feature = Set<members::feature>;
    }
    /// Marker types for field names
    #[allow(non_camel_case_types)]
    pub mod members {
        ///Marker type for the `created_at` field
        pub struct created_at(());
        ///Marker type for the `did` field
        pub struct did(());
        ///Marker type for the `feature` field
        pub struct feature(());
    }
}

/// Builder for constructing an instance of this type.
pub struct InviteBuilder<St: invite_state::State, S: BosStr = DefaultStr> {
    _state: PhantomData<fn() -> St>,
    _fields: (Option<Datetime>, Option<Did<S>>, Option<S>),
    _type: PhantomData<fn() -> S>,
}

impl Invite<DefaultStr> {
    /// Create a new builder for this type, using the default string type (DefaultStr = SmolStr) if needed
    pub fn new() -> InviteBuilder<invite_state::Empty, DefaultStr> {
        InviteBuilder::new()
    }
}

impl<S: BosStr> Invite<S> {
    /// Create a new builder for this type
    pub fn builder() -> InviteBuilder<invite_state::Empty, S> {
        InviteBuilder::builder()
    }
}

impl InviteBuilder<invite_state::Empty, DefaultStr> {
    /// Create a new builder with all fields unset, using the default string type, if needed
    pub fn new() -> Self {
        InviteBuilder {
            _state: PhantomData,
            _fields: (None, None, None),
            _type: PhantomData,
        }
    }
}

impl<S: BosStr> InviteBuilder<invite_state::Empty, S> {
    /// Create a new builder with all fields unset
    pub fn builder() -> Self {
        InviteBuilder {
            _state: PhantomData,
            _fields: (None, None, None),
            _type: PhantomData,
        }
    }
}

impl<St, S: BosStr> InviteBuilder<St, S>
where
    St: invite_state::State,
    St::CreatedAt: invite_state::IsUnset,
{
    /// Set the `createdAt` field (required)
    pub fn created_at(
        mut self,
        value: impl Into<Datetime>,
    ) -> InviteBuilder<invite_state::SetCreatedAt<St>, S> {
        self._fields.0 = Option::Some(value.into());
        InviteBuilder {
            _state: PhantomData,
            _fields: self._fields,
            _type: PhantomData,
        }
    }
}

impl<St, S: BosStr> InviteBuilder<St, S>
where
    St: invite_state::State,
    St::Did: invite_state::IsUnset,
{
    /// Set the `did` field (required)
    pub fn did(
        mut self,
        value: impl Into<Did<S>>,
    ) -> InviteBuilder<invite_state::SetDid<St>, S> {
        self._fields.1 = Option::Some(value.into());
        InviteBuilder {
            _state: PhantomData,
            _fields: self._fields,
            _type: PhantomData,
        }
    }
}

impl<St, S: BosStr> InviteBuilder<St, S>
where
    St: invite_state::State,
    St::Feature: invite_state::IsUnset,
{
    /// Set the `feature` field (required)
    pub fn feature(
        mut self,
        value: impl Into<S>,
    ) -> InviteBuilder<invite_state::SetFeature<St>, S> {
        self._fields.2 = Option::Some(value.into());
        InviteBuilder {
            _state: PhantomData,
            _fields: self._fields,
            _type: PhantomData,
        }
    }
}

impl<St, S: BosStr> InviteBuilder<St, S>
where
    St: invite_state::State,
    St::CreatedAt: invite_state::IsSet,
    St::Did: invite_state::IsSet,
    St::Feature: invite_state::IsSet,
{
    /// Build the final struct.
    pub fn build(self) -> Invite<S> {
        Invite {
            created_at: self._fields.0.unwrap(),
            did: self._fields.1.unwrap(),
            feature: self._fields.2.unwrap(),
            extra_data: Default::default(),
        }
    }
    /// Build the final struct with custom extra_data.
    pub fn build_with_data(self, extra_data: BTreeMap<SmolStr, Data<S>>) -> Invite<S> {
        Invite {
            created_at: self._fields.0.unwrap(),
            did: self._fields.1.unwrap(),
            feature: self._fields.2.unwrap(),
            extra_data: Some(extra_data),
        }
    }
}

fn lexicon_doc_place_stream_beta_invite() -> LexiconDoc<'static> {
    #[allow(unused_imports)]
    use jacquard_common::{CowStr, deps::smol_str::SmolStr, types::blob::MimeType};
    use jacquard_lexicon::lexicon::*;
    use alloc::collections::BTreeMap;
    LexiconDoc {
        lexicon: Lexicon::Lexicon1,
        id: CowStr::new_static("place.stream.beta.invite"),
        defs: {
            let mut map = BTreeMap::new();
            map.insert(
                SmolStr::new_static("main"),
                LexUserType::Record(LexRecord {
                    description: Some(
                        CowStr::new_static(
                            "Grants a single account access to a named beta feature on this network. Records live in a project-operated repo (the streamplace node's `--beta-invite-did`); operators trust invites only from that one account, by configuration. Each (did, feature) pair gets its own record so individual features can be revoked independently by deleting the corresponding record.",
                        ),
                    ),
                    key: Some(CowStr::new_static("tid")),
                    record: LexRecordRecord::Object(LexObject {
                        required: Some(
                            vec![
                                SmolStr::new_static("did"), SmolStr::new_static("feature"),
                                SmolStr::new_static("createdAt")
                            ],
                        ),
                        properties: {
                            #[allow(unused_mut)]
                            let mut map = BTreeMap::new();
                            map.insert(
                                SmolStr::new_static("createdAt"),
                                LexObjectProperty::String(LexString {
                                    description: Some(
                                        CowStr::new_static(
                                            "Client-declared timestamp when this invite was issued.",
                                        ),
                                    ),
                                    format: Some(LexStringFormat::Datetime),
                                    ..Default::default()
                                }),
                            );
                            map.insert(
                                SmolStr::new_static("did"),
                                LexObjectProperty::String(LexString {
                                    description: Some(
                                        CowStr::new_static(
                                            "Account being granted access to the named beta feature.",
                                        ),
                                    ),
                                    format: Some(LexStringFormat::Did),
                                    ..Default::default()
                                }),
                            );
                            map.insert(
                                SmolStr::new_static("feature"),
                                LexObjectProperty::String(LexString {
                                    description: Some(
                                        CowStr::new_static(
                                            "Identifier of the beta feature being granted (e.g. \"vod\").",
                                        ),
                                    ),
                                    ..Default::default()
                                }),
                            );
                            map
                        },
                        ..Default::default()
                    }),
                    ..Default::default()
                }),
            );
            map
        },
        ..Default::default()
    }
}