use crate::{
error::{parse::validate::ValidationError, utils::MetaData},
knot::Address,
line::{Condition, InternalLine},
story::validate::{ValidateContent, ValidationData},
};
use std::sync::{Arc, Mutex};
#[cfg(feature = "serde_support")]
use serde::{Deserialize, Serialize};
use std::ops::DerefMut;
#[derive(Clone, Debug)]
#[cfg_attr(feature = "serde_support", derive(Deserialize, Serialize))]
pub struct InternalChoice {
pub selection_text: Arc<Mutex<InternalLine>>,
pub display_text: InternalLine,
pub condition: Option<Condition>,
pub is_sticky: bool,
pub is_fallback: bool,
pub meta_data: MetaData,
}
impl PartialEq for InternalChoice {
fn eq(&self, rhs: &InternalChoice) -> bool {
let left_line = (*self.selection_text.lock().unwrap()).clone();
let right_line = (*rhs.selection_text.lock().unwrap()).clone();
left_line == right_line
&& self.display_text == rhs.display_text
&& self.condition == rhs.condition
&& self.is_sticky == rhs.is_sticky
&& self.is_fallback == rhs.is_fallback
&& self.meta_data == rhs.meta_data
}
}
impl ValidateContent for InternalChoice {
fn validate(
&mut self,
error: &mut ValidationError,
current_location: &Address,
_: &MetaData,
data: &ValidationData,
) {
let num_address_errors = error.invalid_address_errors.len();
self.selection_text.lock().unwrap().deref_mut().validate(
error,
current_location,
&self.meta_data,
data,
);
if num_address_errors == error.invalid_address_errors.len() {
self.display_text
.validate(error, current_location, &self.meta_data, data);
}
if let Some(ref mut condition) = self.condition {
condition.validate(error, current_location, &self.meta_data, data);
}
}
}
pub struct InternalChoiceBuilder {
selection_text: InternalLine,
display_text: InternalLine,
condition: Option<Condition>,
is_fallback: bool,
is_sticky: bool,
tags: Option<Vec<String>>,
}
impl InternalChoiceBuilder {
pub fn from_line(line: InternalLine) -> Self {
InternalChoiceBuilder {
selection_text: line.clone(),
display_text: line,
condition: None,
is_sticky: false,
is_fallback: false,
tags: None,
}
}
pub fn build(mut self) -> InternalChoice {
if let Some(tags) = self.tags {
self.display_text.tags = tags.clone();
self.selection_text.tags = tags.clone();
}
let meta_data = self.display_text.meta_data.clone();
InternalChoice {
selection_text: Arc::new(Mutex::new(self.selection_text)),
display_text: self.display_text,
condition: self.condition,
is_sticky: self.is_sticky,
is_fallback: self.is_fallback,
meta_data,
}
}
pub fn set_condition(&mut self, condition: &Condition) {
self.condition.replace(condition.clone());
}
#[cfg(test)]
pub fn set_display_text(&mut self, line: InternalLine) {
self.display_text = line;
}
pub fn set_is_fallback(&mut self, fallback: bool) {
self.is_fallback = fallback;
}
pub fn set_selection_text(&mut self, line: InternalLine) {
self.selection_text = line;
}
#[cfg(test)]
pub fn from_string(line: &str) -> Self {
Self::from_line(InternalLine::from_string(line))
}
#[cfg(test)]
pub fn from_selection_string(line: &str) -> Self {
let empty = InternalLine::from_string("");
Self::from_string(line).with_display_text(empty)
}
#[cfg(test)]
pub fn is_fallback(mut self) -> Self {
self.is_fallback = true;
self
}
#[cfg(test)]
pub fn is_sticky(mut self) -> Self {
self.is_sticky = true;
self
}
#[cfg(test)]
pub fn with_condition(mut self, condition: &Condition) -> Self {
self.set_condition(condition);
self
}
#[cfg(test)]
pub fn with_display_text(mut self, line: InternalLine) -> Self {
self.set_display_text(line);
self
}
#[cfg(test)]
pub fn with_tags(mut self, tags: &[String]) -> Self {
self.tags.replace(tags.to_vec());
self
}
}