use arc_bytes::serde::Bytes;
use serde::{Deserialize, Serialize};
use crate::api::{Api, ApiName};
use crate::connection::{
    AccessPolicy, Database, IdentityReference, Range, SerializedQueryKey, Session, SessionId, Sort,
};
use crate::document::{DocumentId, Header, OwnedDocument};
use crate::keyvalue::{KeyOperation, Output};
use crate::schema::view::map::{self, MappedSerializedDocuments};
use crate::schema::{CollectionName, NamedReference, Qualified, SchemaSummary, ViewName};
use crate::transaction::{Executed, OperationResult, Transaction};
pub const CURRENT_PROTOCOL_VERSION: &str = "bonsai-pre-1";
#[derive(Clone, Deserialize, Serialize, Debug)]
pub struct Payload {
    pub session_id: Option<SessionId>,
    pub id: Option<u32>,
    pub name: ApiName,
    pub value: Result<Bytes, crate::Error>,
}
#[derive(Clone, Deserialize, Serialize, Debug)]
pub struct CreateDatabase {
    pub database: Database,
    pub only_if_needed: bool,
}
impl Api for CreateDatabase {
    type Error = crate::Error;
    type Response = ();
    fn name() -> ApiName {
        ApiName::new("bonsaidb", "CreateDatabase")
    }
}
#[derive(Clone, Deserialize, Serialize, Debug)]
pub struct DeleteDatabase {
    pub name: String,
}
impl Api for DeleteDatabase {
    type Error = crate::Error;
    type Response = ();
    fn name() -> ApiName {
        ApiName::new("bonsaidb", "DeleteDatabase")
    }
}
#[derive(Clone, Deserialize, Serialize, Debug)]
pub struct ListDatabases;
impl Api for ListDatabases {
    type Error = crate::Error;
    type Response = Vec<Database>;
    fn name() -> ApiName {
        ApiName::new("bonsaidb", "ListDatabases")
    }
}
#[derive(Clone, Deserialize, Serialize, Debug)]
pub struct ListAvailableSchemas;
impl Api for ListAvailableSchemas {
    type Error = crate::Error;
    type Response = Vec<SchemaSummary>;
    fn name() -> ApiName {
        ApiName::new("bonsaidb", "ListAvailableSchemas")
    }
}
#[derive(Clone, Deserialize, Serialize, Debug)]
pub struct CreateUser {
    pub username: String,
}
impl Api for CreateUser {
    type Error = crate::Error;
    type Response = u64;
    fn name() -> ApiName {
        ApiName::new("bonsaidb", "CreateUser")
    }
}
#[derive(Clone, Deserialize, Serialize, Debug)]
pub struct DeleteUser {
    pub user: NamedReference<'static, u64>,
}
impl Api for DeleteUser {
    type Error = crate::Error;
    type Response = ();
    fn name() -> ApiName {
        ApiName::new("bonsaidb", "DeleteUser")
    }
}
#[cfg(feature = "password-hashing")]
#[derive(Clone, Deserialize, Serialize, Debug)]
pub struct SetUserPassword {
    pub user: NamedReference<'static, u64>,
    pub password: crate::connection::SensitiveString,
}
#[cfg(feature = "password-hashing")]
impl Api for SetUserPassword {
    type Error = crate::Error;
    type Response = ();
    fn name() -> ApiName {
        ApiName::new("bonsaidb", "SetUserPassword")
    }
}
#[cfg(any(feature = "password-hashing", feature = "token-authentication"))]
#[derive(Clone, Deserialize, Serialize, Debug)]
pub struct Authenticate {
    pub authentication: crate::connection::Authentication,
}
#[cfg(any(feature = "password-hashing", feature = "token-authentication"))]
impl Api for Authenticate {
    type Error = crate::Error;
    type Response = Session;
    fn name() -> ApiName {
        ApiName::new("bonsaidb", "Authenticate")
    }
}
#[derive(Clone, Deserialize, Serialize, Debug)]
pub struct AssumeIdentity(pub IdentityReference<'static>);
impl Api for AssumeIdentity {
    type Error = crate::Error;
    type Response = Session;
    fn name() -> ApiName {
        ApiName::new("bonsaidb", "AssumeIdentity")
    }
}
#[derive(Clone, Deserialize, Serialize, Debug)]
pub struct LogOutSession(pub SessionId);
impl Api for LogOutSession {
    type Error = crate::Error;
    type Response = ();
    fn name() -> ApiName {
        ApiName::new("bonsaidb", "LogOutSession")
    }
}
#[derive(Clone, Deserialize, Serialize, Debug)]
pub struct AlterUserPermissionGroupMembership {
    pub user: NamedReference<'static, u64>,
    pub group: NamedReference<'static, u64>,
    pub should_be_member: bool,
}
impl Api for AlterUserPermissionGroupMembership {
    type Error = crate::Error;
    type Response = ();
    fn name() -> ApiName {
        ApiName::new("bonsaidb", "AlterUserPermissionGroupMembership")
    }
}
#[derive(Clone, Deserialize, Serialize, Debug)]
pub struct AlterUserRoleMembership {
    pub user: NamedReference<'static, u64>,
    pub role: NamedReference<'static, u64>,
    pub should_be_member: bool,
}
impl Api for AlterUserRoleMembership {
    type Error = crate::Error;
    type Response = ();
    fn name() -> ApiName {
        ApiName::new("bonsaidb", "AlterUserRoleMembership")
    }
}
#[derive(Clone, Deserialize, Serialize, Debug)]
pub struct Get {
    pub database: String,
    pub collection: CollectionName,
    pub id: DocumentId,
}
impl Api for Get {
    type Error = crate::Error;
    type Response = Option<OwnedDocument>;
    fn name() -> ApiName {
        ApiName::new("bonsaidb", "Get")
    }
}
#[derive(Clone, Deserialize, Serialize, Debug)]
pub struct GetMultiple {
    pub database: String,
    pub collection: CollectionName,
    pub ids: Vec<DocumentId>,
}
impl Api for GetMultiple {
    type Error = crate::Error;
    type Response = Vec<OwnedDocument>;
    fn name() -> ApiName {
        ApiName::new("bonsaidb", "GetMultiple")
    }
}
#[derive(Clone, Deserialize, Serialize, Debug)]
pub struct List {
    pub database: String,
    pub collection: CollectionName,
    pub ids: Range<DocumentId>,
    pub order: Sort,
    pub limit: Option<u32>,
}
impl Api for List {
    type Error = crate::Error;
    type Response = Vec<OwnedDocument>;
    fn name() -> ApiName {
        ApiName::new("bonsaidb", "List")
    }
}
#[derive(Clone, Deserialize, Serialize, Debug)]
pub struct ListHeaders(pub List);
impl Api for ListHeaders {
    type Error = crate::Error;
    type Response = Vec<Header>;
    fn name() -> ApiName {
        ApiName::new("bonsaidb", "ListHeaders")
    }
}
#[derive(Clone, Deserialize, Serialize, Debug)]
pub struct Count {
    pub database: String,
    pub collection: CollectionName,
    pub ids: Range<DocumentId>,
}
impl Api for Count {
    type Error = crate::Error;
    type Response = u64;
    fn name() -> ApiName {
        ApiName::new("bonsaidb", "Count")
    }
}
#[derive(Clone, Deserialize, Serialize, Debug)]
pub struct Query {
    pub database: String,
    pub view: ViewName,
    pub key: Option<SerializedQueryKey>,
    pub order: Sort,
    pub limit: Option<u32>,
    pub access_policy: AccessPolicy,
}
impl Api for Query {
    type Error = crate::Error;
    type Response = Vec<map::Serialized>;
    fn name() -> ApiName {
        ApiName::new("bonsaidb", "Query")
    }
}
#[derive(Clone, Deserialize, Serialize, Debug)]
pub struct QueryWithDocs(pub Query);
impl Api for QueryWithDocs {
    type Error = crate::Error;
    type Response = MappedSerializedDocuments;
    fn name() -> ApiName {
        ApiName::new("bonsaidb", "QueryWithDocs")
    }
}
#[derive(Clone, Deserialize, Serialize, Debug)]
pub struct Reduce {
    pub database: String,
    pub view: ViewName,
    pub key: Option<SerializedQueryKey>,
    pub access_policy: AccessPolicy,
}
impl Api for Reduce {
    type Error = crate::Error;
    type Response = Bytes;
    fn name() -> ApiName {
        ApiName::new("bonsaidb", "Reduce")
    }
}
#[derive(Clone, Deserialize, Serialize, Debug)]
pub struct ReduceGrouped(pub Reduce);
impl Api for ReduceGrouped {
    type Error = crate::Error;
    type Response = Vec<map::MappedSerializedValue>;
    fn name() -> ApiName {
        ApiName::new("bonsaidb", "ReduceGrouped")
    }
}
#[derive(Clone, Deserialize, Serialize, Debug)]
pub struct DeleteDocs {
    pub database: String,
    pub view: ViewName,
    pub key: Option<SerializedQueryKey>,
    pub access_policy: AccessPolicy,
}
impl Api for DeleteDocs {
    type Error = crate::Error;
    type Response = u64;
    fn name() -> ApiName {
        ApiName::new("bonsaidb", "DeleteDocs")
    }
}
#[derive(Clone, Deserialize, Serialize, Debug)]
pub struct ApplyTransaction {
    pub database: String,
    pub transaction: Transaction,
}
impl Api for ApplyTransaction {
    type Error = crate::Error;
    type Response = Vec<OperationResult>;
    fn name() -> ApiName {
        ApiName::new("bonsaidb", "ApplyTransaction")
    }
}
#[derive(Clone, Deserialize, Serialize, Debug)]
pub struct ListExecutedTransactions {
    pub database: String,
    pub starting_id: Option<u64>,
    pub result_limit: Option<u32>,
}
impl Api for ListExecutedTransactions {
    type Error = crate::Error;
    type Response = Vec<Executed>;
    fn name() -> ApiName {
        ApiName::new("bonsaidb", "ListExecutedTransactions")
    }
}
#[derive(Clone, Deserialize, Serialize, Debug)]
pub struct LastTransactionId {
    pub database: String,
}
impl Api for LastTransactionId {
    type Error = crate::Error;
    type Response = Option<u64>;
    fn name() -> ApiName {
        ApiName::new("bonsaidb", "LastTransactionId")
    }
}
#[derive(Clone, Deserialize, Serialize, Debug)]
pub struct CreateSubscriber {
    pub database: String,
}
impl Api for CreateSubscriber {
    type Error = crate::Error;
    type Response = u64;
    fn name() -> ApiName {
        ApiName::new("bonsaidb", "CreateSubscriber")
    }
}
#[derive(Clone, Deserialize, Serialize, Debug)]
pub struct Publish {
    pub database: String,
    pub topic: Bytes,
    pub payload: Bytes,
}
impl Api for Publish {
    type Error = crate::Error;
    type Response = ();
    fn name() -> ApiName {
        ApiName::new("bonsaidb", "Publish")
    }
}
#[derive(Clone, Deserialize, Serialize, Debug)]
pub struct PublishToAll {
    pub database: String,
    pub topics: Vec<Bytes>,
    pub payload: Bytes,
}
impl Api for PublishToAll {
    type Error = crate::Error;
    type Response = ();
    fn name() -> ApiName {
        ApiName::new("bonsaidb", "PublishToAll")
    }
}
#[derive(Clone, Deserialize, Serialize, Debug)]
pub struct SubscribeTo {
    pub database: String,
    pub subscriber_id: u64,
    pub topic: Bytes,
}
impl Api for SubscribeTo {
    type Error = crate::Error;
    type Response = ();
    fn name() -> ApiName {
        ApiName::new("bonsaidb", "SubscribeTo")
    }
}
#[derive(Clone, Deserialize, Serialize, Debug)]
pub struct MessageReceived {
    pub subscriber_id: u64,
    pub topic: Bytes,
    pub payload: Bytes,
}
impl Api for MessageReceived {
    type Error = crate::Error;
    type Response = Self;
    fn name() -> ApiName {
        ApiName::new("bonsaidb", "MessageReceived")
    }
}
#[derive(Clone, Deserialize, Serialize, Debug)]
pub struct UnsubscribeFrom {
    pub database: String,
    pub subscriber_id: u64,
    pub topic: Bytes,
}
impl Api for UnsubscribeFrom {
    type Error = crate::Error;
    type Response = ();
    fn name() -> ApiName {
        ApiName::new("bonsaidb", "UnsubscribeFrom")
    }
}
#[derive(Clone, Deserialize, Serialize, Debug)]
pub struct UnregisterSubscriber {
    pub database: String,
    pub subscriber_id: u64,
}
impl Api for UnregisterSubscriber {
    type Error = crate::Error;
    type Response = ();
    fn name() -> ApiName {
        ApiName::new("bonsaidb", "UnregisterSubscriber")
    }
}
#[derive(Clone, Deserialize, Serialize, Debug)]
pub struct ExecuteKeyOperation {
    pub database: String,
    pub op: KeyOperation,
}
impl Api for ExecuteKeyOperation {
    type Error = crate::Error;
    type Response = Output;
    fn name() -> ApiName {
        ApiName::new("bonsaidb", "ExecuteKeyOperation")
    }
}
#[derive(Clone, Deserialize, Serialize, Debug)]
pub struct CompactCollection {
    pub database: String,
    pub name: CollectionName,
}
impl Api for CompactCollection {
    type Error = crate::Error;
    type Response = ();
    fn name() -> ApiName {
        ApiName::new("bonsaidb", "CompactCollection")
    }
}
#[derive(Clone, Deserialize, Serialize, Debug)]
pub struct CompactKeyValueStore {
    pub database: String,
}
impl Api for CompactKeyValueStore {
    type Error = crate::Error;
    type Response = ();
    fn name() -> ApiName {
        ApiName::new("bonsaidb", "CompactKeyValueStore")
    }
}
#[derive(Clone, Deserialize, Serialize, Debug)]
pub struct Compact {
    pub database: String,
}
impl Api for Compact {
    type Error = crate::Error;
    type Response = ();
    fn name() -> ApiName {
        ApiName::new("bonsaidb", "Compact")
    }
}
#[derive(Clone, thiserror::Error, Debug, Serialize, Deserialize)]
pub enum Error {
    #[error("unexpected response: {0}")]
    UnexpectedResponse(String),
    #[error("connection timeout")]
    ConnectTimeout,
    #[error("request timeout")]
    RequestTimeout,
    #[error("unexpected disconnection")]
    Disconnected,
}