use std::{convert::TryFrom, time::Duration};
use regex::bytes::Regex;
use serde_with::serde_as;
use snafu::{ResultExt, Snafu};
use vector_lib::configurable::configurable_component;
use crate::line_agg;
#[serde_as]
#[configurable_component]
#[derive(Clone, Debug, PartialEq, Eq)]
#[serde(deny_unknown_fields)]
pub struct MultilineConfig {
    #[configurable(metadata(docs::examples = "^[\\s]+"))]
    #[configurable(metadata(docs::examples = "\\\\$"))]
    #[configurable(metadata(docs::examples = "^(INFO|ERROR) "))]
    #[configurable(metadata(docs::examples = ";$"))]
    pub start_pattern: String,
    #[configurable(metadata(docs::examples = "^[\\s]+"))]
    #[configurable(metadata(docs::examples = "\\\\$"))]
    #[configurable(metadata(docs::examples = "^(INFO|ERROR) "))]
    #[configurable(metadata(docs::examples = ";$"))]
    pub condition_pattern: String,
    #[configurable(derived)]
    pub mode: line_agg::Mode,
    #[serde_as(as = "serde_with::DurationMilliSeconds<u64>")]
    #[configurable(metadata(docs::examples = 1000))]
    #[configurable(metadata(docs::examples = 600000))]
    #[configurable(metadata(docs::human_name = "Timeout"))]
    pub timeout_ms: Duration,
}
impl TryFrom<&MultilineConfig> for line_agg::Config {
    type Error = Error;
    fn try_from(config: &MultilineConfig) -> Result<Self, Self::Error> {
        let MultilineConfig {
            start_pattern,
            condition_pattern,
            mode,
            timeout_ms,
        } = config;
        let start_pattern = Regex::new(start_pattern)
            .with_context(|_| InvalidMultilineStartPatternSnafu { start_pattern })?;
        let condition_pattern = Regex::new(condition_pattern)
            .with_context(|_| InvalidMultilineConditionPatternSnafu { condition_pattern })?;
        let timeout = *timeout_ms;
        Ok(Self {
            start_pattern,
            condition_pattern,
            mode: *mode,
            timeout,
        })
    }
}
#[derive(Debug, Snafu)]
pub enum Error {
    #[snafu(display(
        "unable to parse multiline start pattern from {:?}: {}",
        start_pattern,
        source
    ))]
    InvalidMultilineStartPattern {
        start_pattern: String,
        source: regex::Error,
    },
    #[snafu(display(
        "unable to parse multiline condition pattern from {:?}: {}",
        condition_pattern,
        source
    ))]
    InvalidMultilineConditionPattern {
        condition_pattern: String,
        source: regex::Error,
    },
}