use clippy_config::Conf;
use clippy_utils::diagnostics::span_lint_and_then;
use clippy_utils::source::{SpanRangeExt, snippet_opt};
use rustc_ast::ast::{Expr, ExprKind};
use rustc_ast::token::LitKind;
use rustc_errors::Applicability;
use rustc_lint::{EarlyContext, EarlyLintPass, LintContext};
use rustc_session::impl_lint_pass;
use rustc_span::{BytePos, Pos, Span};
use std::iter::once;
use std::ops::ControlFlow;

declare_clippy_lint! {
    /// ### What it does
    /// Checks for raw string literals with an unnecessary amount of hashes around them.
    ///
    /// ### Why is this bad?
    /// It's just unnecessary, and makes it look like there's more escaping needed than is actually
    /// necessary.
    ///
    /// ### Example
    /// ```no_run
    /// let r = r###"Hello, "world"!"###;
    /// ```
    /// Use instead:
    /// ```no_run
    /// let r = r#"Hello, "world"!"#;
    /// ```
    #[clippy::version = "1.72.0"]
    pub NEEDLESS_RAW_STRING_HASHES,
    pedantic,
    "suggests reducing the number of hashes around a raw string literal"
}

declare_clippy_lint! {
    /// ### What it does
    /// Checks for raw string literals where a string literal can be used instead.
    ///
    /// ### Why restrict this?
    /// For consistent style by using simpler string literals whenever possible.
    ///
    /// However, there are many cases where using a raw string literal is more
    /// idiomatic than a string literal, so it's opt-in.
    ///
    /// ### Example
    /// ```no_run
    /// let r = r"Hello, world!";
    /// ```
    /// Use instead:
    /// ```no_run
    /// let r = "Hello, world!";
    /// ```
    #[clippy::version = "1.72.0"]
    pub NEEDLESS_RAW_STRINGS,
    restriction,
    "suggests using a string literal when a raw string literal is unnecessary"
}

impl_lint_pass!(RawStrings => [NEEDLESS_RAW_STRINGS, NEEDLESS_RAW_STRING_HASHES]);

pub struct RawStrings {
    pub allow_one_hash_in_raw_strings: bool,
}

impl RawStrings {
    pub fn new(conf: &'static Conf) -> Self {
        Self {
            allow_one_hash_in_raw_strings: conf.allow_one_hash_in_raw_strings,
        }
    }
}

impl EarlyLintPass for RawStrings {
    fn check_expr(&mut self, cx: &EarlyContext<'_>, expr: &Expr) {
        if let ExprKind::FormatArgs(format_args) = &expr.kind
            && !format_args.span.in_external_macro(cx.sess().source_map())
            && format_args.span.check_source_text(cx, |src| src.starts_with('r'))
            && let Some(str) = snippet_opt(cx.sess(), format_args.span)
            && let count_hash = str.bytes().skip(1).take_while(|b| *b == b'#').count()
            && let Some(str) = str.get(count_hash + 2..str.len() - count_hash - 1)
        {
            self.check_raw_string(
                cx,
                str,
                format_args.span,
                "r",
                u8::try_from(count_hash).unwrap(),
                "string",
            );
        }

        if let ExprKind::Lit(lit) = expr.kind
            && let (prefix, max) = match lit.kind {
                LitKind::StrRaw(max) => ("r", max),
                LitKind::ByteStrRaw(max) => ("br", max),
                LitKind::CStrRaw(max) => ("cr", max),
                _ => return,
            }
            && !expr.span.in_external_macro(cx.sess().source_map())
            && expr.span.check_source_text(cx, |src| src.starts_with(prefix))
        {
            self.check_raw_string(cx, lit.symbol.as_str(), expr.span, prefix, max, lit.kind.descr());
        }
    }
}

impl RawStrings {
    fn check_raw_string(&self, cx: &EarlyContext<'_>, str: &str, lit_span: Span, prefix: &str, max: u8, descr: &str) {
        if !str.contains(['\\', '"']) {
            span_lint_and_then(
                cx,
                NEEDLESS_RAW_STRINGS,
                lit_span,
                "unnecessary raw string literal",
                |diag| {
                    let (start, end) = hash_spans(lit_span, prefix.len(), 0, max);

                    // BytePos: skip over the `b` in `br`, we checked the prefix appears in the source text
                    let r_pos = lit_span.lo() + BytePos::from_usize(prefix.len() - 1);
                    let start = start.with_lo(r_pos);

                    let mut remove = vec![(start, String::new())];
                    // avoid debug ICE from empty suggestions
                    if !end.is_empty() {
                        remove.push((end, String::new()));
                    }

                    diag.multipart_suggestion(
                        format!("use a plain {descr} literal instead"),
                        remove,
                        Applicability::MachineApplicable,
                    );
                },
            );
            if !cx.get_lint_level_spec(NEEDLESS_RAW_STRINGS).is_allow() {
                return;
            }
        }

        let mut req = {
            let mut following_quote = false;
            let mut req = 0;
            // `once` so a raw string ending in hashes is still checked
            let num = str.as_bytes().iter().chain(once(&0)).try_fold(0u8, |acc, &b| {
                match b {
                    b'"' if !following_quote => (following_quote, req) = (true, 1),
                    b'#' => req += u8::from(following_quote),
                    _ => {
                        if following_quote {
                            following_quote = false;

                            if req == max {
                                return ControlFlow::Break(req);
                            }

                            return ControlFlow::Continue(acc.max(req));
                        }
                    },
                }

                ControlFlow::Continue(acc)
            });

            match num {
                ControlFlow::Continue(num) | ControlFlow::Break(num) => num,
            }
        };
        if self.allow_one_hash_in_raw_strings {
            req = req.max(1);
        }
        if req < max {
            span_lint_and_then(
                cx,
                NEEDLESS_RAW_STRING_HASHES,
                lit_span,
                "unnecessary hashes around raw string literal",
                |diag| {
                    let (start, end) = hash_spans(lit_span, prefix.len(), req, max);

                    let message = match max - req {
                        _ if req == 0 => format!("remove all the hashes around the {descr} literal"),
                        1 => format!("remove one hash from both sides of the {descr} literal"),
                        n => format!("remove {n} hashes from both sides of the {descr} literal"),
                    };

                    diag.multipart_suggestion(
                        message,
                        vec![(start, String::new()), (end, String::new())],
                        Applicability::MachineApplicable,
                    );
                },
            );
        }
    }
}

/// Returns spans pointing at the unneeded hashes, e.g. for a `req` of `1` and `max` of `3`:
///
/// ```ignore
/// r###".."###
///   ^^    ^^
/// ```
fn hash_spans(literal_span: Span, prefix_len: usize, req: u8, max: u8) -> (Span, Span) {
    let literal_span = literal_span.data();

    // BytePos: we checked prefix appears literally in the source text
    let hash_start = literal_span.lo + BytePos::from_usize(prefix_len);
    let hash_end = literal_span.hi;

    // BytePos: req/max are counts of the ASCII character #
    let start = Span::new(
        hash_start + BytePos(req.into()),
        hash_start + BytePos(max.into()),
        literal_span.ctxt,
        None,
    );
    let end = Span::new(
        hash_end - BytePos(req.into()),
        hash_end - BytePos(max.into()),
        literal_span.ctxt,
        None,
    );

    (start, end)
}
