use std::{ops::Range, str::FromStr};

use codespan_reporting::diagnostic::{Diagnostic, Label, LabelStyle, Severity};
use tracing::instrument;

use crate::{
    state::{toml_error_to_diagnostic, FileId, TomlError, Treehouse},
    tree::{self, ast::Roots},
};

pub struct ErrorsEmitted;

#[instrument(skip(input))]
pub fn parse_tree_with_diagnostics(
    file_id: FileId,
    input: &str,
) -> Result<Roots, Vec<Diagnostic<FileId>>> {
    Roots::parse(&mut tree::pull::Parser { input, position: 0 }).map_err(|error| {
        vec![Diagnostic {
            severity: Severity::Error,
            code: Some("tree".into()),
            message: error.kind.to_string(),
            labels: vec![Label {
                style: LabelStyle::Primary,
                file_id,
                range: error.range,
                message: String::new(),
            }],
            notes: vec![],
        }]
    })
}

pub fn parse_toml_with_diagnostics(
    treehouse: &mut Treehouse,
    file_id: FileId,
    range: Range<usize>,
) -> Result<toml_edit::Document, Vec<Diagnostic<FileId>>> {
    let input = &treehouse.source(file_id).input()[range.clone()];
    toml_edit::Document::from_str(input).map_err(|error| {
        vec![toml_error_to_diagnostic(TomlError {
            message: error.message().to_owned(),
            span: error.span(),
            file_id,
            input_range: range.clone(),
        })]
    })
}
