use ed25519_dalek::SignatureError;
use tokio::sync::mpsc;

use crate::{
    proto::{data_model::UnauthorisedWriteError, meadowcap::UserId, wgps::ResourceHandle},
    session::{pai_finder::PaiError, resource::MissingResource},
    store::traits::SecretStoreError,
    util::channel::{ReadError, WriteError},
};

// This is a catch-all error type for the session module.
// TODO: Split this into multiple error types
#[derive(Debug, thiserror::Error)]
pub enum Error {
    #[error("local store failed: {0}")]
    Store(#[from] anyhow::Error),
    #[error("authentication error: {0}")]
    Auth(#[from] crate::store::auth::AuthError),
    #[error("payload store failed: {0}")]
    PayloadStore(std::io::Error),
    #[error("payload digest does not match expected digest")]
    PayloadDigestMismatch,
    #[error("payload size does not match expected size")]
    PayloadSizeMismatch,
    #[error("local store failed: {0}")]
    KeyStore(#[from] SecretStoreError),
    #[error("failed to receive data: {0}")]
    Receive(#[from] ReadError),
    #[error("failed to send data: {0}")]
    Write(#[from] WriteError),
    #[error("wrong secret key for capability")]
    WrongSecretKeyForCapability,
    #[error("missing resource {0:?}")]
    MissingResource(ResourceHandle),
    #[error("received capability is invalid")]
    InvalidCapability,
    #[error("received capability has an invalid signature")]
    InvalidSignature,
    #[error("missing resource")]
    RangeOutsideCapability,
    #[error("received a message that is not valid in the current session state")]
    InvalidMessageInCurrentState,
    #[error("our and their area of interests refer to different namespaces")]
    AreaOfInterestNamespaceMismatch,
    #[error("our and their area of interests do not overlap")]
    AreaOfInterestDoesNotOverlap,
    #[error("received an area of interest which is not authorised")]
    UnauthorisedArea,
    #[error("received an entry which is not authorised")]
    UnauthorisedWrite(#[from] UnauthorisedWriteError),
    #[error("received an unsupported message type")]
    UnsupportedMessage,
    #[error("received a message that is intended for another channel")]
    WrongChannel,
    #[error("the received nonce does not match the received commitment")]
    BrokenCommittement,
    #[error("received an actor message for unknown session")]
    SessionNotFound,
    #[error("invalid parameters: {0}")]
    InvalidParameters(&'static str),
    #[error("reached an invalid state")]
    InvalidState(&'static str),
    #[error("actor failed to respond")]
    ActorFailed,
    #[error("missing user secret key for {0:?}")]
    MissingUserKey(UserId),
    #[error("a task failed to join")]
    TaskFailed(#[from] tokio::task::JoinError),
    #[error("no known interests for given capability")]
    NoKnownInterestsForCapability,
    #[error("private area intersection error: {0}")]
    Pai(#[from] PaiError),
    #[error("net failed: {0}")]
    Net(anyhow::Error),
    #[error("channel closed unexpectedly")]
    ChannelClosed,
    #[error("our node is shutting down")]
    ShuttingDown,
    #[error("The operation was cancelled locally")]
    Cancelled,
    #[error("Connection was closed by peer")]
    ConnectionClosed(#[source] anyhow::Error),
    #[error("Session was closed by peer")]
    SessionClosedByPeer,
}

#[derive(Debug, thiserror::Error)]
#[error("channel receiver dropped")]
pub struct ChannelReceiverDropped;
impl From<ChannelReceiverDropped> for Error {
    fn from(_: ChannelReceiverDropped) -> Self {
        Self::ChannelClosed
    }
}

// TODO: Remove likely?
// Added this to be able to implement PartialEq on EventKind for tests
// but many errors are not PartialEq, so we just return false for them, always
impl PartialEq for Error {
    fn eq(&self, other: &Self) -> bool {
        match (self, other) {
            (Self::Store(_), Self::Store(_)) => false,
            (Self::Auth(_), Self::Auth(_)) => false,
            (Self::PayloadStore(_), Self::PayloadStore(_)) => false,
            (Self::KeyStore(_), Self::KeyStore(_)) => false,
            (Self::Receive(_), Self::Receive(_)) => false,
            (Self::Write(_), Self::Write(_)) => false,
            (Self::TaskFailed(_), Self::TaskFailed(_)) => false,
            (Self::Pai(_), Self::Pai(_)) => false,
            (Self::Net(_), Self::Net(_)) => false,
            (Self::MissingResource(l0), Self::MissingResource(r0)) => l0 == r0,
            (Self::InvalidParameters(l0), Self::InvalidParameters(r0)) => l0 == r0,
            (Self::InvalidState(l0), Self::InvalidState(r0)) => l0 == r0,
            (Self::MissingUserKey(l0), Self::MissingUserKey(r0)) => l0 == r0,
            _ => core::mem::discriminant(self) == core::mem::discriminant(other),
        }
    }
}

impl Eq for Error {}

// impl From<meadowcap::InvalidCapability> for Error {
//     fn from(_value: meadowcap::InvalidCapability) -> Self {
//         Self::InvalidCapability
//     }
// }

impl From<SignatureError> for Error {
    fn from(_value: SignatureError) -> Self {
        Self::InvalidSignature
    }
}

// impl From<meadowcap::InvalidParams> for Error {
//     fn from(_value: meadowcap::InvalidParams) -> Self {
//         Self::InvalidParameters("")
//     }
// }

impl From<MissingResource> for Error {
    fn from(value: MissingResource) -> Self {
        Self::MissingResource(value.0)
    }
}

impl<T> From<mpsc::error::SendError<T>> for Error {
    fn from(_error: mpsc::error::SendError<T>) -> Self {
        Self::ChannelClosed
    }
}

Synonyms

radio/iroh-ffi/src/error.rs
radio/iroh-car/src/error.rs
cw-cyber/packages/hub-base/src/error.rs
cw-cyber/contracts/cybernet/src/error.rs
cw-cyber/contracts/std-test/src/error.rs
cw-cyber/contracts/hub-networks/src/error.rs
cw-cyber/contracts/litium-wrap/src/error.rs
cw-cyber/contracts/hub-channels/src/error.rs
radio/iroh-blobs/src/get/error.rs
cw-cyber/contracts/hub-tokens/src/error.rs
cw-cyber/contracts/hub-skills/src/error.rs
radio/cyber-bao/src/io/error.rs
cw-cyber/contracts/cw-cyber-gift/src/error.rs
cw-cyber/contracts/litium-core/src/error.rs
cw-cyber/contracts/cw-cyber-subgraph/src/error.rs
cw-cyber/contracts/hub-protocols/src/error.rs
cw-cyber/contracts/cw-cyber-passport/src/error.rs
cw-cyber/contracts/litium-refer/src/error.rs
cw-cyber/contracts/litium-stake/src/error.rs
cw-cyber/contracts/graph-filter/src/error.rs
radio/iroh-dns-server/src/http/error.rs
cw-cyber/contracts/hub-libs/src/error.rs
cw-cyber/contracts/litium-mine/src/error.rs

Neighbours