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_units;
use crate::core::vhdl_parser::vhdl_parse_str;
use crate::core::scope_tree::common::*;
use crate::core::scope_tree::get_scopes_from_syntax_tree;
use crate::core::scope_tree::get_scopes_from_vhdl_fast;
use crate::diagnostics::provide_diagnostics;
use crate::server::LspServer;
use crate::server::LspConfiguration;
use crate::utils::from_uri_to_escape_path_string;
use crate::utils::to_escape_path;
#[allow(unused)]
use log::{info, debug, error};
use pathdiff::diff_paths;
use ropey::{Rope, RopeSlice};
use serde_json::Value;
use vhdl_lang::ast::DesignFile;
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;
use std::sync::{Condvar, Mutex, RwLock};
use std::thread;
use sv_parser::*;
use vhdl_lang::Project;
use thread::JoinHandle;
use tower_lsp::lsp_types::*;

impl LspServer {
    pub fn did_open(&self, params: DidOpenTextDocumentParams) -> PublishDiagnosticsParams {
        let document: TextDocumentItem = params.text_document;
        let uri = document.uri.clone();
        let path_string = from_uri_to_escape_path_string(&uri).unwrap();
        
        if self.srcs.contain_source(&path_string) {
            // 如果已经存在了，则进行增量更新
            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);
        }


        // 生成诊断信息
        if let Some(source) = self.srcs.get_source(&path_string) {
            let source = source.read().unwrap();
            let diagnostics = provide_diagnostics(
                uri, 
                &source.text, 
                &self
            );
            diagnostics
        } else {
            PublishDiagnosticsParams {
                uri,
                diagnostics: Vec::new(),
                version: None,
            }
        }
    }

    pub fn did_change(&self, params: DidChangeTextDocumentParams) {
        let path_string = from_uri_to_escape_path_string(&params.text_document.uri).unwrap();

        if let Some(source) = self.srcs.get_source(&path_string) {
            let mut source = source.write().unwrap();

            // 根据输入的 change 动态更新对应的代码的文本片段
            for change in params.content_changes {
                if change.range.is_none() {
                    source.text = Rope::from_str(&change.text);
                } else {
                    source.text.apply_change(&change);
                }
                source.last_change_range = change.range;
            }
            source.version = params.text_document.version;
            drop(source);
    
            // 唤醒解析线程
            let source_status = self.srcs.get_source_status(&path_string).unwrap();
            let (lock, cvar) = &*source_status.read().unwrap().valid_parse;
            let mut valid = lock.lock().unwrap();
            *valid = false;
            cvar.notify_all();
        }
    }

    /// 保存时触发的行为
    /// - 提供诊断信息（主要是第三方诊断器，因为 save 后磁盘上的内容就和缓冲区中的一致了）
    pub fn did_save(&self, params: DidSaveTextDocumentParams) -> PublishDiagnosticsParams {
        let uri = params.text_document.uri;
        let path_string = from_uri_to_escape_path_string(&uri).unwrap();

        if let Some(source) = self.srcs.get_source(&path_string) {
            let source = source.read().unwrap();
            provide_diagnostics(
                uri,
                &source.text,
                &self
            )
        } else {
            PublishDiagnosticsParams {
                uri,
                diagnostics: Vec::new(),
                version: None,
            }
        }
    }

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

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

            // hdlparam
            {
                self.srcs.hdl_param.delete_file(&path_string);
            }

            // 文本缓冲器
            {
                let mut sources = self.srcs.sources.write().unwrap();
                sources.remove(&path_string);
            }

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

            // vhdl
            {
                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 {
    /// 文件的 uri
    pub uri: Url,
    /// 代码文本信息
    pub text: Rope,
    /// 版本号
    pub version: i32,
    /// 是否已经完成至少一次解析，用于在初始化相关的函数中使用
    pub finish_at_least_once: bool,
    /// 用于在解析失败时恢复解析的量
    pub last_change_range: Option<Range>,
}

/// file metadata, including whether or not the syntax tree is up to date
pub struct SourceStatus {
    /// 当前解析的文件的路径
    pub path: String,
    /// 用于进行控制的锁
    pub valid_parse: Arc<(Mutex<bool>, Condvar)>,
    /// 解析当前文件的线程句柄
    #[allow(unused)]
    pub parse_handle: JoinHandle<()>,
}

pub enum AstLike {
    Svlog(SyntaxTree),
    Vhdl(DesignFile)
}

/// The Sources struct manages all source files
pub struct Sources {
    // 用于存储后端中的前端的文本缓冲区的备份
    pub sources: Arc<RwLock<HashMap<String, Arc<RwLock<Source>>>>>,
    // 存储类似于线程句柄等数据的结构
    pub sources_status: Arc<RwLock<HashMap<String, Arc<RwLock<SourceStatus>>>>>,
    /// 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 {
            sources: Arc::new(RwLock::new(HashMap::new())),
            sources_status: Arc::new(RwLock::new(HashMap::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::new())),
            lsp_configuration: Arc::new(RwLock::new(HashMap::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_hdl_file(
                    fake_path,
                    template.fast,
                    sv_parser::common::ParseResult::new(),
                    None
                );
                primitive_text_handle.update_text(&name, &template.text);
            }
        }
    }

    /// 判断当前文本缓冲器中是否存在指定路径的文件的备份
    pub fn contain_source(&self, path_string: &str) -> bool {
        let sources = self.sources.read().unwrap();
        sources.contains_key(path_string)
    }

    pub fn init_vhdl_project(&self, extension_path: &str) {
        let project_handle = self.vhdl_project.clone();
        let mut global_project = project_handle.write().unwrap();
        match &mut *global_project {
            Some(_) => (),
            None => {
                let std_cfg_path = match PathBuf::from_str(&(extension_path.to_string() + "/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 mut messages = Vec::new();
                        let mut project = Project::from_config(std_config.clone(), &mut messages);
                        project.analyse();
                        let config_file_strs = Vec::new();
                        *global_project = Some(VhdlProject { project, std_config, config_file_strs });
                    }
                    Err(e) => info!("error happen in <init_vhdl_project>: Can't load standard vhdl lib from {std_cfg_path:#?} because {e:#?}")
                }
            }
        }
    }

    /// 增加一个 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_parse_handle = valid_parse.clone();

        let mut sources = self.sources.write().unwrap();

        // 为新加入的文件构建后端文本缓冲器副本
        let source_handle = Arc::new(RwLock::new(Source {
            uri: doc.uri.clone(),
            text: Rope::from_str(&doc.text),
            version: doc.version,
            finish_at_least_once: false,
            last_change_range: None,
        }));

        let parse_loop_used_source_handle = source_handle.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 configuration = server.configuration.clone();
        let uri = doc.uri.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();

        // 用于进行 fast 的同步（和 request 那边的同步）
        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);

        // 创建一个解析线程
        let parse_handle = thread::spawn(move || {
            // TODO: 检查这里
            let (ref lock, ref cvar) = *valid_parse_handle;
            
            loop {
                info!("do parse in {:?}, language_id: {:?}", uri.to_string(), language_id);

                // 此时 update fast 的地方为 write 会进行阻塞
                {
                    let _unused = fast_lock.read().unwrap();
                    // 从内存中直接获取增量更新系统维护的代码文本
                    let file = parse_loop_used_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(
                                &configuration,
                                &parse_loop_used_source_handle,
                                &scope_handle,
                                &project_handle,
                                &hdl_param_handle,
                                &text,
                                uri,
                            );
                        },
                        "verilog" | "systemverilog" => {
                            sv_parser_pipeline(
                                &configuration,
                                &parse_loop_used_source_handle,
                                &scope_handle,
                                &hdl_param_handle,
                                &text,
                                uri,
                                range,
                                &inc_dirs.read().unwrap()
                            );
                        },
                        _ => {}
                    }
                }

                // 下方基于消费者-生产者模型进行控制
                // lock 会尝试去获取互斥锁，如果当前持有互斥锁的线程发生了 panic，则当前 unwrap 操作会失败
                let mut valid = lock.lock().unwrap();
                *valid = true;
                // 唤醒所有正在等待条件变量的线程，即所有被下方 cvar.wait 阻塞的线程将被激活
                cvar.notify_all();
                while *valid {
                    valid = cvar.wait(valid).unwrap();
                }
            }
        });

        // 将新的文件缓冲区数据结构加入 sources 和 status 中
        sources.insert(path_string.to_string(), source_handle);

        let mut source_status = self.sources_status.write().unwrap();
        let status_handle = Arc::new(RwLock::new(SourceStatus {
            path: path_string.to_string(),
            valid_parse,
            parse_handle,
        }));
        source_status.insert(path_string.to_string(), status_handle);
    }

    /// 输入路径，获得路径对应的文件的文本缓冲器对象 source
    pub fn get_source(&self, path_string: &str) -> Option<Arc<RwLock<Source>>> {
        let sources = self.sources.read().unwrap();
        if let Some(source_handle) = sources.get(path_string) {
            return Some(source_handle.clone());
        }

        None
    }

    /// 输入路径，获得路径对应的文件的文本缓冲器对象 source 的运行时状态
    pub fn get_source_status(&self, path_string: &str) -> Option<Arc<RwLock<SourceStatus>>> {
        let source_status = self.sources_status.read().unwrap();
        if let Some(status_handle) = source_status.get(path_string) {
            return Some(status_handle.clone());
        }

        None
    }

    /// 等待解析线程创建完成 ？
    pub fn wait_parse_ready(&self, path_string: &str, wait_valid: bool) {
        if let Some(source_handle) = self.get_source(path_string) {
            let source = source_handle.read().unwrap();
            if !source.finish_at_least_once || wait_valid {
                drop(source);
                let source_status_handle = self.get_source_status(path_string).unwrap(); // status 和 source 是同步创建的，要有一起有
                let (lock, cvar) = &*source_status_handle.read().unwrap().valid_parse;
                let mut valid = lock.lock().unwrap();
                // 解析线程一轮解析结束后， valid 会变为 true，结束循环
                while !*valid {
                    valid = cvar.wait(valid).unwrap();
                }
            }
        }
    }

    /// 根据输入 token，计算当前
    pub fn get_completions(
        &self,
        token: &str,
        byte_idx: usize,
        url: &Url,
    ) -> Option<CompletionList> {
        Some(CompletionList {
            is_incomplete: false,
            items: self
                .scope_tree
                .read()
                .ok()?
                .as_ref()?
                .get_completion(token, byte_idx, url),
        })
    }


    #[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
    }

    /// 同时从 fast 和 primitives 里面找 module
    /// 在内部判断一个 module 是否存在时会用到
    /// - name: 模块的名字
    pub fn contains_module(&self, name: &str) -> bool {
        if let Some(_) = self.hdl_param.find_module_by_name(name) {
            return true;
        }

        // 从 primitives 里面寻找
        let primitive_text = self.primitive_text.clone();
        let primitive_map = primitive_text.name_to_text.read().unwrap();
        primitive_map.contains_key(name)
    }
}


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

fn replace_substring(rope: Rope, substring: &str) -> Rope {
    let text = rope.to_string();
    let replaced_text = text.replace(substring, &" ".repeat(substring.len()));
    Rope::from(replaced_text)
}

/// 更加稳定地解析 sv 和 v
/// 支持遇到错误进行自动修复，然后再解析
pub fn recovery_sv_parse(
    doc: &Rope,
    uri: &Url,
    last_change_range: &Option<Range>,
    inc_paths: &[PathBuf],
    allow_incomplete: bool,
) -> Option<(SyntaxTree, sv_parser::common::ParseResult)> {
    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();

    // TODO: find how to fix it
    // remove `reset all to avoid parse error
    text = replace_substring(text, "`resetall");

    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));
        }
    };

    // 最多解析 50 次
    while i < parse_iterations && i < 50 {
        i += 1;
        match make_ast_from_svlog_code(
            &text.to_string(),
            uri.to_file_path().unwrap(),
            &defines,
            &includes,
            true,
            allow_incomplete
        ) {
            Ok((syntax_tree, parse_result)) => {
                return Some((syntax_tree, parse_result));
            }
            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)) => {
                            info!("meet preprocess error, text: {text:?}");

                            // 把出错的地方替换成空格
                            // 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<LspConfiguration>>,
    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 escape_path_string = from_uri_to_escape_path_string(uri).unwrap();
    let escape_path = PathBuf::from_str(&escape_path_string).unwrap();

    let ast = recovery_sv_parse_with_retry(
        doc,
        uri,
        last_change_range,
        include_dirs
    );

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

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

    // 加入语法树 & 更新 fast
    if let Some((syntax_tree, parse_result)) = ast {
        if let Ok(fast) = make_fast_from_syntaxtree(&syntax_tree, &escape_path) {
            info!("update parse_result: {:?}", parse_result);
            hdl_param_handle.update_hdl_file(
                escape_path_string.to_string(),
                fast,
                parse_result,
                Some(AstLike::Svlog(syntax_tree))
            );
        }

        file.finish_at_least_once = true;
    } else {
        file.finish_at_least_once = false;
    }
    // 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<LspConfiguration>>,
    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 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.clone() + "/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);

    let mut global_project = project_handle.write().unwrap();
    match &mut *global_project {
        Some(vhdl_project) => {
            let mut source = source_handle.write().unwrap();
            let text = doc.to_string();
            let mut scope_tree = if let Some(design_file) = vhdl_parse_str(&escape_path, &text) {
                let arch_and_entity = vhdl_project.project.get_analyzed_units(&escape_path);
                if let Some(mut fast) = make_fast_from_units(arch_and_entity) {
                    // 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_hdl_file(
                        escape_path_string.to_string(),
                        fast.clone(),
                        sv_parser::common::ParseResult::new(),
                        Some(AstLike::Vhdl(design_file))
                    );
                    let scope_tree = get_scopes_from_vhdl_fast(&fast, doc, uri);
                    scope_tree
                } else {
                    None
                }
            } else {
                source.finish_at_least_once = false;
                None
            };
            drop(source);


            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);
        }
        _ => ()
    }
}

//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");
    }
}
