use crate::core::hdlparam::HdlParam;
use crate::core::primitive_parser::PrimitiveText;
use crate::core::sv_parser::make_fast_from_syntaxtree;
use crate::core::vhdl_parser::make_fast_from_design_file;
use crate::core::vhdl_parser::vhdl_parse_str;
use crate::definition::def_types::*;
use crate::definition::get_scopes_from_syntax_tree;
use crate::definition::get_scopes_from_vhdl_fast;
use crate::diagnostics::{get_diagnostics, is_hidden};
use crate::server::LSPServer;
use crate::server::ProjectConfig;
use crate::utils::to_escape_path;
#[allow(unused)]
use log::info;
use log::{debug, error};
use pathdiff::diff_paths;
use ropey::{Rope, RopeSlice};
use serde_json::Value;
use std::cmp::min;
use std::collections::HashMap;
use std::env::current_dir;
#[allow(unused)]
use std::ops::Deref;
use std::ops::Range as StdRange;
use std::path::Path;
use std::path::PathBuf;
use std::str::FromStr;
use std::sync::{Arc, Condvar, Mutex, RwLock};
use std::thread;
use sv_parser::*;
use vhdl_lang::Project;
use thread::JoinHandle;
use tower_lsp::lsp_types::*;
use walkdir::WalkDir;

impl LSPServer {
    pub fn did_open(&self, params: DidOpenTextDocumentParams) -> PublishDiagnosticsParams {
        let document: TextDocumentItem = params.text_document;
        let uri = document.uri.clone();

        // check if doc is already added
        if self.srcs.names.read().unwrap().contains_key(&document.uri) {
            // convert to a did_change that replace the entire text
            self.did_change(DidChangeTextDocumentParams {
                text_document: VersionedTextDocumentIdentifier::new(document.uri, document.version),
                content_changes: vec![TextDocumentContentChangeEvent {
                    range: None,
                    range_length: None,
                    text: document.text,
                }],
            });
        } else {
            self.srcs.add(self, document);
        }
        
        // 生成诊断信息
        let urls = self.srcs.names.read().unwrap().keys().cloned().collect();
        let file_id = self.srcs.get_id(&uri);
        if let Some(file) = self.srcs.get_file(file_id) {
            let file = file.read().unwrap();
            let diagnostics = get_diagnostics(
                uri, 
                &file.text, 
                urls, 
                &self.conf.read().unwrap()
            );
            diagnostics
        } else {
            PublishDiagnosticsParams {
                uri,
                diagnostics: Vec::new(),
                version: None,
            }
        }
    }

    pub fn did_change(&self, params: DidChangeTextDocumentParams) {
        let file_id = self.srcs.get_id(&params.text_document.uri);
        if let Some(file) = self.srcs.get_file(file_id) {
            let mut file = file.write().unwrap();

            // 根据输入的 change 动态更新对应的代码的文本片段
            for change in params.content_changes {
                if change.range.is_none() {
                    file.text = Rope::from_str(&change.text);
                } else {
                    file.text.apply_change(&change);
                }
                file.last_change_range = change.range;
            }
            file.version = params.text_document.version;
            drop(file);
    
            // invalidate syntaxtree and wake parse thread
            let meta_data = self.srcs.get_meta_data(file_id).unwrap();
            let (lock, cvar) = &*meta_data.read().unwrap().valid_parse;
            let mut valid = lock.lock().unwrap();
            *valid = false;
            cvar.notify_all();
        }
    }

    pub fn did_save(&self, params: DidSaveTextDocumentParams) -> PublishDiagnosticsParams {
        let urls = self.srcs.names.read().unwrap().keys().cloned().collect();
        let file_id = self.srcs.get_id(&params.text_document.uri);
        let uri = params.text_document.uri.clone();

        if let Some(file) = self.srcs.get_file(file_id) {
            let file = file.read().unwrap();
            get_diagnostics(
                uri,
                &file.text,
                urls,
                &self.conf.read().unwrap(),
            )
        } else {
            PublishDiagnosticsParams {
                uri,
                diagnostics: Vec::new(),
                version: None,
            }
        }
    }

    pub fn did_delete_files(&self, params: DeleteFilesParams) {
        // 删除 sources 内对应的文件
        for file_delete in params.files {
            let url = Url::parse(&file_delete.uri).unwrap();
            let pathbuf = PathBuf::from_str(url.path()).unwrap();
            let pathbuf = to_escape_path(&pathbuf);
            let path_string = pathbuf.to_str().unwrap();

            {
                let mut fast_sync_controller = self.srcs.fast_sync_controller.write().unwrap();
                fast_sync_controller.remove(path_string);
            }

            self.srcs.hdl_param.delete_file(path_string);

            {
                let mut names = self.srcs.names.write().unwrap();
                names.remove(&url);
            }

            {
                let mut global_scope = self.srcs.scope_tree.write().unwrap();
                match &mut *global_scope {
                    Some(scope) => {
                        scope.defs.retain(|x| x.url() != url);
                        scope.scopes.retain(|x| x.url() != url);
                    },
                    None => {},
                }
            }

            {
                let mut vhdl_project = self.srcs.vhdl_project.write().unwrap();
                match &mut *vhdl_project {
                    Some(vhdl_project) => {
                        let config_file_strs = vhdl_project.config_file_strs.clone()
                                                            .into_iter()
                                                            .filter(|x| x != path_string)
                                                            .collect::<Vec<String>>();
                        let mut messages = Vec::new();
                        let config_str = format!(
                            r#"
                                [libraries]
                                digital_lsp.files = [{}]
                            "#, config_file_strs.join(",")
                        );
                        let config = vhdl_lang::Config::from_str(&config_str, Path::new(""));
                        if let Ok(mut config) = config {
                            config.append(&vhdl_project.std_config, &mut messages);
                            let mut project = Project::from_config(config, &mut messages);
                            project.analyse();
                            *vhdl_project = VhdlProject { project, std_config: vhdl_project.std_config.clone(), config_file_strs };
                        }
                    }
                    None => ()
                }
            }
        }
    }
}

/// The Source struct holds all file specific information
pub struct Source {
    /// id
    pub id: usize,
    /// uri
    pub uri: Url,
    /// 代码文本信息
    pub text: Rope,
    /// 版本号
    pub version: i32,
    /// 解析的 IR，分为 DesignFile（VHDL）和 SyntaxTree（SV）两种
    pub parse_ir: Option<ParseIR>,
    /// 用于在解析失败时恢复解析的量
    pub last_change_range: Option<Range>,
}

pub enum ParseIR {
    /// 基于 vhdl-parser 的IR，存放 VHDL
    #[allow(unused)]
    DesignFile(vhdl_lang::ast::DesignFile),
    /// 存放 sv 的 IR
    SyntaxTree(sv_parser::SyntaxTree)
}


/// file metadata, including whether or not the syntax tree is up to date
pub struct SourceMeta {
    pub id: usize,
    pub valid_parse: Arc<(Mutex<bool>, Condvar)>,
    #[allow(unused)]
    pub parse_handle: JoinHandle<()>,
}

/// find SystemVerilog/Verilog sources recursively from opened files
fn find_src_paths(dirs: &[PathBuf]) -> Vec<PathBuf> {
    let mut paths: Vec<PathBuf> = Vec::new();

    for dir in dirs {
        let walker = WalkDir::new(dir).into_iter();
        for entry in walker.filter_entry(|e| !is_hidden(e)) {
            let entry = entry.unwrap();
            if entry.file_type().is_file() && entry.path().extension().is_some() {
                let extension = entry.path().extension().unwrap();

                if extension == "sv" || extension == "svh" || extension == "v" || extension == "vh" {
                    let entry_path = entry.path().to_path_buf();
                    if !paths.contains(&entry_path) {
                        paths.push(entry_path);
                    }
                }
            }
        }
    }
    paths
}

/// The Sources struct manages all source files
pub struct Sources {
    // all files
    pub files: Arc<RwLock<Vec<Arc<RwLock<Source>>>>>,
    // map file urls to id
    pub names: Arc<RwLock<HashMap<Url, usize>>>,
    // file metadata
    pub meta: Arc<RwLock<Vec<Arc<RwLock<SourceMeta>>>>>,
    /// scope tree 类型的树形结构，用于提供 sv 的 lsp
    pub scope_tree: Arc<RwLock<Option<GenericScope>>>,
    // vhdl project, store vhdl design files, do lsp
    pub vhdl_project: Arc<RwLock<Option<VhdlProject>>>,
    // include directories, passed to parser to resolve `include
    pub include_dirs: Arc<RwLock<Vec<PathBuf>>>,
    // primitive instance text
    pub primitive_text: Arc<PrimitiveText>,
    /// hdlparam 后端实现
    pub hdl_param: Arc<HdlParam>,
    // 同步解析线程和发送 fast 请求的
    pub fast_sync_controller: Arc<RwLock<HashMap<String, Arc<RwLock<bool>>>>>,
    // lsp 配置相关的
    pub lsp_configuration: Arc<RwLock<HashMap<String, Value>>>
}

impl std::default::Default for Sources {
    fn default() -> Self {
        Self::new()
    }
}

impl Sources {
    pub fn new() -> Self {
        Self {
            files: Arc::new(RwLock::new(Vec::new())),
            names: Arc::new(RwLock::new(HashMap::new())),
            meta: Arc::new(RwLock::new(Vec::new())),
            scope_tree: Arc::new(RwLock::new(None)),
            vhdl_project: Arc::new(RwLock::new(None)),
            include_dirs: Arc::new(RwLock::new(Vec::new())),
            primitive_text: Arc::new(PrimitiveText::new()),
            hdl_param: Arc::new(HdlParam::new()),
            fast_sync_controller: Arc::new(RwLock::new(HashMap::<String, Arc<RwLock<bool>>>::new())),
            lsp_configuration: Arc::new(RwLock::new(HashMap::<String, Value>::new()))
        }
    }

    pub fn init_primitive(&self, tool_chain: &str, extension_path: &str) {
        let primitive_bin = format!("{}/resources/dide-lsp/static/{}/primitive.bin", extension_path, tool_chain);
        info!("attempt to find primitives in {}", primitive_bin);
        
        if let Some(primitive_xml) = crate::core::primitive_parser::load_primitive_bin(&primitive_bin) {
            let primitive_text_handle = self.primitive_text.clone();
            let hdl_param_handle = self.hdl_param.clone();
            for (name, template) in primitive_xml.name_to_template {
                // use "primitive/name" as a fake path
                let fake_path = "primitive/".to_string() + &name;
                hdl_param_handle.update_fast(fake_path, template.fast);
                primitive_text_handle.update_text(&name, &template.text);
            }
        }
    }

    /// 增加一个 hdl 文件，并为该文件添加单独的解析线程
    pub fn add(&self, server: &LSPServer, doc: TextDocumentItem) {
        // 对于当前的文件增加一个解析线程，不断进行解析和同步
        #[allow(clippy::mutex_atomic)] // https://github.com/rust-lang/rust-clippy/issues/1516
        let valid_parse = Arc::new((Mutex::new(false), Condvar::new()));
        let valid_parse2 = valid_parse.clone();
        let mut files = self.files.write().unwrap();
        let source = Arc::new(RwLock::new(Source {
            id: files.len(),
            uri: doc.uri.clone(),
            text: Rope::from_str(&doc.text),
            version: doc.version,
            parse_ir: None,
            last_change_range: None,
        }));
        let source_handle = source.clone();
        let scope_handle = self.scope_tree.clone();
        let project_handle = self.vhdl_project.clone();
        let hdl_param_handle = self.hdl_param.clone();
        let inc_dirs = self.include_dirs.clone();

        let uri = doc.uri.clone();

        let conf = server.conf.clone();

        info!("launch worker to parse {:?}", doc.uri.to_string());
        let language_id = doc.language_id.to_string();

        // 新建一个 fast controller 用于控制下方的解析线程和外部的请求函数
        let pathbuf = PathBuf::from_str(&doc.uri.path()).unwrap();
        let pathbuf = to_escape_path(&pathbuf);
        let path_string = pathbuf.to_str().unwrap();
        let mut fast_controller = self.fast_sync_controller.write().unwrap();
        let fast_lock = Arc::new(RwLock::new(true));
        fast_controller.insert(path_string.to_string(), fast_lock.clone());
        drop(fast_controller);

        // spawn parse thread
        let parse_handle = thread::spawn(move || {
            let (lock, cvar) = &*valid_parse2;
            loop {
                info!("do parse in {:?}, language_id: {:?}", uri.to_string(), language_id);

                // 此时 update fast 的地方为 write 会进行阻塞
                {
                    let _unused = fast_lock.read().unwrap();
                    // 从内存中直接获取增量更新系统维护的代码文本
                    let file = source_handle.read().unwrap();
                    let text = file.text.clone();
                    let uri = &file.uri.clone();

                    let range = &file.last_change_range.clone();
                    drop(file);
                    match language_id.as_str() {
                        "vhdl" => {
                            vhdl_parser_pipeline(
                                &conf,
                                &source_handle,
                                &scope_handle,
                                &project_handle,
                                &hdl_param_handle,
                                &text,
                                uri,
                            );
                        },
                        "verilog" | "systemverilog" => {
                            sv_parser_pipeline(
                                &conf,
                                &source_handle,
                                &scope_handle,
                                &hdl_param_handle,
                                &text,
                                uri,
                                range,
                                &inc_dirs.read().unwrap()
                            );
                        },
                        _ => {}
                    }
                }

                // 通过条件锁进行控制
                let mut valid = lock.lock().unwrap();
                *valid = true;
                cvar.notify_all();
                while *valid {
                    valid = cvar.wait(valid).unwrap();
                }
            }
        });
        files.push(source);
        let fid = files.len() - 1;
        self.meta
            .write()
            .unwrap()
            .push(Arc::new(RwLock::new(SourceMeta {
                id: fid,
                valid_parse,
                parse_handle,
            })));

        self.names.write().unwrap().insert(doc.uri, fid);
    }

    /// get file by id
    pub fn get_file(&self, id: usize) -> Option<Arc<RwLock<Source>>> {
        let files = self.files.read().ok()?;
        for file in files.iter() {
            let source = file.read().ok()?;
            if source.id == id {
                return Some(file.clone());
            }
        }
        None
    }

    /// get metadata by file id
    pub fn get_meta_data(&self, id: usize) -> Option<Arc<RwLock<SourceMeta>>> {
        let meta = self.meta.read().ok()?;
        for data in meta.iter() {
            let i = data.read().ok()?;
            if i.id == id {
                return Some(data.clone());
            }
        }
        None
    }

    /// wait for a valid parse
    pub fn wait_parse_ready(&self, id: usize, wait_valid: bool) {
        if let Some(file) = self.get_file(id) {
            let file = file.read().unwrap();
            if file.parse_ir.is_none() || wait_valid {
                drop(file);
                let meta_data = self.get_meta_data(id).unwrap();
                let (lock, cvar) = &*meta_data.read().unwrap().valid_parse;
                let mut valid = lock.lock().unwrap();
                while !*valid {
                    valid = cvar.wait(valid).unwrap();
                }
            }
        }
    }

    /// get file id from url
    pub fn get_id(&self, uri: &Url) -> usize {
        *self.names.read().unwrap().get(uri).unwrap()
    }

    /// compute identifier completions
    pub fn get_completions(
        &self,
        token: &str,
        byte_idx: usize,
        url: &Url,
    ) -> Option<CompletionList> {
        debug!("retrieving identifier completion for token: {}", &token);
        Some(CompletionList {
            is_incomplete: false,
            items: self
                .scope_tree
                .read()
                .ok()?
                .as_ref()?
                .get_completion(token, byte_idx, url),
        })
    }

    /// compute dot completions
    pub fn get_dot_completions(
        &self,
        token: &str,
        byte_idx: usize,
        url: &Url,
    ) -> Option<CompletionList> {
        debug!("retrieving dot completion for token: {}", &token);
        let tree = self.scope_tree.read().ok()?;
        Some(CompletionList {
            is_incomplete: false,
            items: tree
                .as_ref()?
                .get_dot_completion(token, byte_idx, url, tree.as_ref()?),
        })
    }

    #[allow(unused)]
    pub fn get_lsp_configuration_string_value(&self, name: &str) -> Option<String> {
        let lsp_configuration = self.lsp_configuration.read().unwrap();
        if let Some(Value::String(value)) = lsp_configuration.get(name) {
            return Some(value.to_string());
        }
        None
    }

    #[allow(unused)]
    pub fn get_lsp_configuration_i64_value(&self, name: &str) -> Option<i64> {
        let lsp_configuration = self.lsp_configuration.read().unwrap();
        if let Some(Value::Number(number)) = lsp_configuration.get(name) {
            return number.as_i64();
        }
        None
    }

    #[allow(unused)]
    pub fn get_lsp_configuration_bool_value(&self, name: &str) -> Option<bool> {
        let lsp_configuration = self.lsp_configuration.read().unwrap();
        if let Some(Value::Bool(value)) = lsp_configuration.get(name) {
            return Some(*value);
        }
        None
    }
}


pub fn recovery_sv_parse_with_retry(
    doc: &Rope,
    uri: &Url,
    last_change_range: &Option<Range>,
    inc_paths: &[PathBuf],
) -> Option<SyntaxTree>{
    if let Some(syntax_tree) = recovery_sv_parse(doc, uri, last_change_range, inc_paths, false) {
        Some(syntax_tree)
    } else {
        recovery_sv_parse(doc, uri, last_change_range, inc_paths, true)
    }
}

/// 更加稳定地解析 sv 和 v
/// 支持遇到错误进行自动修复，然后再解析
pub fn recovery_sv_parse(
    doc: &Rope,
    uri: &Url,
    last_change_range: &Option<Range>,
    inc_paths: &[PathBuf],
    allow_incomplete: bool,
) -> Option<SyntaxTree> {
    let mut parse_iterations = 1;
    let mut i = 0;
    let mut includes: Vec<PathBuf> = inc_paths.to_vec();
    let mut defines = HashMap::new();
    let mut reverted_change = false;
    let mut text = doc.clone();

    let recover_text_by_byte_idx = |byte_idx: usize, reverted_change: &mut bool, text: &mut Rope| {
        let mut line_start = text.byte_to_line(byte_idx);
        let mut line_end = text.byte_to_line(byte_idx) + 1;

        // println!("byte: {byte_idx}, line_start: {line_start}, line_end: {line_end}");
    
        if !(*reverted_change) {
            if let Some(range) = last_change_range {
                line_start = range.start.line as usize;
                line_end = range.end.line as usize + 1;
                *reverted_change = true;
            }
        }

        // 把 last_change 处的地方替换成空格
        for line_idx in line_start .. line_end {
            let line = text.line(line_idx);
            let start_char = text.line_to_char(line_idx);
            let line_length = line.len_chars();
            text.remove(start_char..(start_char + line_length - 1));
            text.insert(start_char, &" ".to_owned().repeat(line_length));
        }
    };

    // 最多解析 500 次
    while i < parse_iterations && i < 500 {
        i += 1;
        match parse_sv_str(
            &text.to_string(),
            uri.to_file_path().unwrap(),
            &defines,
            &includes,
            true,
            allow_incomplete
        ) {
            Ok((syntax_tree, _)) => {
                return Some(syntax_tree);
            }
            Err(err) => {
                // println!("err: {err:?}");
                match err {
                    // 语法错误
                    sv_parser::Error::Parse(trace) => match trace {
                        Some((_, byte_idx)) => {
                            // 把出错的地方替换成空格
                            recover_text_by_byte_idx(byte_idx, &mut reverted_change, &mut text);
                            parse_iterations += 1;
                        }
                        None => return None,
                    },
                    
                    // 遇到 include 错误，那就把提示中的 include 加入解析中再次解析
                    sv_parser::Error::Include { source: x } => {
                        if let sv_parser::Error::File { source: _, path: z } = *x {
                            // Include paths have to be relative to the working directory
                            // so we have to convert a source file relative path to a working directory
                            // relative path. This should have been handled by sv-parser
                            let mut inc_path_given = z.clone();
                            let mut uri_path = uri.to_file_path().unwrap();
                            uri_path.pop();
                            let rel_path = diff_paths(uri_path, current_dir().unwrap()).unwrap();
                            inc_path_given.pop();
                            let inc_path = rel_path.join(inc_path_given);
                            if !includes.contains(&inc_path) {
                                includes.push(inc_path);
                            } else {
                                error!("parser: include error: {:?}", z);
                                break;
                            }
                            parse_iterations += 1;
                        }
                    }

                    // 宏定义不存在的错误
                    sv_parser::Error::DefineNotFound(not_found_macro_name) => {
                        let com_define = Define {
                            identifier: not_found_macro_name.to_string(),
                            arguments: Vec::new(),
                            text: Some(DefineText {text: "UNKNOWN_MACRO".to_string(), origin: None})
                        };
                        defines.insert(not_found_macro_name, Some(com_define));
                        parse_iterations += 1;
                    }
                    sv_parser::Error::Preprocess(trace) => match trace {
                        Some((_, byte_idx)) => {
                            // 把出错的地方替换成空格
                            // println!("text {text:?}");
                            recover_text_by_byte_idx(byte_idx, &mut reverted_change, &mut text);
                            parse_iterations += 1;
                        }
                        None => return None
                    }
                    sv_parser::Error::DefineArgNotFound(trace) => match trace {
                        Some((_, start_byte_idx, _)) => {
                            recover_text_by_byte_idx(start_byte_idx, &mut reverted_change, &mut text);
                            // recover_text_by_byte_idx(end_byte_idx, &mut reverted_change, &mut text);
                            parse_iterations += 1;
                        }
                        _ => return None
                    }
                    sv_parser::Error::DefineNoArgs(trace) => match trace {
                        Some((_, start_byte_idx, _)) => {
                            recover_text_by_byte_idx(start_byte_idx, &mut reverted_change, &mut text);
                            parse_iterations += 1;
                        }
                        _ => return None
                    }
                    _ => error!("parse error, {:?}", err),
                };
            }
        }
    }
    None

}

pub fn sv_parser_pipeline(
    #[allow(unused)]
    conf: &Arc<RwLock<ProjectConfig>>,
    source_handle: &Arc<RwLock<Source>>,
    scope_handle: &Arc<RwLock<Option<GenericScope>>>,
    hdl_param_handle: &Arc<HdlParam>,
    doc: &Rope,
    uri: &Url,
    last_change_range: &Option<Range>,
    include_dirs: &Vec<PathBuf>
) {
    if doc.len_chars() == 0 {
        return;
    }
    
    let path = match PathBuf::from_str(uri.path()) {
        Ok(path) => path,
        Err(error) => {
            info!("error happen in <goto_include_definition>: {:?}", error);
            return;
        }
    };
    let escape_path = to_escape_path(&path);
    let escape_path_string = escape_path.to_str().unwrap_or("");
    if escape_path_string.len() == 0 {
        info!("error happen in [sv_parser_pipeline], escape_path_string is empty");
        return;
    }

    info!("debug, parse: {:?}", path);
    let syntax_tree = recovery_sv_parse_with_retry(
        doc,
        uri,
        last_change_range,
        include_dirs
    );
    info!("finish parse {:?}", path);

    // 更新 scope tree
    let mut scope_tree = match &syntax_tree {
        Some(tree) => get_scopes_from_syntax_tree(tree, uri),
        None => None,
    };

    let mut file = source_handle.write().unwrap();

    // 加入语法树 & 更新 fast
    if let Some(syntax_tree) = syntax_tree {
        if let Ok(fast) = make_fast_from_syntaxtree(&syntax_tree, &escape_path) {
            hdl_param_handle.update_fast(escape_path_string.to_string(), fast);
        }
        let parse_ir = ParseIR::SyntaxTree(syntax_tree);
        file.parse_ir = Some(parse_ir);
    } else {
        file.parse_ir = None;
    }
    // file.syntax_tree = syntax_tree;
    drop(file);

    info!("finish parse {:?}", uri.to_string());

    // 更新 global_scope，用于 sv 的解析
    // global_scope 为全局最大的那个 scope，它的 scopes 和 defs 下的元素和每一个文件一一对应
    let mut global_scope = scope_handle.write().unwrap();
    match &mut *global_scope {
        Some(scope) => match &mut scope_tree {
            Some(tree) => {
                // 更新所有 uri 为当前 uri 的文件结构
                scope.defs.retain(|x| &x.url() != uri);
                scope.scopes.retain(|x| &x.url() != uri);

                scope.defs.append(&mut tree.defs);
                scope.scopes.append(&mut tree.scopes);
            }
            None => (),
        },
        // 使用 scope_tree 来更新全局的 scope
        None => *global_scope = scope_tree,
    }
    // eprintln!("{:#?}", *global_scope);
    drop(global_scope);
}

pub fn vhdl_parser_pipeline(
    conf: &Arc<RwLock<ProjectConfig>>,
    source_handle: &Arc<RwLock<Source>>,
    scope_handle: &Arc<RwLock<Option<GenericScope>>>,
    project_handle: &Arc<RwLock<Option<VhdlProject>>>,
    hdl_param_handle: &Arc<HdlParam>,
    doc: &Rope,
    uri: &Url
) {
    if doc.len_chars() == 0 {
        return;
    }

    let path = match PathBuf::from_str(uri.path()) {
        Ok(path) => path,
        Err(error) => {
            info!("error happen in <goto_include_definition>: {:?}", error);
            return;
        }
    };
    let escape_path = to_escape_path(&path);
    let escape_path_string = escape_path.to_str().unwrap_or("");
    if escape_path_string.len() == 0 {
        info!("error happen in [vhdl_parser_pipeline], escape_path_string is empty");
        return;
    }

    let extension_path = {
        let configure = conf.read().unwrap();
        configure.extension_path.to_string()
    };

    let mut file = source_handle.write().unwrap();
    let text = doc.to_string();
    let mut scope_tree = if let Some(design_file) = vhdl_parse_str(&escape_path, &text) {
        if let Some(mut fast) = make_fast_from_design_file(&design_file) {
            let parse_ir = ParseIR::DesignFile(design_file);
            file.parse_ir = Some(parse_ir);

            for module in &fast.content {
                info!("parse port number: {:?}", module.ports.len());
            }

            let file_type = {
                let fast_map = hdl_param_handle.path_to_hdl_file.read().unwrap();
                if let Some(hdl_file) = fast_map.get(escape_path_string) {
                    hdl_file.fast.file_type.to_string()
                } else {
                    if let Some(relative_path) = escape_path_string.strip_prefix(&extension_path) {
                        if relative_path.starts_with("/user/ip") || relative_path.starts_with("user/ip") {
                            "ip".to_string()
                        } else {
                            "common".to_string()
                        }
                    } else {
                        "common".to_string()
                    }                    
                }
            };

            fast.file_type = file_type;
            hdl_param_handle.update_fast(escape_path_string.to_string(), fast.clone());
            let scope_tree = get_scopes_from_vhdl_fast(&fast, doc, uri);
            scope_tree
        } else {
            None
        }
    } else {
        file.parse_ir = None;
        None
    };
    drop(file);


    info!("finish parse {:?}", uri.to_string());

    // 更新 global_scope，用于 sv 的解析
    // global_scope 为全局最大的那个 scope，它的 scopes 和 defs 下的元素和每一个文件一一对应
    let mut global_scope = scope_handle.write().unwrap();
    match &mut *global_scope {
        Some(scope) => match &mut scope_tree {
            Some(tree) => {
                // 更新所有 uri 为当前 uri 的文件结构
                scope.defs.retain(|x| &x.url() != uri);
                scope.scopes.retain(|x| &x.url() != uri);

                scope.defs.append(&mut tree.defs);
                scope.scopes.append(&mut tree.scopes);
            }
            None => (),
        },
        // 使用 scope_tree 来更新全局的 scope
        None => *global_scope = scope_tree,
    }
    // eprintln!("{:#?}", *global_scope);

    let mut global_project = project_handle.write().unwrap();
    match &mut *global_project {
        Some(vhdl_project) => {
            if let Some(source) = vhdl_project.project.get_source(&escape_path) {
                source.change(None, &doc.to_string());
                vhdl_project.project.update_source(&source);
                vhdl_project.project.analyse();
            } else {
                vhdl_project.config_file_strs.push(format!("{:?}", escape_path));
                let mut messages = Vec::new();
                let config_str = format!(
                    r#"
                        [libraries]
                        digital_lsp.files = [{}]
                    "#, vhdl_project.config_file_strs.join(",")
                );
                let config = vhdl_lang::Config::from_str(&config_str, Path::new(""));
                if let Ok(mut config) = config {
                    config.append(&vhdl_project.std_config, &mut messages);
                    let mut project = Project::from_config(config, &mut messages);
                    project.analyse();
                    *vhdl_project = VhdlProject { project, std_config: vhdl_project.std_config.clone(), config_file_strs: vhdl_project.config_file_strs.clone() };
                }
            }
        }
        None => {
            let std_cfg_path = match PathBuf::from_str(&(extension_path + "/resources/dide-lsp/static/vhdl_std_lib/vhdl_ls.toml")) {
                Ok(path) => path,
                Err(e) => {
                    info!("error happen in <vhdl_parse_pipeline>: {:?}", e);
                    return;
                }
            };
            match vhdl_lang::Config::read_file_path(&std_cfg_path) {
                Ok(std_config) => {
                    let config_str = format!(
                        r#"
                            [libraries]
                            digital_lsp.files = [{:?}]
                        "#, escape_path
                    );
                    let mut config_file_strs = Vec::new();
                    config_file_strs.push(format!("{:?}", escape_path));
                    let config = vhdl_lang::Config::from_str(&config_str, Path::new(""));
                    if let Ok(mut config) = config {
                        let mut messages = Vec::new();
                        config.append(&std_config, &mut messages);
                        let mut project = Project::from_config(config, &mut messages);
                        project.analyse();
                        *global_project = Some(VhdlProject { project, std_config, config_file_strs });
                    }
                }
                Err(e) => info!("error happen in <vhdl_parse_pipeline>: Can't load standard vhdl lib from {std_cfg_path:#?} because {e:#?}")
            }
        }
    }
    drop(global_project);

    drop(global_scope);
}

//TODO: add bounds checking for utf8<->utf16 conversions
/// This trait defines some helper functions to convert between lsp types
/// and char/byte positions
pub trait LSPSupport {
    fn pos_to_byte(&self, pos: &Position) -> usize;
    fn pos_to_char(&self, pos: &Position) -> usize;
    fn byte_to_pos(&self, byte_idx: usize) -> Position;
    fn char_to_pos(&self, char_idx: usize) -> Position;
    fn range_to_char_range(&self, range: &Range) -> StdRange<usize>;
    fn char_range_to_range(&self, range: StdRange<usize>) -> Range;
    fn apply_change(&mut self, change: &TextDocumentContentChangeEvent);
}

/// Extend ropey's Rope type with lsp convenience functions
impl LSPSupport for Rope {
    fn pos_to_byte(&self, pos: &Position) -> usize {
        return self.char_to_byte(self.pos_to_char(pos));
    }
    fn pos_to_char(&self, pos: &Position) -> usize {
        let line_slice = self.line(pos.line as usize);
        return self.line_to_char(pos.line as usize) + line_slice.utf16_cu_to_char(pos.character as usize);
    }
    fn byte_to_pos(&self, byte_idx: usize) -> Position {
        // info!("byte_idx: {byte_idx}");
        let self_len = if self.len_bytes() != 0 { self.len_bytes() - 1 } else { 0 };
        return self.char_to_pos(self.byte_to_char(min(byte_idx, self_len)));
    }
    fn char_to_pos(&self, char_idx: usize) -> Position {
        let line = self.char_to_line(char_idx);
        let line_slice = self.line(line);
        return Position {
            line: line as u32,
            character: line_slice.char_to_utf16_cu(char_idx - self.line_to_char(line)) as u32,
        };
    }
    fn range_to_char_range(&self, range: &Range) -> StdRange<usize> {
        return self.pos_to_char(&range.start)..self.pos_to_char(&range.end);
    }
    fn char_range_to_range(&self, range: StdRange<usize>) -> Range {
        return Range {
            start: self.char_to_pos(range.start),
            end: self.char_to_pos(range.end),
        };
    }
    fn apply_change(&mut self, change: &TextDocumentContentChangeEvent) {
        if let Some(range) = change.range {
            let char_range = self.range_to_char_range(&range);
            self.remove(char_range.clone());
            if !change.text.is_empty() {
                self.insert(char_range.start, &change.text);
            }
        }
    }
}

impl<'a> LSPSupport for RopeSlice<'a> {
    fn pos_to_byte(&self, pos: &Position) -> usize {
        self.char_to_byte(self.pos_to_char(pos))
    }
    fn pos_to_char(&self, pos: &Position) -> usize {
        let line_slice = self.line(pos.line as usize);
        self.line_to_char(pos.line as usize) + line_slice.utf16_cu_to_char(pos.character as usize)
    }
    fn byte_to_pos(&self, byte_idx: usize) -> Position {
        // info!("byte_idx: {byte_idx}");
        self.char_to_pos(self.byte_to_char(min(byte_idx, self.len_bytes() - 1)))
    }
    fn char_to_pos(&self, char_idx: usize) -> Position {
        let line = self.char_to_line(char_idx);
        let line_slice = self.line(line);
        Position {
            line: line as u32,
            character: line_slice.char_to_utf16_cu(char_idx - self.line_to_char(line)) as u32,
        }
    }
    fn range_to_char_range(&self, range: &Range) -> StdRange<usize> {
        self.pos_to_char(&range.start)..self.pos_to_char(&range.end)
    }
    fn char_range_to_range(&self, range: StdRange<usize>) -> Range {
        Range {
            start: self.char_to_pos(range.start),
            end: self.char_to_pos(range.end),
        }
    }
    fn apply_change(&mut self, _: &TextDocumentContentChangeEvent) {
        panic!("can't edit a rope slice");
    }
}
