use std::collections::HashMap;
use crate::{decoder::{RawBlock, RawBlockInput}, error::DecodeError, structs::{Block, Value}};
#[derive(Debug, Clone, PartialEq)]
pub enum InputValue {
Literal(Value),
Color(u8, u8, u8),
Broadcast(String),
Variable(String),
List(String),
Block(Box<Block>),
}
#[derive(Debug, Clone, PartialEq)]
pub struct BlockInput {
pub shadow: bool,
pub value: InputValue,
}
impl BlockInput {
pub fn new(raw: RawBlockInput, blocks: &HashMap<String, RawBlock>) -> Result<Self, DecodeError> {
let shadow = match raw.shadow {
1 | 3 => true,
2 => false,
_ => unreachable!("Invalid shadow value: {}", raw.shadow),
};
let value = match raw.kind {
0 => {
let block_id = raw
.value
.as_str()
.ok_or_else(|| DecodeError::InvalidData("Expected a string".to_string()))?;
InputValue::Block(Box::new(Block::new(block_id, blocks)?))
}
4..=8 => {
InputValue::Literal(Value::from(raw.value.clone()))
}
9 => {
let hex_str = raw
.value
.as_str()
.ok_or_else(|| DecodeError::InvalidData("Expected a string".to_string()))?;
if !hex_str.starts_with('#') || hex_str.len() != 7 {
return Err(DecodeError::InvalidData(format!(
"Invalid hex color string: {}",
hex_str
)));
}
let r = u8::from_str_radix(&hex_str[1..3], 16).map_err(|_| {
DecodeError::InvalidData(format!("Invalid red component in hex color: {}", hex_str))
})?;
let g = u8::from_str_radix(&hex_str[3..5], 16).map_err(|_| {
DecodeError::InvalidData(format!("Invalid green component in hex color: {}", hex_str))
})?;
let b = u8::from_str_radix(&hex_str[5..7], 16).map_err(|_| {
DecodeError::InvalidData(format!("Invalid blue component in hex color: {}", hex_str))
})?;
InputValue::Color(r, g, b)
}
10 => {
let string = raw
.value
.as_str()
.ok_or_else(|| DecodeError::InvalidData("Expected a string".to_string()))?;
InputValue::Literal(Value::String(string.to_string()))
}
11 => {
let broadcast_name = raw
.value
.as_str()
.ok_or_else(|| DecodeError::InvalidData("Expected a string".to_string()))?;
InputValue::Broadcast(broadcast_name.to_string())
}
12 => {
let var_name = raw
.value
.as_str()
.ok_or_else(|| DecodeError::InvalidData("Expected a string".to_string()))?;
InputValue::Variable(var_name.to_string())
}
13 => {
let list_name = raw
.value
.as_str()
.ok_or_else(|| DecodeError::InvalidData("Expected a string".to_string()))?;
InputValue::List(list_name.to_string())
}
_ => {
return Err(DecodeError::InvalidData(format!(
"Unknown kind value: {}",
raw.kind
)))
}
};
Ok(BlockInput { shadow, value })
}
}