//! Contains the `Credentials` struct, which contains all keys, IDs, organizations and other identity-related and security-related data that is persistent in a `Client`

use std::error::Error;
use trifid_pki::cert::{deserialize_ed25519_public_many, serialize_ed25519_public};
use trifid_pki::ed25519_dalek::{SigningKey, VerifyingKey};
use serde::{Serialize, Deserialize};

#[derive(Serialize, Deserialize, Clone)]
/// Contains information necessary to make requests against the `DNClient` API.
pub struct Credentials {
    /// The assigned Host ID that this client represents
    pub host_id: String,
    /// The ed25519 private key used to sign requests against the API
    pub ed_privkey: SigningKey,
    /// The counter used in the other API requests. It is unknown what the purpose of this is, but the original client persists it and it is needed for API calls.
    pub counter: u32,
    /// The set of trusted ed25519 keys that may be used by the API to sign API responses.
    pub trusted_keys: Vec<VerifyingKey>
}

/// Converts an array of `VerifyingKey`s to a singular bundle of PEM-encoded keys
pub fn ed25519_public_keys_to_pem(keys: &[VerifyingKey]) -> Vec<u8> {
    let mut res = vec![];

    for key in keys {
        res.append(&mut serialize_ed25519_public(&key.to_bytes()));
    }

    res
}

/// Converts a set of PEM-encoded ed25519 public keys, and converts them into an array of `VerifyingKey`s.
/// # Errors
/// This function will return an error if the PEM could not be decoded, or if any of the encoded keys are invalid.
pub fn ed25519_public_keys_from_pem(pem: &[u8]) -> Result<Vec<VerifyingKey>, Box<dyn Error>> {
    let pems = deserialize_ed25519_public_many(pem)?;
    let mut keys = vec![];

    #[allow(clippy::unwrap_used)]
    for pem in pems {
        keys.push(VerifyingKey::from_bytes(&pem.try_into().unwrap_or_else(|_| unreachable!()))?);
    }

    Ok(keys)
}