use crate::validator::context::ValidationContext;
use crate::validator::error::ValidationError;
use crate::validator::result::ValidationResult;
use regex::Regex;

impl<'a> ValidationContext<'a> {
  pub(crate) fn validate_string(
    &self,
    result: &mut ValidationResult,
  ) -> Result<bool, ValidationError> {
    let current = self.instance;
    if let Some(s) = current.as_str() {
      if let Some(min) = self.schema.min_length
        && (s.chars().count() as f64) < min
      {
        result.errors.push(ValidationError {
          code: "MIN_LENGTH_VIOLATED".to_string(),
          message: format!("Length < min {}", min),
          path: self.path.to_string(),
        });
      }
      if let Some(max) = self.schema.max_length
        && (s.chars().count() as f64) > max
      {
        result.errors.push(ValidationError {
          code: "MAX_LENGTH_VIOLATED".to_string(),
          message: format!("Length > max {}", max),
          path: self.path.to_string(),
        });
      }
      if let Some(ref compiled_re) = self.schema.compiled_pattern {
        if !compiled_re.0.is_match(s) {
          result.errors.push(ValidationError {
            code: "PATTERN_VIOLATED".to_string(),
            message: format!("Pattern mismatch {:?}", self.schema.pattern),
            path: self.path.to_string(),
          });
        }
      } else if let Some(ref pattern) = self.schema.pattern
        && let Ok(re) = Regex::new(pattern)
        && !re.is_match(s)
      {
        result.errors.push(ValidationError {
          code: "PATTERN_VIOLATED".to_string(),
          message: format!("Pattern mismatch {}", pattern),
          path: self.path.to_string(),
        });
      }
    }
    Ok(true)
  }
}
