use crate::{
    Token,
    char_string::CharStringExt,
    expr::{AnchorStart, Expr, SequenceExpr},
};

use super::{ExprLinter, Lint, LintKind, Suggestion};
use crate::linting::expr_linter::Chunk;

pub struct ToTooChunkStartComma {
    expr: Box<dyn Expr>,
}

impl Default for ToTooChunkStartComma {
    fn default() -> Self {
        let expr = SequenceExpr::with(AnchorStart)
            .t_aco("to")
            .then_optional_whitespace()
            .then_comma();

        Self {
            expr: Box::new(expr),
        }
    }
}

impl ExprLinter for ToTooChunkStartComma {
    type Unit = Chunk;

    fn expr(&self) -> &dyn Expr {
        self.expr.as_ref()
    }

    fn match_to_lint(&self, tokens: &[Token], source: &[char]) -> Option<Lint> {
        let to_tok = tokens
            .iter()
            .find(|t| t.get_ch(source).eq_ch(&['t', 'o']))?;

        Some(Lint {
            span: to_tok.span,
            lint_kind: LintKind::WordChoice,
            suggestions: vec![Suggestion::replace_with_match_case_str(
                "too",
                to_tok.get_ch(source),
            )],
            message: "Use `too` here to mean ‘also’ or an excessive degree.".to_owned(),
            ..Default::default()
        })
    }

    fn description(&self) -> &str {
        "Detects `to` at the start of a clause before a comma."
    }
}
