use std::ops::Deref;
use chrono::Utc;
use serde_json::Value;
use crate::core::voiceflow::dialog_blocks::enums::VoiceflowButtonsOption;
use crate::core::voiceflow::dialog_blocks::{VoiceflowButton, VoiceflowText};
use crate::core::voiceflow::dialog_blocks::traits::FromValue;
use crate::errors::{VoiceflousionError, VoiceflousionResult};
#[derive(Debug, Clone)]
pub struct VoiceflowButtons {
option: VoiceflowButtonsOption,
buttons: Vec<VoiceflowButton>,
mark_timestamp: i64,
}
impl VoiceflowButtons {
pub fn new(buttons: Vec<VoiceflowButton>) -> Self {
Self {
buttons,
mark_timestamp: Utc::now().timestamp(),
option: VoiceflowButtonsOption::Text(VoiceflowText::new(String::from("Voiceflousion placeholder button's text"))),
}
}
pub fn option(&self) -> &VoiceflowButtonsOption {
&self.option
}
pub fn mark(&self) -> i64 {
self.mark_timestamp
}
pub fn set_option(&mut self, buttons_option: VoiceflowButtonsOption) {
self.option = buttons_option;
}
pub fn get_button(&self, button_index: usize) -> VoiceflousionResult<&VoiceflowButton> {
self.get(button_index).ok_or_else(|| VoiceflousionError::ValidationError(
"SentMessage content".to_string(),
format!("Invalid index {} for buttons container with {} buttons", button_index, self.len())
))
}
}
impl Deref for VoiceflowButtons{
type Target = Vec<VoiceflowButton>;
fn deref(&self) -> &Self::Target {
&self.buttons
}
}
impl FromValue for VoiceflowButtons {
fn from_value(value: &Value) -> VoiceflousionResult<Option<Self>> {
let buttons_value = match value["trace"]["payload"].get("buttons") {
None => value.get("buttons").and_then(|buttons| buttons.as_array()),
Some(buttons) => buttons.as_array(),
}.ok_or_else(|| VoiceflousionError::VoiceflowBlockConvertationError(
"VoiceflowButtons buttons value".to_string(),
value.clone()
))?;
let buttons_option: Result<Vec<Option<VoiceflowButton>>, VoiceflousionError> = buttons_value.into_iter()
.map(|button| VoiceflowButton::from_value(button))
.collect();
let buttons: Vec<VoiceflowButton> = buttons_option?.into_iter().filter_map(|button| button).collect();
if buttons.is_empty() {
return Ok(None);
}
Ok(Some(Self::new(buttons)))
}
}