gitql_core/values/
array.rsuse std::any::Any;
use std::cmp::Ordering;
use gitql_ast::types::array::ArrayType;
use gitql_ast::types::base::DataType;
use super::base::Value;
use super::boolean::BoolValue;
use super::integer::IntValue;
#[derive(Clone)]
pub struct ArrayValue {
    pub values: Vec<Box<dyn Value>>,
    pub base_type: Box<dyn DataType>,
}
impl Value for ArrayValue {
    fn literal(&self) -> String {
        let mut str = String::new();
        let last_position = self.values.len() - 1;
        str += "[";
        for (pos, element) in self.values.iter().enumerate() {
            str += &element.literal();
            if pos != last_position {
                str += ", ";
            }
        }
        str += "]";
        str
    }
    fn equals(&self, other: &Box<dyn Value>) -> bool {
        if let Some(other_array) = other.as_any().downcast_ref::<ArrayValue>() {
            if !self.base_type.equals(&other_array.base_type) {
                return false;
            }
            let self_values = &self.values;
            let other_values = &other_array.values;
            if self.values.len() != other_values.len() {
                return false;
            }
            for i in 0..self.values.len() {
                if !self_values[i].equals(&other_values[i]) {
                    return false;
                }
            }
        }
        false
    }
    fn compare(&self, _other: &Box<dyn Value>) -> Option<Ordering> {
        None
    }
    fn data_type(&self) -> Box<dyn DataType> {
        Box::new(ArrayType {
            base: self.base_type.clone(),
        })
    }
    fn as_any(&self) -> &dyn Any {
        self
    }
    fn index_op(&self, index: &Box<dyn Value>) -> Result<Box<dyn Value>, String> {
        if let Some(index) = index.as_any().downcast_ref::<IntValue>() {
            if (index.value < 1) || (index.value as usize > self.values.len()) {
                return Err("Array Index must be between 1 and length of Array".to_string());
            }
            let array_index = (index.value - 1) as usize;
            return Ok(self.values[array_index].clone());
        }
        Err("Unexpected Array Index type".to_string())
    }
    fn slice_op(
        &self,
        start: &Option<Box<dyn Value>>,
        end: &Option<Box<dyn Value>>,
    ) -> Result<Box<dyn Value>, String> {
        if start.is_none() && end.is_none() {
            return Ok(Box::new(self.clone()));
        }
        let mut start_index: usize = 0;
        if start.is_some() {
            if let Some(start_value) = start.clone().unwrap().as_any().downcast_ref::<IntValue>() {
                if start_value.value < 1 || start_value.value >= self.values.len() as i64 {
                    return Err("Slice start must be between 1 and length of Array".to_string());
                }
                start_index = start_value.value as usize;
            }
        }
        let mut end_index: usize = self.values.len();
        if end.is_some() {
            if let Some(end_value) = end.clone().unwrap().as_any().downcast_ref::<IntValue>() {
                if end_value.value < start_index as i64
                    || end_value.value > self.values.len() as i64
                {
                    return Err("Slice end must be between start and length of Array".to_string());
                }
                end_index = end_value.value as usize;
            }
        }
        let slice = self.values[start_index..end_index].to_vec();
        Ok(Box::new(ArrayValue {
            values: slice,
            base_type: self.base_type.clone(),
        }))
    }
    fn logical_or_op(&self, other: &Box<dyn Value>) -> Result<Box<dyn Value>, String> {
        if let Some(other_array) = other.as_any().downcast_ref::<ArrayValue>() {
            for value in self.values.iter() {
                for other_value in other_array.values.iter() {
                    if value.equals(other_value) {
                        return Ok(Box::new(BoolValue { value: true }));
                    }
                }
            }
            return Ok(Box::new(BoolValue { value: false }));
        }
        Err("Unexpected Array overlap type".to_string())
    }
    fn contains_op(&self, other: &Box<dyn Value>) -> Result<Box<dyn Value>, String> {
        for value in self.values.iter() {
            if value.equals(other) {
                return Ok(Box::new(BoolValue { value: true }));
            }
        }
        Ok(Box::new(BoolValue { value: false }))
    }
}