use std::{path::PathBuf, str::FromStr};

use serde_json::Value;
use tower_lsp::lsp_types::{Diagnostic, Url};

use crate::{diagnostics::provide_diagnostics, server::Backend, utils::{from_uri_to_escape_path_string, open_doc_as_rope}};

/// 前端请求，发布诊断结果，仅在初始化和修改配置时触发
/// 参数为 [file_path: string]
pub async fn publish_diagnostics(
    backend: &Backend,
    arguments: Vec<Value>
) -> tower_lsp::jsonrpc::Result<Option<Value>> {
    let path_string = arguments.get(0).unwrap().to_string();
    let uri = Url::from_file_path(path_string).unwrap();
    let path_string = from_uri_to_escape_path_string(&uri).unwrap();
    let pathbuf = PathBuf::from_str(&path_string).unwrap();

    // 考虑到性能，如果后端文本缓冲器内存在当前路径的 文本备份，则使用它作为 rope
    // 否则，进行 IO 后再转换
    let rope = open_doc_as_rope(&pathbuf).unwrap();
    let diagnostics_params = provide_diagnostics(uri, &rope, &backend.server);
    backend.client.publish_diagnostics(
        diagnostics_params.uri,
        diagnostics_params.diagnostics,
        None
    ).await;

    Ok(None)
}

/// 前端请求，清除诊断结果，仅在初始化和修改配置时触发
/// 参数为 [file_path: string]
pub async fn clear_diagnostics(
    backend: &Backend,
    arguments: Vec<Value>
) -> tower_lsp::jsonrpc::Result<Option<Value>> {
    let path_string = arguments.get(0).unwrap().to_string();
    let uri = Url::from_file_path(path_string).unwrap();

    let diagnostics = Vec::<Diagnostic>::new();
    backend.client.publish_diagnostics(uri, diagnostics, None).await;

    Ok(None)
}