use std::cmp;
use std::string::String;
use std::usize;

use crate::clean::{self, DocFragment, Item};
use crate::core::DocContext;
use crate::fold::{self, DocFolder};
use crate::passes::Pass;

#[cfg(test)]
mod tests;

pub const UNINDENT_COMMENTS: Pass = Pass {
    name: "unindent-comments",
    run: unindent_comments,
    description: "removes excess indentation on comments in order for markdown to like it",
};

pub fn unindent_comments(krate: clean::Crate, _: &DocContext<'_>) -> clean::Crate {
    CommentCleaner.fold_crate(krate)
}

struct CommentCleaner;

impl fold::DocFolder for CommentCleaner {
    fn fold_item(&mut self, mut i: Item) -> Option<Item> {
        i.attrs.unindent_doc_comments();
        self.fold_item_recur(i)
    }
}

impl clean::Attributes {
    pub fn unindent_doc_comments(&mut self) {
        unindent_fragments(&mut self.doc_strings);
    }
}

fn unindent_fragments(docs: &mut Vec<DocFragment>) {
    for fragment in docs {
        match *fragment {
            DocFragment::SugaredDoc(_, _, ref mut doc_string)
            | DocFragment::RawDoc(_, _, ref mut doc_string)
            | DocFragment::Include(_, _, _, ref mut doc_string) => {
                *doc_string = unindent(doc_string)
            }
        }
    }
}

fn unindent(s: &str) -> String {
    let lines = s.lines().collect::<Vec<&str>>();
    let mut saw_first_line = false;
    let mut saw_second_line = false;
    let min_indent = lines.iter().fold(usize::MAX, |min_indent, line| {
        // After we see the first non-whitespace line, look at
        // the line we have. If it is not whitespace, and therefore
        // part of the first paragraph, then ignore the indentation
        // level of the first line
        let ignore_previous_indents =
            saw_first_line && !saw_second_line && !line.chars().all(|c| c.is_whitespace());

        let min_indent = if ignore_previous_indents { usize::MAX } else { min_indent };

        if saw_first_line {
            saw_second_line = true;
        }

        if line.chars().all(|c| c.is_whitespace()) {
            min_indent
        } else {
            saw_first_line = true;
            let mut whitespace = 0;
            line.chars().all(|char| {
                // Compare against either space or tab, ignoring whether they
                // are mixed or not
                if char == ' ' || char == '\t' {
                    whitespace += 1;
                    true
                } else {
                    false
                }
            });
            cmp::min(min_indent, whitespace)
        }
    });

    if !lines.is_empty() {
        let mut unindented = vec![lines[0].trim_start().to_string()];
        unindented.extend_from_slice(
            &lines[1..]
                .iter()
                .map(|&line| {
                    if line.chars().all(|c| c.is_whitespace()) {
                        line.to_string()
                    } else {
                        assert!(line.len() >= min_indent);
                        line[min_indent..].to_string()
                    }
                })
                .collect::<Vec<_>>(),
        );
        unindented.join("\n")
    } else {
        s.to_string()
    }
}
