use serde::{Deserialize, Serialize};
use serde_json::Value;
use crate::errors::CustomError;
#[derive(Clone, Copy, Debug, PartialEq, Eq, Deserialize, Serialize)]
pub enum PayloadType{
    Disclosed,
    Undisclosed,
    ProofMethods
}
#[derive(Clone, Debug, PartialEq, Eq, Deserialize, Serialize)]
pub struct Payloads (pub Vec<(Value, PayloadType)>);
impl Payloads {
    pub fn new_from_values(values: Vec<Value>) -> Self {
        let mut payloads = Vec::new();
        for value in values {
            payloads.push((value, PayloadType::Disclosed));
        }
        Payloads(payloads)
    }
    pub fn get_undisclosed_indexes(&self) -> Vec<usize> {
        let mut undisclosed_indexes = Vec::new();
        for (index, (_, payload_type)) in self.0.iter().enumerate() {
            if let PayloadType::Undisclosed = payload_type {
                undisclosed_indexes.push(index);
            }
        }
        undisclosed_indexes
    }
    pub fn get_disclosed_indexes(&self) -> Vec<usize> {
        let mut disclosed_indexes = Vec::new();
        for (index, (_, payload_type)) in self.0.iter().enumerate() {
            if let PayloadType::Disclosed = payload_type {
                disclosed_indexes.push(index);
            }
        }
        disclosed_indexes
    }
    pub fn get_undisclosed_payloads(&self) -> Vec<Value> {
        let undisclosed_indexes = self.get_undisclosed_indexes();
        let undisclosed_payloads: Vec<Value> = self.0
            .iter()
            .enumerate()
            .filter(|(index, _)| undisclosed_indexes.contains(index))
            .map(|(_, payload)| payload.0.clone())
            .collect();
        undisclosed_payloads
    }
    pub fn get_disclosed_payloads(&self) -> Vec<Value> {
        let disclosed_indexes = self.get_disclosed_indexes();
        let disclosed_payloads: Vec<Value> = self.0
            .iter()
            .enumerate()
            .filter(|(index, _)| disclosed_indexes.contains(index))
            .map(|(_, payload)| payload.0.clone())
            .collect();
        disclosed_payloads
    }
    pub fn set_disclosed(&mut self, index: usize, disclosed: bool) -> Result<(), CustomError>{
        if let Some(p) = self.0.get_mut(index) {
            let payload_value = p.0.clone();
            match disclosed {
                true => *p = (payload_value, PayloadType::Disclosed),
                false => *p = (payload_value, PayloadType::Undisclosed)
            };
            Ok(())
        } else {
            Err(CustomError::IndexOutOfBounds)
        }
    }
}