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

#[allow(unused)]
use log::info;
use tower_lsp::lsp_types::*;
use crate::{server::LspServer, utils::{from_lsp_pos, from_uri_to_escape_path_string, get_definition_token, srcpos_to_location, to_escape_path}};

pub fn goto_vhdl_definition(server: &LspServer, params: &GotoDefinitionParams) -> Option<GotoDefinitionResponse> {
    let uri = &params.text_document_position_params.text_document.uri;
    let pos = params.text_document_position_params.position;

    let path_string = from_uri_to_escape_path_string(uri).unwrap();

    // 等待解析完成
    server.srcs.wait_parse_ready(&path_string, false);
    let source = server.srcs.get_source(&path_string)?;
    let source = source.read().ok()?;

    let line_text = source.text.line(pos.line as usize);

    #[allow(unused)]
    let token: String = get_definition_token(&line_text, pos);

    let project = server.srcs.vhdl_project.read().ok()?;
    let global_project = project.as_ref().unwrap();

    let path = match PathBuf::from_str(uri.path()) {
        Ok(path) => path,
        Err(error) => {
            info!("error happen in vhdl <hover>: {:?}", error);
            return None;
        }
    };
    let escape_path = to_escape_path(&path);
    let project_file = escape_path.as_path();
    let Some(source) = global_project.project.get_source(project_file) else {
        return None
    };

    let ents = global_project.project.find_implementation(&source, from_lsp_pos(pos));

    Some(GotoDefinitionResponse::Array(
        ents.into_iter()
            .filter_map(|ent| ent.decl_pos().map(srcpos_to_location))
            .collect(),
    ))

    // // match include
    // if let Some(definition) = goto_include_definition(doc, &line_text, pos) {
    //     return Some(definition);
    // }

    // // match macro
    // if let Some(definition) = goto_macro_definition(server, &line_text, pos) {
    //     return Some(definition);
    // }

    // match instance

    // let scope_tree = server.srcs.scope_tree.read().ok()?;

    // // match position port & param
    // if let Some(definition) = goto_position_port_param_definition(server, &line_text, doc, pos) {
    //     return Some(definition);
    // }

    // // match module name
    // if let Some(definition) = goto_module_declaration_definition(server, &token) {
    //     return Some(definition);
    // }

    // let byte_idx = file.text.pos_to_byte(&pos);
    // let global_scope = scope_tree.as_ref()?;
    // let def = global_scope.get_definition(&token, byte_idx, doc)?;
    
    // let def_pos = file.text.byte_to_pos(def.byte_idx());
    // Some(GotoDefinitionResponse::Scalar(Location::new(
    //     def.url(),
    //     Range::new(def_pos, def_pos),
    // )))
}