use ghost_helpers::networks::NetworkCurve;

use crate::AuthIndex;

#[derive(Clone, Copy, PartialEq, Eq)]
pub enum ExodusError {
    InvalidParticipantId,
    DeserializationError,
    SerializationError,
    InvalidMinSigners(AuthIndex, AuthIndex),
    InvalidMaxSigners(AuthIndex),
    DKGNotSupported(NetworkCurve),
    IncorrectNumberOfCoefficients,
    IncorrectNumberOfCommitments,
    IncorrectNumberOfPackages,
    IncorrectPackage,
    PackageNotFound,
    InvalidSecretShare,
    InvalidProofOfKnowledge,
    MissingCommitment,
    IncorrectCommitment,
    UnknownIdentifier,
    IdentityCommitment,
    DuplicatedIdentifier,
    IncorrectNumberOfIdentifiers,
    InvalidSignature,
    InvalidSignatureShare,
    InvalidNonceCommitments,
    EncryptionFailed,
    DecryptionFailed,
    HKDFFailed,
    InvalidNonceLength,
    MalformedSigningKey,
    NoStoredNetworks,
    OffchainTimeoutPeriod,
    BadSignature(AuthIndex),
    TransactionSubmissionFailed(AuthIndex),
    UnknownReceiverIndex(AuthIndex),
    CouldNotConstructMessage(AuthIndex),
    NothingToWrite,
    UnknownPrefix,
    UnexpectedRound,
    InvalidMerkleProof,
    InvalidIdentityElement,
    NoActiveAuthorities,
    Unknown,
}

impl core::fmt::Debug for ExodusError {
    fn fmt(&self, fmt: &mut core::fmt::Formatter) -> core::fmt::Result {
        match *self {
            ExodusError::InvalidParticipantId => write!(fmt, "Participant index could not be parsed to identifier."),
            ExodusError::DeserializationError => write!(fmt, "Error during deserializing value."),
            ExodusError::SerializationError => write!(fmt, "Error serializing value."),
            ExodusError::InvalidMinSigners(min, max) => write!(fmt, "Number of min_signers ({min}) must be at least 2 and not larger than max_signers ({max})."),
            ExodusError::InvalidMaxSigners(max_signers) => write!(fmt, "Number of max_signers must be at least 2, {max_signers} given."),
            ExodusError::DKGNotSupported(ref curve) => write!(fmt, "The ciphersuite {curve:?} does not support DKG."),
            ExodusError::IncorrectNumberOfCoefficients => write!(fmt, "Incorrect number of coefficients; should be equal to min signers."),
            ExodusError::IncorrectNumberOfCommitments => write!(fmt, "Incorrect number of commitments; should be equal to min signers."),
            ExodusError::InvalidNonceCommitments => write!(fmt, "Hiding nonce commitments indexes should match binding nonce  commitments."),
            ExodusError::InvalidProofOfKnowledge => write!(fmt, "The proof of knowledge is not valid."),
            ExodusError::IncorrectNumberOfPackages => write!(fmt, "Incorrect number of packages; should be equal to max signers."),
            ExodusError::IncorrectPackage => write!(fmt, "The incorrect package was specified."),
            ExodusError::PackageNotFound => write!(fmt, "Round 1 package not found for Round 2 participant."),
            ExodusError::InvalidSecretShare => write!(fmt, "Invalid secret share."),
            ExodusError::MissingCommitment => write!(fmt, "The Signing Package must contain the participant's Commitments."),
            ExodusError::IncorrectCommitment => write!(fmt, "The participant's commitment is incorrect."),
            ExodusError::UnknownIdentifier => write!(fmt, "Unknown identifier."),
            ExodusError::IdentityCommitment => write!(fmt, "Commitment equals the identity."),
            ExodusError::DuplicatedIdentifier => write!(fmt, "Duplicated identifier."),
            ExodusError::IncorrectNumberOfIdentifiers => write!(fmt, "Incorrect number of identifiers."),
            ExodusError::InvalidSignature => write!(fmt, "Invalid signature."),
            ExodusError::InvalidSignatureShare => write!(fmt, "Invalid signature share."),
            ExodusError::EncryptionFailed => write!(fmt, "Encryption failed."),
            ExodusError::DecryptionFailed => write!(fmt, "Decryption failed."),
            ExodusError::HKDFFailed => write!(fmt, "HKDF failed."),
            ExodusError::InvalidNonceLength => write!(fmt, "Encryption nonce has invalid length."),
            ExodusError::MalformedSigningKey => write!(fmt, "Malformed signing key encoding."),
            ExodusError::NoStoredNetworks => write!(fmt, "No stored networks to be worked on."),
            ExodusError::OffchainTimeoutPeriod => write!(fmt, "Offchain request should be in-flight."),
            ExodusError::BadSignature(auth_index) => write!(fmt, "Signature could not be created from {auth_index}."),
            ExodusError::TransactionSubmissionFailed(auth_index) => write!(fmt, "Could not submit transaction from {auth_index}."),
            ExodusError::UnknownReceiverIndex(receiver_index) => write!(fmt, "Unknown receiver index {receiver_index} found."),
            ExodusError::CouldNotConstructMessage(auth_index) => write!(fmt, "Could not construct message during OCW from {auth_index}."),
            ExodusError::NothingToWrite => write!(fmt, "Nothing to write into local storage."),
            ExodusError::UnknownPrefix => write!(fmt, "Unknown prefix used for local storage."),
            ExodusError::UnexpectedRound => write!(fmt, "Unexpected round provided."),
            ExodusError::InvalidMerkleProof => write!(fmt, "Invalid merkle proof provided."),
            ExodusError::InvalidIdentityElement => write!(fmt, "Invalid identity element provided."),
            ExodusError::NoActiveAuthorities => write!(fmt, "No active authorities for signing exodus transactions."),
            ExodusError::Unknown => write!(fmt, "Unknown error."),
        }
    }
}
